claude-mpm 4.7.4__py3-none-any.whl → 4.18.2__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 (308) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +118 -0
  3. claude_mpm/agents/BASE_ENGINEER.md +286 -0
  4. claude_mpm/agents/BASE_PM.md +106 -1
  5. claude_mpm/agents/OUTPUT_STYLE.md +329 -11
  6. claude_mpm/agents/PM_INSTRUCTIONS.md +397 -459
  7. claude_mpm/agents/agent_loader.py +17 -5
  8. claude_mpm/agents/frontmatter_validator.py +284 -253
  9. claude_mpm/agents/templates/README.md +465 -0
  10. claude_mpm/agents/templates/agent-manager.json +4 -1
  11. claude_mpm/agents/templates/agentic-coder-optimizer.json +13 -3
  12. claude_mpm/agents/templates/api_qa.json +11 -2
  13. claude_mpm/agents/templates/circuit_breakers.md +638 -0
  14. claude_mpm/agents/templates/clerk-ops.json +12 -2
  15. claude_mpm/agents/templates/code_analyzer.json +8 -2
  16. claude_mpm/agents/templates/content-agent.json +358 -0
  17. claude_mpm/agents/templates/dart_engineer.json +15 -2
  18. claude_mpm/agents/templates/data_engineer.json +15 -2
  19. claude_mpm/agents/templates/documentation.json +10 -2
  20. claude_mpm/agents/templates/engineer.json +21 -1
  21. claude_mpm/agents/templates/gcp_ops_agent.json +12 -2
  22. claude_mpm/agents/templates/git_file_tracking.md +584 -0
  23. claude_mpm/agents/templates/golang_engineer.json +270 -0
  24. claude_mpm/agents/templates/imagemagick.json +4 -1
  25. claude_mpm/agents/templates/java_engineer.json +346 -0
  26. claude_mpm/agents/templates/local_ops_agent.json +1227 -6
  27. claude_mpm/agents/templates/memory_manager.json +4 -1
  28. claude_mpm/agents/templates/nextjs_engineer.json +141 -133
  29. claude_mpm/agents/templates/ops.json +12 -2
  30. claude_mpm/agents/templates/php-engineer.json +270 -174
  31. claude_mpm/agents/templates/pm_examples.md +474 -0
  32. claude_mpm/agents/templates/pm_red_flags.md +240 -0
  33. claude_mpm/agents/templates/product_owner.json +338 -0
  34. claude_mpm/agents/templates/project_organizer.json +14 -4
  35. claude_mpm/agents/templates/prompt-engineer.json +13 -2
  36. claude_mpm/agents/templates/python_engineer.json +174 -81
  37. claude_mpm/agents/templates/qa.json +11 -2
  38. claude_mpm/agents/templates/react_engineer.json +16 -3
  39. claude_mpm/agents/templates/refactoring_engineer.json +12 -2
  40. claude_mpm/agents/templates/research.json +34 -21
  41. claude_mpm/agents/templates/response_format.md +583 -0
  42. claude_mpm/agents/templates/ruby-engineer.json +129 -192
  43. claude_mpm/agents/templates/rust_engineer.json +270 -0
  44. claude_mpm/agents/templates/security.json +10 -2
  45. claude_mpm/agents/templates/svelte-engineer.json +225 -0
  46. claude_mpm/agents/templates/ticketing.json +10 -2
  47. claude_mpm/agents/templates/typescript_engineer.json +116 -125
  48. claude_mpm/agents/templates/validation_templates.md +312 -0
  49. claude_mpm/agents/templates/vercel_ops_agent.json +12 -2
  50. claude_mpm/agents/templates/version_control.json +12 -2
  51. claude_mpm/agents/templates/web_qa.json +11 -2
  52. claude_mpm/agents/templates/web_ui.json +15 -2
  53. claude_mpm/cli/__init__.py +34 -614
  54. claude_mpm/cli/commands/agent_manager.py +25 -12
  55. claude_mpm/cli/commands/agent_state_manager.py +186 -0
  56. claude_mpm/cli/commands/agents.py +235 -148
  57. claude_mpm/cli/commands/agents_detect.py +380 -0
  58. claude_mpm/cli/commands/agents_recommend.py +309 -0
  59. claude_mpm/cli/commands/aggregate.py +7 -3
  60. claude_mpm/cli/commands/analyze.py +9 -4
  61. claude_mpm/cli/commands/analyze_code.py +7 -2
  62. claude_mpm/cli/commands/auto_configure.py +570 -0
  63. claude_mpm/cli/commands/config.py +47 -13
  64. claude_mpm/cli/commands/configure.py +419 -1571
  65. claude_mpm/cli/commands/configure_agent_display.py +261 -0
  66. claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
  67. claude_mpm/cli/commands/configure_hook_manager.py +225 -0
  68. claude_mpm/cli/commands/configure_models.py +18 -0
  69. claude_mpm/cli/commands/configure_navigation.py +167 -0
  70. claude_mpm/cli/commands/configure_paths.py +104 -0
  71. claude_mpm/cli/commands/configure_persistence.py +254 -0
  72. claude_mpm/cli/commands/configure_startup_manager.py +646 -0
  73. claude_mpm/cli/commands/configure_template_editor.py +497 -0
  74. claude_mpm/cli/commands/configure_validators.py +73 -0
  75. claude_mpm/cli/commands/local_deploy.py +537 -0
  76. claude_mpm/cli/commands/memory.py +54 -20
  77. claude_mpm/cli/commands/mpm_init.py +585 -196
  78. claude_mpm/cli/commands/mpm_init_handler.py +37 -3
  79. claude_mpm/cli/commands/search.py +170 -4
  80. claude_mpm/cli/commands/upgrade.py +152 -0
  81. claude_mpm/cli/executor.py +202 -0
  82. claude_mpm/cli/helpers.py +105 -0
  83. claude_mpm/cli/interactive/__init__.py +3 -0
  84. claude_mpm/cli/interactive/skills_wizard.py +491 -0
  85. claude_mpm/cli/parsers/__init__.py +7 -1
  86. claude_mpm/cli/parsers/agents_parser.py +9 -0
  87. claude_mpm/cli/parsers/auto_configure_parser.py +245 -0
  88. claude_mpm/cli/parsers/base_parser.py +110 -3
  89. claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
  90. claude_mpm/cli/parsers/mpm_init_parser.py +65 -5
  91. claude_mpm/cli/shared/output_formatters.py +28 -19
  92. claude_mpm/cli/startup.py +481 -0
  93. claude_mpm/cli/utils.py +52 -1
  94. claude_mpm/commands/mpm-agents-detect.md +168 -0
  95. claude_mpm/commands/mpm-agents-recommend.md +214 -0
  96. claude_mpm/commands/mpm-agents.md +75 -1
  97. claude_mpm/commands/mpm-auto-configure.md +217 -0
  98. claude_mpm/commands/mpm-help.md +163 -0
  99. claude_mpm/commands/mpm-init.md +148 -3
  100. claude_mpm/commands/mpm-version.md +113 -0
  101. claude_mpm/commands/mpm.md +1 -0
  102. claude_mpm/config/agent_config.py +2 -2
  103. claude_mpm/config/model_config.py +428 -0
  104. claude_mpm/constants.py +1 -0
  105. claude_mpm/core/base_service.py +13 -12
  106. claude_mpm/core/enums.py +452 -0
  107. claude_mpm/core/factories.py +1 -1
  108. claude_mpm/core/instruction_reinforcement_hook.py +2 -1
  109. claude_mpm/core/interactive_session.py +9 -3
  110. claude_mpm/core/log_manager.py +2 -0
  111. claude_mpm/core/logging_config.py +6 -2
  112. claude_mpm/core/oneshot_session.py +8 -4
  113. claude_mpm/core/optimized_agent_loader.py +3 -3
  114. claude_mpm/core/output_style_manager.py +12 -192
  115. claude_mpm/core/service_registry.py +5 -1
  116. claude_mpm/core/types.py +2 -9
  117. claude_mpm/core/typing_utils.py +7 -6
  118. claude_mpm/dashboard/static/js/dashboard.js +0 -14
  119. claude_mpm/dashboard/templates/index.html +3 -41
  120. claude_mpm/hooks/__init__.py +20 -0
  121. claude_mpm/hooks/claude_hooks/event_handlers.py +4 -2
  122. claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
  123. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +23 -2
  124. claude_mpm/hooks/failure_learning/__init__.py +60 -0
  125. claude_mpm/hooks/failure_learning/failure_detection_hook.py +235 -0
  126. claude_mpm/hooks/failure_learning/fix_detection_hook.py +217 -0
  127. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +286 -0
  128. claude_mpm/hooks/instruction_reinforcement.py +7 -2
  129. claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
  130. claude_mpm/hooks/kuzu_memory_hook.py +37 -12
  131. claude_mpm/hooks/kuzu_response_hook.py +183 -0
  132. claude_mpm/models/resume_log.py +340 -0
  133. claude_mpm/services/agents/__init__.py +18 -5
  134. claude_mpm/services/agents/auto_config_manager.py +796 -0
  135. claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
  136. claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
  137. claude_mpm/services/agents/deployment/agent_validator.py +17 -1
  138. claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
  139. claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
  140. claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
  141. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
  142. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
  143. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
  144. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
  145. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
  146. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
  147. claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
  148. claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
  149. claude_mpm/services/agents/local_template_manager.py +1 -1
  150. claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
  151. claude_mpm/services/agents/observers.py +547 -0
  152. claude_mpm/services/agents/recommender.py +568 -0
  153. claude_mpm/services/agents/registry/modification_tracker.py +5 -2
  154. claude_mpm/services/command_handler_service.py +11 -5
  155. claude_mpm/services/core/__init__.py +33 -1
  156. claude_mpm/services/core/interfaces/__init__.py +90 -3
  157. claude_mpm/services/core/interfaces/agent.py +184 -0
  158. claude_mpm/services/core/interfaces/health.py +172 -0
  159. claude_mpm/services/core/interfaces/model.py +281 -0
  160. claude_mpm/services/core/interfaces/process.py +372 -0
  161. claude_mpm/services/core/interfaces/project.py +121 -0
  162. claude_mpm/services/core/interfaces/restart.py +307 -0
  163. claude_mpm/services/core/interfaces/stability.py +260 -0
  164. claude_mpm/services/core/memory_manager.py +11 -24
  165. claude_mpm/services/core/models/__init__.py +79 -0
  166. claude_mpm/services/core/models/agent_config.py +381 -0
  167. claude_mpm/services/core/models/health.py +162 -0
  168. claude_mpm/services/core/models/process.py +235 -0
  169. claude_mpm/services/core/models/restart.py +302 -0
  170. claude_mpm/services/core/models/stability.py +264 -0
  171. claude_mpm/services/core/models/toolchain.py +306 -0
  172. claude_mpm/services/core/path_resolver.py +23 -7
  173. claude_mpm/services/diagnostics/__init__.py +2 -2
  174. claude_mpm/services/diagnostics/checks/agent_check.py +25 -24
  175. claude_mpm/services/diagnostics/checks/claude_code_check.py +24 -23
  176. claude_mpm/services/diagnostics/checks/common_issues_check.py +25 -24
  177. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -23
  178. claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
  179. claude_mpm/services/diagnostics/checks/installation_check.py +30 -29
  180. claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
  181. claude_mpm/services/diagnostics/checks/mcp_check.py +50 -36
  182. claude_mpm/services/diagnostics/checks/mcp_services_check.py +38 -33
  183. claude_mpm/services/diagnostics/checks/monitor_check.py +23 -22
  184. claude_mpm/services/diagnostics/checks/startup_log_check.py +9 -8
  185. claude_mpm/services/diagnostics/diagnostic_runner.py +6 -5
  186. claude_mpm/services/diagnostics/doctor_reporter.py +28 -25
  187. claude_mpm/services/diagnostics/models.py +19 -24
  188. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
  189. claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
  190. claude_mpm/services/infrastructure/monitoring/base.py +5 -13
  191. claude_mpm/services/infrastructure/monitoring/network.py +7 -6
  192. claude_mpm/services/infrastructure/monitoring/process.py +13 -12
  193. claude_mpm/services/infrastructure/monitoring/resources.py +7 -6
  194. claude_mpm/services/infrastructure/monitoring/service.py +16 -15
  195. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  196. claude_mpm/services/local_ops/__init__.py +163 -0
  197. claude_mpm/services/local_ops/crash_detector.py +257 -0
  198. claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
  199. claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
  200. claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
  201. claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
  202. claude_mpm/services/local_ops/health_manager.py +430 -0
  203. claude_mpm/services/local_ops/log_monitor.py +396 -0
  204. claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
  205. claude_mpm/services/local_ops/process_manager.py +595 -0
  206. claude_mpm/services/local_ops/resource_monitor.py +331 -0
  207. claude_mpm/services/local_ops/restart_manager.py +401 -0
  208. claude_mpm/services/local_ops/restart_policy.py +387 -0
  209. claude_mpm/services/local_ops/state_manager.py +372 -0
  210. claude_mpm/services/local_ops/unified_manager.py +600 -0
  211. claude_mpm/services/mcp_config_manager.py +9 -4
  212. claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
  213. claude_mpm/services/mcp_gateway/core/base.py +18 -31
  214. claude_mpm/services/mcp_gateway/main.py +30 -0
  215. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +206 -32
  216. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
  217. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +25 -5
  218. claude_mpm/services/mcp_service_verifier.py +1 -1
  219. claude_mpm/services/memory/failure_tracker.py +563 -0
  220. claude_mpm/services/memory_hook_service.py +165 -4
  221. claude_mpm/services/model/__init__.py +147 -0
  222. claude_mpm/services/model/base_provider.py +365 -0
  223. claude_mpm/services/model/claude_provider.py +412 -0
  224. claude_mpm/services/model/model_router.py +453 -0
  225. claude_mpm/services/model/ollama_provider.py +415 -0
  226. claude_mpm/services/monitor/daemon_manager.py +3 -2
  227. claude_mpm/services/monitor/handlers/dashboard.py +2 -1
  228. claude_mpm/services/monitor/handlers/hooks.py +2 -1
  229. claude_mpm/services/monitor/management/lifecycle.py +3 -2
  230. claude_mpm/services/monitor/server.py +2 -1
  231. claude_mpm/services/project/__init__.py +23 -0
  232. claude_mpm/services/project/detection_strategies.py +719 -0
  233. claude_mpm/services/project/toolchain_analyzer.py +581 -0
  234. claude_mpm/services/self_upgrade_service.py +342 -0
  235. claude_mpm/services/session_management_service.py +3 -2
  236. claude_mpm/services/session_manager.py +205 -1
  237. claude_mpm/services/shared/async_service_base.py +16 -27
  238. claude_mpm/services/shared/lifecycle_service_base.py +1 -14
  239. claude_mpm/services/socketio/handlers/__init__.py +5 -2
  240. claude_mpm/services/socketio/handlers/hook.py +13 -2
  241. claude_mpm/services/socketio/handlers/registry.py +4 -2
  242. claude_mpm/services/socketio/server/main.py +10 -8
  243. claude_mpm/services/subprocess_launcher_service.py +14 -5
  244. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +8 -7
  245. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +6 -5
  246. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +8 -7
  247. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +7 -6
  248. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +5 -4
  249. claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
  250. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
  251. claude_mpm/services/unified/deployment_strategies/local.py +6 -5
  252. claude_mpm/services/unified/deployment_strategies/utils.py +6 -5
  253. claude_mpm/services/unified/deployment_strategies/vercel.py +7 -6
  254. claude_mpm/services/unified/interfaces.py +3 -1
  255. claude_mpm/services/unified/unified_analyzer.py +14 -10
  256. claude_mpm/services/unified/unified_config.py +2 -1
  257. claude_mpm/services/unified/unified_deployment.py +9 -4
  258. claude_mpm/services/version_service.py +104 -1
  259. claude_mpm/skills/__init__.py +21 -0
  260. claude_mpm/skills/bundled/__init__.py +6 -0
  261. claude_mpm/skills/bundled/api-documentation.md +393 -0
  262. claude_mpm/skills/bundled/async-testing.md +571 -0
  263. claude_mpm/skills/bundled/code-review.md +143 -0
  264. claude_mpm/skills/bundled/database-migration.md +199 -0
  265. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  266. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  267. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  268. claude_mpm/skills/bundled/git-workflow.md +414 -0
  269. claude_mpm/skills/bundled/imagemagick.md +204 -0
  270. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  271. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  272. claude_mpm/skills/bundled/pdf.md +141 -0
  273. claude_mpm/skills/bundled/performance-profiling.md +567 -0
  274. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  275. claude_mpm/skills/bundled/security-scanning.md +327 -0
  276. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  277. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  278. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  279. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  280. claude_mpm/skills/bundled/xlsx.md +157 -0
  281. claude_mpm/skills/registry.py +286 -0
  282. claude_mpm/skills/skill_manager.py +310 -0
  283. claude_mpm/storage/state_storage.py +15 -15
  284. claude_mpm/tools/code_tree_analyzer.py +177 -141
  285. claude_mpm/tools/code_tree_events.py +4 -2
  286. claude_mpm/utils/agent_dependency_loader.py +40 -20
  287. claude_mpm/utils/display_helper.py +260 -0
  288. claude_mpm/utils/git_analyzer.py +407 -0
  289. claude_mpm/utils/robust_installer.py +73 -19
  290. {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/METADATA +129 -12
  291. {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/RECORD +295 -193
  292. claude_mpm/dashboard/static/css/code-tree.css +0 -1639
  293. claude_mpm/dashboard/static/index-hub-backup.html +0 -713
  294. claude_mpm/dashboard/static/js/components/code-tree/tree-breadcrumb.js +0 -353
  295. claude_mpm/dashboard/static/js/components/code-tree/tree-constants.js +0 -235
  296. claude_mpm/dashboard/static/js/components/code-tree/tree-search.js +0 -409
  297. claude_mpm/dashboard/static/js/components/code-tree/tree-utils.js +0 -435
  298. claude_mpm/dashboard/static/js/components/code-tree.js +0 -5869
  299. claude_mpm/dashboard/static/js/components/code-viewer.js +0 -1386
  300. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
  301. claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
  302. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
  303. claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
  304. claude_mpm/services/project/analyzer_refactored.py +0 -450
  305. {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/WHEEL +0 -0
  306. {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/entry_points.txt +0 -0
  307. {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/licenses/LICENSE +0 -0
  308. {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,264 @@
1
+ """
2
+ Stability Monitoring Data Models for Claude MPM Framework
3
+ ===========================================================
4
+
5
+ WHY: This module defines data structures for stability monitoring operations,
6
+ including memory leak detection, log pattern matching, and resource usage tracking.
7
+
8
+ DESIGN DECISION: Uses dataclasses for immutability and type safety. Provides
9
+ clear data structures for proactive monitoring and crash prevention.
10
+
11
+ ARCHITECTURE:
12
+ - MemoryTrend: Memory usage trend analysis with leak detection
13
+ - LogPatternMatch: Log pattern match with severity and context
14
+ - ResourceUsage: Comprehensive resource usage snapshot
15
+ """
16
+
17
+ from dataclasses import asdict, dataclass, field
18
+ from datetime import datetime
19
+ from typing import Any, Dict, List
20
+
21
+
22
+ @dataclass
23
+ class MemoryTrend:
24
+ """
25
+ Memory usage trend analysis result.
26
+
27
+ WHY: Provides structured data for memory leak detection, including
28
+ historical measurements, slope calculation, and leak detection status.
29
+
30
+ Attributes:
31
+ deployment_id: Unique deployment identifier
32
+ timestamps: List of measurement timestamps
33
+ memory_mb: List of memory measurements in megabytes
34
+ slope_mb_per_minute: Calculated memory growth rate (MB/minute)
35
+ is_leaking: Whether a memory leak was detected
36
+ window_size: Number of measurements in the analysis window
37
+ threshold_mb_per_minute: Leak detection threshold used
38
+ """
39
+
40
+ deployment_id: str
41
+ timestamps: List[datetime] = field(default_factory=list)
42
+ memory_mb: List[float] = field(default_factory=list)
43
+ slope_mb_per_minute: float = 0.0
44
+ is_leaking: bool = False
45
+ window_size: int = 0
46
+ threshold_mb_per_minute: float = 10.0
47
+
48
+ def to_dict(self) -> Dict[str, Any]:
49
+ """
50
+ Convert to dictionary for JSON serialization.
51
+
52
+ Returns:
53
+ Dictionary representation with datetimes converted to ISO format
54
+ """
55
+ data = asdict(self)
56
+ data["timestamps"] = [ts.isoformat() for ts in self.timestamps]
57
+ return data
58
+
59
+ @classmethod
60
+ def from_dict(cls, data: Dict[str, Any]) -> "MemoryTrend":
61
+ """
62
+ Create MemoryTrend from dictionary.
63
+
64
+ Args:
65
+ data: Dictionary from JSON deserialization
66
+
67
+ Returns:
68
+ MemoryTrend instance
69
+ """
70
+ # Convert ISO strings to datetime
71
+ if isinstance(data.get("timestamps"), list):
72
+ data["timestamps"] = [
73
+ datetime.fromisoformat(ts) if isinstance(ts, str) else ts
74
+ for ts in data["timestamps"]
75
+ ]
76
+
77
+ return cls(**data)
78
+
79
+ @property
80
+ def latest_memory_mb(self) -> float:
81
+ """Get the most recent memory measurement."""
82
+ return self.memory_mb[-1] if self.memory_mb else 0.0
83
+
84
+ @property
85
+ def oldest_memory_mb(self) -> float:
86
+ """Get the oldest memory measurement in the window."""
87
+ return self.memory_mb[0] if self.memory_mb else 0.0
88
+
89
+ @property
90
+ def time_span_minutes(self) -> float:
91
+ """Get the time span covered by the measurements in minutes."""
92
+ if len(self.timestamps) < 2:
93
+ return 0.0
94
+ delta = self.timestamps[-1] - self.timestamps[0]
95
+ return delta.total_seconds() / 60.0
96
+
97
+
98
+ @dataclass
99
+ class LogPatternMatch:
100
+ """
101
+ Result of a log pattern match.
102
+
103
+ WHY: Contains all information about a detected error pattern in logs,
104
+ enabling analysis, alerting, and debugging of issues before they cause crashes.
105
+
106
+ Attributes:
107
+ deployment_id: Unique deployment identifier
108
+ pattern: Regex pattern that matched
109
+ line: The log line that matched
110
+ timestamp: When the match was detected
111
+ severity: Error severity level (ERROR, CRITICAL, WARNING)
112
+ line_number: Line number in log file (if available)
113
+ context: Additional context lines (before/after)
114
+ """
115
+
116
+ deployment_id: str
117
+ pattern: str
118
+ line: str
119
+ timestamp: datetime = field(default_factory=datetime.now)
120
+ severity: str = "ERROR"
121
+ line_number: int = 0
122
+ context: List[str] = field(default_factory=list)
123
+
124
+ def to_dict(self) -> Dict[str, Any]:
125
+ """
126
+ Convert to dictionary for JSON serialization.
127
+
128
+ Returns:
129
+ Dictionary representation with datetime converted to ISO format
130
+ """
131
+ data = asdict(self)
132
+ data["timestamp"] = self.timestamp.isoformat()
133
+ return data
134
+
135
+ @classmethod
136
+ def from_dict(cls, data: Dict[str, Any]) -> "LogPatternMatch":
137
+ """
138
+ Create LogPatternMatch from dictionary.
139
+
140
+ Args:
141
+ data: Dictionary from JSON deserialization
142
+
143
+ Returns:
144
+ LogPatternMatch instance
145
+ """
146
+ # Convert ISO string to datetime
147
+ if isinstance(data.get("timestamp"), str):
148
+ data["timestamp"] = datetime.fromisoformat(data["timestamp"])
149
+
150
+ return cls(**data)
151
+
152
+ @property
153
+ def is_critical(self) -> bool:
154
+ """Check if this match represents a critical error."""
155
+ return self.severity == "CRITICAL"
156
+
157
+
158
+ @dataclass
159
+ class ResourceUsage:
160
+ """
161
+ Comprehensive resource usage snapshot.
162
+
163
+ WHY: Provides detailed resource consumption metrics across multiple
164
+ resource types to enable preemptive action before exhaustion.
165
+
166
+ Attributes:
167
+ deployment_id: Unique deployment identifier
168
+ file_descriptors: Current file descriptor count
169
+ max_file_descriptors: Maximum file descriptors allowed (ulimit -n)
170
+ threads: Current thread count
171
+ connections: Current network connection count
172
+ disk_free_mb: Free disk space in working directory (MB)
173
+ is_critical: Whether any resource exceeds 80% threshold
174
+ timestamp: When the measurement was taken
175
+ details: Additional resource-specific details
176
+ """
177
+
178
+ deployment_id: str
179
+ file_descriptors: int = 0
180
+ max_file_descriptors: int = 0
181
+ threads: int = 0
182
+ connections: int = 0
183
+ disk_free_mb: float = 0.0
184
+ is_critical: bool = False
185
+ timestamp: datetime = field(default_factory=datetime.now)
186
+ details: Dict[str, Any] = field(default_factory=dict)
187
+
188
+ def to_dict(self) -> Dict[str, Any]:
189
+ """
190
+ Convert to dictionary for JSON serialization.
191
+
192
+ Returns:
193
+ Dictionary representation with datetime converted to ISO format
194
+ """
195
+ data = asdict(self)
196
+ data["timestamp"] = self.timestamp.isoformat()
197
+ return data
198
+
199
+ @classmethod
200
+ def from_dict(cls, data: Dict[str, Any]) -> "ResourceUsage":
201
+ """
202
+ Create ResourceUsage from dictionary.
203
+
204
+ Args:
205
+ data: Dictionary from JSON deserialization
206
+
207
+ Returns:
208
+ ResourceUsage instance
209
+ """
210
+ # Convert ISO string to datetime
211
+ if isinstance(data.get("timestamp"), str):
212
+ data["timestamp"] = datetime.fromisoformat(data["timestamp"])
213
+
214
+ return cls(**data)
215
+
216
+ @property
217
+ def fd_usage_percent(self) -> float:
218
+ """Calculate file descriptor usage percentage."""
219
+ if self.max_file_descriptors == 0:
220
+ return 0.0
221
+ return (self.file_descriptors / self.max_file_descriptors) * 100.0
222
+
223
+ @property
224
+ def is_fd_critical(self) -> bool:
225
+ """Check if file descriptor usage is critical (>80%)."""
226
+ return self.fd_usage_percent >= 80.0 # >= instead of > for 80% exactly
227
+
228
+ def get_critical_resources(self) -> List[str]:
229
+ """
230
+ Get list of resources at critical levels.
231
+
232
+ Returns:
233
+ List of resource names exceeding 80% threshold
234
+ """
235
+ critical = []
236
+
237
+ if self.is_fd_critical:
238
+ critical.append(
239
+ f"file_descriptors ({self.file_descriptors}/{self.max_file_descriptors})"
240
+ )
241
+
242
+ # Check thread count (threshold from details if available)
243
+ thread_threshold = self.details.get("thread_threshold", 1000)
244
+ if self.threads > thread_threshold * 0.8:
245
+ critical.append(f"threads ({self.threads})")
246
+
247
+ # Check connection count (threshold from details if available)
248
+ connection_threshold = self.details.get("connection_threshold", 500)
249
+ if self.connections > connection_threshold * 0.8:
250
+ critical.append(f"connections ({self.connections})")
251
+
252
+ # Check disk space (threshold from details if available)
253
+ disk_threshold_mb = self.details.get("disk_threshold_mb", 100)
254
+ if self.disk_free_mb < disk_threshold_mb:
255
+ critical.append(f"disk_space ({self.disk_free_mb:.1f}MB free)")
256
+
257
+ return critical
258
+
259
+
260
+ __all__ = [
261
+ "LogPatternMatch",
262
+ "MemoryTrend",
263
+ "ResourceUsage",
264
+ ]
@@ -0,0 +1,306 @@
1
+ """
2
+ Toolchain Data Models for Claude MPM Framework
3
+ ==============================================
4
+
5
+ WHY: These models represent the structure of project toolchain analysis results.
6
+ They provide a standardized way to represent detected languages, frameworks,
7
+ deployment targets, and overall toolchain characteristics.
8
+
9
+ DESIGN DECISION: Uses dataclasses with field validation and default values
10
+ to ensure data consistency. Confidence levels are included to represent
11
+ uncertainty in detection. Immutable where possible to prevent accidental
12
+ modification of analysis results.
13
+
14
+ Part of TSK-0054: Auto-Configuration Feature - Phase 1
15
+ """
16
+
17
+ from dataclasses import dataclass, field
18
+ from enum import Enum
19
+ from pathlib import Path
20
+ from typing import Any, Dict, List, Optional
21
+
22
+
23
+ class ConfidenceLevel(str, Enum):
24
+ """Confidence level for detection results.
25
+
26
+ WHY: Not all detections are equally certain. This enum provides a
27
+ standardized way to communicate confidence levels to users and
28
+ enable threshold-based decision making.
29
+ """
30
+
31
+ HIGH = "high" # >80% confidence, very strong indicators
32
+ MEDIUM = "medium" # 50-80% confidence, good indicators
33
+ LOW = "low" # 20-50% confidence, weak indicators
34
+ VERY_LOW = "very_low" # <20% confidence, speculative
35
+
36
+
37
+ @dataclass(frozen=True)
38
+ class ToolchainComponent:
39
+ """Represents a component in the project's toolchain.
40
+
41
+ WHY: Toolchain components (languages, frameworks, tools) share common
42
+ attributes like name, version, and confidence. This base model enables
43
+ consistent representation across different component types.
44
+
45
+ DESIGN DECISION: Frozen dataclass to prevent modification after creation,
46
+ ensuring analysis results remain consistent. Version is optional as not
47
+ all components have detectable versions.
48
+ """
49
+
50
+ name: str
51
+ version: Optional[str] = None
52
+ confidence: ConfidenceLevel = ConfidenceLevel.MEDIUM
53
+ metadata: Dict[str, Any] = field(default_factory=dict)
54
+
55
+ def __post_init__(self):
56
+ """Validate component data after initialization."""
57
+ if not self.name or not self.name.strip():
58
+ raise ValueError("Component name cannot be empty")
59
+ if self.version is not None and not self.version.strip():
60
+ raise ValueError("Component version cannot be empty string")
61
+
62
+
63
+ @dataclass(frozen=True)
64
+ class LanguageDetection:
65
+ """Result of language detection analysis.
66
+
67
+ WHY: Projects often use multiple languages. This model captures both
68
+ primary (main codebase) and secondary (scripts, config) languages
69
+ with their relative proportions and confidence levels.
70
+
71
+ DESIGN DECISION: Includes percentage breakdown to help understand
72
+ language distribution. Confidence per language enables threshold-based
73
+ filtering of uncertain detections.
74
+ """
75
+
76
+ primary_language: str
77
+ primary_version: Optional[str] = None
78
+ primary_confidence: ConfidenceLevel = ConfidenceLevel.MEDIUM
79
+ secondary_languages: List[ToolchainComponent] = field(default_factory=list)
80
+ language_percentages: Dict[str, float] = field(default_factory=dict)
81
+
82
+ def __post_init__(self):
83
+ """Validate language detection data."""
84
+ if not self.primary_language or not self.primary_language.strip():
85
+ raise ValueError("Primary language cannot be empty")
86
+
87
+ # Validate language percentages sum to ~100% (allow small floating point error)
88
+ if self.language_percentages:
89
+ total = sum(self.language_percentages.values())
90
+ if not (99.0 <= total <= 101.0):
91
+ raise ValueError(f"Language percentages must sum to 100%, got {total}%")
92
+
93
+ @property
94
+ def all_languages(self) -> List[str]:
95
+ """Get list of all detected languages (primary + secondary)."""
96
+ languages = [self.primary_language]
97
+ languages.extend(comp.name for comp in self.secondary_languages)
98
+ return languages
99
+
100
+ @property
101
+ def high_confidence_languages(self) -> List[str]:
102
+ """Get languages detected with high confidence."""
103
+ languages = []
104
+ if self.primary_confidence == ConfidenceLevel.HIGH:
105
+ languages.append(self.primary_language)
106
+ languages.extend(
107
+ comp.name
108
+ for comp in self.secondary_languages
109
+ if comp.confidence == ConfidenceLevel.HIGH
110
+ )
111
+ return languages
112
+
113
+
114
+ @dataclass(frozen=True)
115
+ class Framework:
116
+ """Represents a detected framework or library.
117
+
118
+ WHY: Frameworks are critical for agent recommendation as different agents
119
+ specialize in different frameworks. This model captures framework identity,
120
+ version, type, and usage characteristics.
121
+
122
+ DESIGN DECISION: Includes framework type (web, testing, ORM, etc.) to
123
+ enable category-based recommendations. Popularity metric helps prioritize
124
+ agent recommendations for commonly-used frameworks.
125
+ """
126
+
127
+ name: str
128
+ version: Optional[str] = None
129
+ framework_type: Optional[str] = None # web, testing, orm, cli, etc.
130
+ confidence: ConfidenceLevel = ConfidenceLevel.MEDIUM
131
+ is_dev_dependency: bool = False
132
+ popularity_score: float = 0.0 # 0.0-1.0, higher = more popular/used
133
+ metadata: Dict[str, Any] = field(default_factory=dict)
134
+
135
+ def __post_init__(self):
136
+ """Validate framework data."""
137
+ if not self.name or not self.name.strip():
138
+ raise ValueError("Framework name cannot be empty")
139
+ if not (0.0 <= self.popularity_score <= 1.0):
140
+ raise ValueError(
141
+ f"Popularity score must be 0.0-1.0, got {self.popularity_score}"
142
+ )
143
+
144
+ @property
145
+ def display_name(self) -> str:
146
+ """Get formatted display name with version."""
147
+ if self.version:
148
+ return f"{self.name} {self.version}"
149
+ return self.name
150
+
151
+
152
+ @dataclass(frozen=True)
153
+ class DeploymentTarget:
154
+ """Represents the detected deployment target environment.
155
+
156
+ WHY: Deployment target affects agent recommendations (e.g., DevOps agents
157
+ for Kubernetes, serverless agents for Lambda). This model captures the
158
+ deployment platform and configuration details.
159
+
160
+ DESIGN DECISION: Includes target type (cloud, container, serverless, etc.)
161
+ and platform-specific configuration. Confidence level enables fallback
162
+ to generic recommendations when deployment target is unclear.
163
+ """
164
+
165
+ target_type: str # cloud, container, serverless, on-premise, edge
166
+ platform: Optional[str] = None # aws, gcp, azure, kubernetes, docker, etc.
167
+ configuration: Dict[str, Any] = field(default_factory=dict)
168
+ confidence: ConfidenceLevel = ConfidenceLevel.MEDIUM
169
+ requires_ops_agent: bool = False
170
+ metadata: Dict[str, Any] = field(default_factory=dict)
171
+
172
+ def __post_init__(self):
173
+ """Validate deployment target data."""
174
+ valid_types = {"cloud", "container", "serverless", "on-premise", "edge"}
175
+ if self.target_type not in valid_types:
176
+ raise ValueError(
177
+ f"Invalid target_type '{self.target_type}'. "
178
+ f"Must be one of: {valid_types}"
179
+ )
180
+
181
+ @property
182
+ def display_name(self) -> str:
183
+ """Get formatted display name."""
184
+ if self.platform:
185
+ return f"{self.target_type} ({self.platform})"
186
+ return self.target_type
187
+
188
+
189
+ @dataclass
190
+ class ToolchainAnalysis:
191
+ """Complete toolchain analysis result.
192
+
193
+ WHY: This is the primary output of toolchain analysis, aggregating all
194
+ detected components into a single structure. It provides a complete
195
+ picture of the project's technical stack.
196
+
197
+ DESIGN DECISION: Not frozen to allow caching and updating of analysis
198
+ results. Includes project_path for reference and validation. Provides
199
+ convenience methods for common queries (e.g., has framework, get languages).
200
+ """
201
+
202
+ project_path: Path
203
+ language_detection: LanguageDetection
204
+ frameworks: List[Framework] = field(default_factory=list)
205
+ deployment_target: Optional[DeploymentTarget] = None
206
+ build_tools: List[ToolchainComponent] = field(default_factory=list)
207
+ package_managers: List[ToolchainComponent] = field(default_factory=list)
208
+ development_tools: List[ToolchainComponent] = field(default_factory=list)
209
+ overall_confidence: ConfidenceLevel = ConfidenceLevel.MEDIUM
210
+ analysis_timestamp: Optional[float] = None
211
+ metadata: Dict[str, Any] = field(default_factory=dict)
212
+
213
+ def __post_init__(self):
214
+ """Validate toolchain analysis data."""
215
+ if not self.project_path.exists():
216
+ raise ValueError(f"Project path does not exist: {self.project_path}")
217
+ if not self.project_path.is_dir():
218
+ raise ValueError(f"Project path is not a directory: {self.project_path}")
219
+
220
+ def has_framework(self, framework_name: str) -> bool:
221
+ """Check if a specific framework is detected."""
222
+ return any(fw.name.lower() == framework_name.lower() for fw in self.frameworks)
223
+
224
+ def get_framework(self, framework_name: str) -> Optional[Framework]:
225
+ """Get framework by name (case-insensitive)."""
226
+ for fw in self.frameworks:
227
+ if fw.name.lower() == framework_name.lower():
228
+ return fw
229
+ return None
230
+
231
+ def get_frameworks_by_type(self, framework_type: str) -> List[Framework]:
232
+ """Get all frameworks of a specific type."""
233
+ return [
234
+ fw
235
+ for fw in self.frameworks
236
+ if fw.framework_type and fw.framework_type.lower() == framework_type.lower()
237
+ ]
238
+
239
+ @property
240
+ def primary_language(self) -> str:
241
+ """Get the primary language detected."""
242
+ return self.language_detection.primary_language
243
+
244
+ @property
245
+ def all_languages(self) -> List[str]:
246
+ """Get all detected languages."""
247
+ return self.language_detection.all_languages
248
+
249
+ @property
250
+ def web_frameworks(self) -> List[Framework]:
251
+ """Get all web frameworks."""
252
+ return self.get_frameworks_by_type("web")
253
+
254
+ @property
255
+ def is_web_project(self) -> bool:
256
+ """Check if this appears to be a web project."""
257
+ return len(self.web_frameworks) > 0
258
+
259
+ @property
260
+ def requires_devops_agent(self) -> bool:
261
+ """Check if project likely needs DevOps agent."""
262
+ if self.deployment_target and self.deployment_target.requires_ops_agent:
263
+ return True
264
+ # Check for containerization
265
+ return any(
266
+ tool.name.lower() in {"docker", "kubernetes", "terraform"}
267
+ for tool in self.development_tools
268
+ )
269
+
270
+ def to_dict(self) -> Dict[str, Any]:
271
+ """Convert analysis to dictionary for serialization."""
272
+ return {
273
+ "project_path": str(self.project_path),
274
+ "language_detection": {
275
+ "primary_language": self.language_detection.primary_language,
276
+ "primary_version": self.language_detection.primary_version,
277
+ "primary_confidence": self.language_detection.primary_confidence.value,
278
+ "secondary_languages": [
279
+ {"name": lang.name, "version": lang.version}
280
+ for lang in self.language_detection.secondary_languages
281
+ ],
282
+ "language_percentages": self.language_detection.language_percentages,
283
+ },
284
+ "frameworks": [
285
+ {
286
+ "name": fw.name,
287
+ "version": fw.version,
288
+ "type": fw.framework_type,
289
+ "confidence": fw.confidence.value,
290
+ }
291
+ for fw in self.frameworks
292
+ ],
293
+ "deployment_target": (
294
+ {
295
+ "type": self.deployment_target.target_type,
296
+ "platform": self.deployment_target.platform,
297
+ "confidence": self.deployment_target.confidence.value,
298
+ }
299
+ if self.deployment_target
300
+ else None
301
+ ),
302
+ "build_tools": [tool.name for tool in self.build_tools],
303
+ "package_managers": [pm.name for pm in self.package_managers],
304
+ "overall_confidence": self.overall_confidence.value,
305
+ "metadata": self.metadata,
306
+ }
@@ -13,6 +13,7 @@ that was previously embedded in FrameworkLoader. It manages:
13
13
  The service consolidates path management logic while maintaining backward compatibility.
14
14
  """
15
15
 
16
+ import os
16
17
  import subprocess
17
18
  from enum import Enum
18
19
  from pathlib import Path
@@ -74,10 +75,25 @@ class PathResolver(IPathResolver):
74
75
  return path_obj
75
76
 
76
77
  if base_dir is None:
77
- base_dir = Path.cwd()
78
+ base_dir = self._get_working_dir()
78
79
 
79
80
  return (base_dir / path_obj).resolve()
80
81
 
82
+ def _get_working_dir(self) -> Path:
83
+ """Get working directory respecting CLAUDE_MPM_USER_PWD.
84
+
85
+ When Claude MPM runs from a global installation, CLAUDE_MPM_USER_PWD
86
+ contains the user's actual working directory. This ensures project-local
87
+ paths are resolved correctly.
88
+
89
+ Returns:
90
+ Path: The user's working directory
91
+ """
92
+ user_pwd = os.environ.get("CLAUDE_MPM_USER_PWD")
93
+ if user_pwd:
94
+ return Path(user_pwd)
95
+ return Path.cwd()
96
+
81
97
  def validate_path(self, path: Path, must_exist: bool = False) -> bool:
82
98
  """
83
99
  Validate a path for security and existence.
@@ -129,7 +145,7 @@ class PathResolver(IPathResolver):
129
145
  Project root path or None if not found
130
146
  """
131
147
  if start_path is None:
132
- start_path = Path.cwd()
148
+ start_path = self._get_working_dir()
133
149
 
134
150
  start_path = start_path.resolve()
135
151
 
@@ -265,7 +281,7 @@ class PathResolver(IPathResolver):
265
281
 
266
282
  if agents_dir and agents_dir.exists():
267
283
  discovered_agents_dir = agents_dir
268
- self.logger.info(f"Using custom agents directory: {discovered_agents_dir}")
284
+ self.logger.debug(f"Using custom agents directory: {discovered_agents_dir}")
269
285
  elif framework_path and framework_path != Path("__PACKAGED__"):
270
286
  # Prioritize templates directory over main agents directory
271
287
  templates_dir = (
@@ -299,7 +315,7 @@ class PathResolver(IPathResolver):
299
315
  paths = {"project": None, "user": None, "system": None}
300
316
 
301
317
  # Project-specific instructions
302
- project_path = Path.cwd() / ".claude-mpm" / "INSTRUCTIONS.md"
318
+ project_path = self._get_working_dir() / ".claude-mpm" / "INSTRUCTIONS.md"
303
319
  if project_path.exists():
304
320
  paths["project"] = project_path
305
321
 
@@ -423,11 +439,11 @@ class PathResolver(IPathResolver):
423
439
  """Check common locations for claude-mpm."""
424
440
  candidates = [
425
441
  # Current directory (if we're already in claude-mpm)
426
- Path.cwd(),
442
+ self._get_working_dir(),
427
443
  # Development location
428
444
  Path.home() / "Projects" / "claude-mpm",
429
445
  # Current directory subdirectory
430
- Path.cwd() / "claude-mpm",
446
+ self._get_working_dir() / "claude-mpm",
431
447
  ]
432
448
 
433
449
  for candidate in candidates:
@@ -487,7 +503,7 @@ class PathResolver(IPathResolver):
487
503
  pass
488
504
 
489
505
  # Check if we're in development
490
- if (Path.cwd() / "pyproject.toml").exists():
506
+ if (self._get_working_dir() / "pyproject.toml").exists():
491
507
  return DeploymentContext.DEVELOPMENT
492
508
 
493
509
  return DeploymentContext.UNKNOWN
@@ -13,6 +13,6 @@ DESIGN DECISIONS:
13
13
 
14
14
  from .diagnostic_runner import DiagnosticRunner
15
15
  from .doctor_reporter import DoctorReporter
16
- from .models import DiagnosticResult, DiagnosticStatus
16
+ from .models import DiagnosticResult
17
17
 
18
- __all__ = ["DiagnosticResult", "DiagnosticRunner", "DiagnosticStatus", "DoctorReporter"]
18
+ __all__ = ["DiagnosticResult", "DiagnosticRunner", "DoctorReporter"]