claude-mpm 5.0.9__py3-none-any.whl → 5.4.41__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 (263) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +4 -0
  3. claude_mpm/agents/BASE_AGENT.md +164 -0
  4. claude_mpm/agents/{PM_INSTRUCTIONS_TEACH.md → CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md} +721 -41
  5. claude_mpm/agents/MEMORY.md +1 -1
  6. claude_mpm/agents/PM_INSTRUCTIONS.md +468 -468
  7. claude_mpm/agents/WORKFLOW.md +5 -254
  8. claude_mpm/agents/agent_loader.py +13 -44
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/frontmatter_validator.py +70 -2
  11. claude_mpm/agents/templates/circuit-breakers.md +431 -45
  12. claude_mpm/cli/__init__.py +0 -1
  13. claude_mpm/cli/__main__.py +4 -0
  14. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  15. claude_mpm/cli/commands/agent_state_manager.py +18 -27
  16. claude_mpm/cli/commands/agents.py +175 -37
  17. claude_mpm/cli/commands/auto_configure.py +723 -236
  18. claude_mpm/cli/commands/config.py +88 -2
  19. claude_mpm/cli/commands/configure.py +1262 -157
  20. claude_mpm/cli/commands/configure_agent_display.py +25 -6
  21. claude_mpm/cli/commands/mpm_init/core.py +225 -46
  22. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  23. claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
  24. claude_mpm/cli/commands/postmortem.py +1 -1
  25. claude_mpm/cli/commands/profile.py +277 -0
  26. claude_mpm/cli/commands/skills.py +214 -189
  27. claude_mpm/cli/commands/summarize.py +413 -0
  28. claude_mpm/cli/executor.py +21 -3
  29. claude_mpm/cli/interactive/agent_wizard.py +85 -10
  30. claude_mpm/cli/parsers/agents_parser.py +54 -9
  31. claude_mpm/cli/parsers/auto_configure_parser.py +13 -138
  32. claude_mpm/cli/parsers/base_parser.py +12 -0
  33. claude_mpm/cli/parsers/config_parser.py +153 -83
  34. claude_mpm/cli/parsers/profile_parser.py +148 -0
  35. claude_mpm/cli/parsers/skills_parser.py +3 -2
  36. claude_mpm/cli/startup.py +879 -149
  37. claude_mpm/commands/mpm-config.md +28 -0
  38. claude_mpm/commands/mpm-doctor.md +9 -22
  39. claude_mpm/commands/mpm-help.md +5 -287
  40. claude_mpm/commands/mpm-init.md +81 -507
  41. claude_mpm/commands/mpm-monitor.md +15 -402
  42. claude_mpm/commands/mpm-organize.md +120 -0
  43. claude_mpm/commands/mpm-postmortem.md +6 -108
  44. claude_mpm/commands/mpm-session-resume.md +12 -363
  45. claude_mpm/commands/mpm-status.md +5 -69
  46. claude_mpm/commands/mpm-ticket-view.md +52 -495
  47. claude_mpm/commands/mpm-version.md +5 -107
  48. claude_mpm/config/agent_sources.py +27 -0
  49. claude_mpm/core/config.py +2 -4
  50. claude_mpm/core/framework/formatters/content_formatter.py +3 -13
  51. claude_mpm/core/framework/loaders/agent_loader.py +8 -5
  52. claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
  53. claude_mpm/core/framework_loader.py +4 -2
  54. claude_mpm/core/logger.py +13 -0
  55. claude_mpm/core/optimized_startup.py +59 -0
  56. claude_mpm/core/output_style_manager.py +173 -43
  57. claude_mpm/core/shared/config_loader.py +1 -1
  58. claude_mpm/core/socketio_pool.py +3 -3
  59. claude_mpm/core/unified_agent_registry.py +134 -16
  60. claude_mpm/core/unified_config.py +22 -0
  61. claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
  62. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +1 -0
  63. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +1 -0
  64. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +1 -0
  65. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +1 -0
  66. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +1 -0
  67. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +2 -0
  68. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DjhvlsAc.js +1 -0
  69. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/N4qtv3Hx.js +2 -0
  70. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uj46x2Wr.js +1 -0
  71. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +2 -0
  72. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +1 -0
  73. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.CAGBuiOw.js +1 -0
  74. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +1 -0
  75. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +10 -0
  76. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  77. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  78. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  79. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  80. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  81. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  82. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  83. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  84. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  85. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  86. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  87. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  88. claude_mpm/hooks/claude_hooks/event_handlers.py +211 -78
  89. claude_mpm/hooks/claude_hooks/hook_handler.py +155 -1
  90. claude_mpm/hooks/claude_hooks/installer.py +33 -10
  91. claude_mpm/hooks/claude_hooks/memory_integration.py +28 -0
  92. claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
  93. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  94. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  95. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  96. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  97. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  98. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  99. claude_mpm/hooks/claude_hooks/services/connection_manager.py +30 -6
  100. claude_mpm/hooks/memory_integration_hook.py +46 -1
  101. claude_mpm/init.py +63 -19
  102. claude_mpm/models/agent_definition.py +7 -0
  103. claude_mpm/models/git_repository.py +3 -3
  104. claude_mpm/scripts/claude-hook-handler.sh +58 -18
  105. claude_mpm/scripts/launch_monitor.py +93 -13
  106. claude_mpm/scripts/start_activity_logging.py +0 -0
  107. claude_mpm/services/agents/agent_builder.py +3 -3
  108. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  109. claude_mpm/services/agents/agent_review_service.py +280 -0
  110. claude_mpm/services/agents/cache_git_manager.py +6 -6
  111. claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
  112. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -5
  113. claude_mpm/services/agents/deployment/agent_template_builder.py +5 -3
  114. claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
  115. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +320 -29
  116. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +546 -68
  117. claude_mpm/services/agents/git_source_manager.py +36 -2
  118. claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
  119. claude_mpm/services/agents/recommender.py +5 -3
  120. claude_mpm/services/agents/single_tier_deployment_service.py +2 -2
  121. claude_mpm/services/agents/sources/git_source_sync_service.py +13 -6
  122. claude_mpm/services/agents/startup_sync.py +22 -2
  123. claude_mpm/services/agents/toolchain_detector.py +10 -6
  124. claude_mpm/services/analysis/__init__.py +11 -1
  125. claude_mpm/services/analysis/clone_detector.py +1030 -0
  126. claude_mpm/services/command_deployment_service.py +81 -10
  127. claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
  128. claude_mpm/services/diagnostics/checks/agent_sources_check.py +1 -1
  129. claude_mpm/services/event_bus/config.py +3 -1
  130. claude_mpm/services/git/git_operations_service.py +101 -16
  131. claude_mpm/services/monitor/daemon.py +9 -2
  132. claude_mpm/services/monitor/daemon_manager.py +39 -3
  133. claude_mpm/services/monitor/management/lifecycle.py +8 -1
  134. claude_mpm/services/monitor/server.py +698 -22
  135. claude_mpm/services/pm_skills_deployer.py +676 -0
  136. claude_mpm/services/profile_manager.py +331 -0
  137. claude_mpm/services/project/project_organizer.py +4 -0
  138. claude_mpm/services/self_upgrade_service.py +120 -12
  139. claude_mpm/services/skills/__init__.py +3 -0
  140. claude_mpm/services/skills/git_skill_source_manager.py +130 -2
  141. claude_mpm/services/skills/selective_skill_deployer.py +704 -0
  142. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  143. claude_mpm/services/skills_deployer.py +126 -9
  144. claude_mpm/services/socketio/dashboard_server.py +1 -0
  145. claude_mpm/services/socketio/event_normalizer.py +51 -6
  146. claude_mpm/services/socketio/server/core.py +386 -108
  147. claude_mpm/services/version_control/git_operations.py +103 -0
  148. claude_mpm/skills/skill_manager.py +92 -3
  149. claude_mpm/utils/agent_dependency_loader.py +14 -2
  150. claude_mpm/utils/agent_filters.py +17 -44
  151. claude_mpm/utils/gitignore.py +3 -0
  152. claude_mpm/utils/migration.py +4 -4
  153. claude_mpm/utils/robust_installer.py +47 -3
  154. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/METADATA +57 -87
  155. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/RECORD +160 -211
  156. claude_mpm-5.4.41.dist-info/entry_points.txt +5 -0
  157. claude_mpm-5.4.41.dist-info/licenses/LICENSE +94 -0
  158. claude_mpm-5.4.41.dist-info/licenses/LICENSE-FAQ.md +153 -0
  159. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
  160. claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
  161. claude_mpm/agents/BASE_OPS.md +0 -219
  162. claude_mpm/agents/BASE_PM.md +0 -480
  163. claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
  164. claude_mpm/agents/BASE_QA.md +0 -167
  165. claude_mpm/agents/BASE_RESEARCH.md +0 -53
  166. claude_mpm/agents/base_agent_loader.py +0 -601
  167. claude_mpm/cli/commands/agents_detect.py +0 -380
  168. claude_mpm/cli/commands/agents_recommend.py +0 -309
  169. claude_mpm/cli/ticket_cli.py +0 -35
  170. claude_mpm/commands/mpm-agents-auto-configure.md +0 -278
  171. claude_mpm/commands/mpm-agents-detect.md +0 -177
  172. claude_mpm/commands/mpm-agents-list.md +0 -131
  173. claude_mpm/commands/mpm-agents-recommend.md +0 -223
  174. claude_mpm/commands/mpm-config-view.md +0 -150
  175. claude_mpm/commands/mpm-ticket-organize.md +0 -304
  176. claude_mpm/dashboard/analysis_runner.py +0 -455
  177. claude_mpm/dashboard/index.html +0 -13
  178. claude_mpm/dashboard/open_dashboard.py +0 -66
  179. claude_mpm/dashboard/static/css/activity.css +0 -1958
  180. claude_mpm/dashboard/static/css/connection-status.css +0 -370
  181. claude_mpm/dashboard/static/css/dashboard.css +0 -4701
  182. claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
  183. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
  184. claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
  185. claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
  186. claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
  187. claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
  188. claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
  189. claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
  190. claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
  191. claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
  192. claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
  193. claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
  194. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
  195. claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
  196. claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
  197. claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
  198. claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
  199. claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
  200. claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
  201. claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
  202. claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
  203. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
  204. claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
  205. claude_mpm/dashboard/static/js/connection-manager.js +0 -536
  206. claude_mpm/dashboard/static/js/dashboard.js +0 -1914
  207. claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
  208. claude_mpm/dashboard/static/js/socket-client.js +0 -1474
  209. claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
  210. claude_mpm/dashboard/static/socket.io.min.js +0 -7
  211. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
  212. claude_mpm/dashboard/templates/code_simple.html +0 -153
  213. claude_mpm/dashboard/templates/index.html +0 -606
  214. claude_mpm/dashboard/test_dashboard.html +0 -372
  215. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  216. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
  217. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
  218. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
  219. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
  220. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
  221. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
  222. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
  223. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
  224. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
  225. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
  226. claude_mpm/scripts/mcp_server.py +0 -75
  227. claude_mpm/scripts/mcp_wrapper.py +0 -39
  228. claude_mpm/services/mcp_gateway/__init__.py +0 -159
  229. claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
  230. claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
  231. claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
  232. claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
  233. claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
  234. claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
  235. claude_mpm/services/mcp_gateway/core/base.py +0 -312
  236. claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
  237. claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
  238. claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
  239. claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
  240. claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
  241. claude_mpm/services/mcp_gateway/main.py +0 -589
  242. claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
  243. claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
  244. claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
  245. claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
  246. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
  247. claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
  248. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
  249. claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
  250. claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
  251. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
  252. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
  253. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
  254. claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
  255. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
  256. claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
  257. claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
  258. claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
  259. claude_mpm-5.0.9.dist-info/entry_points.txt +0 -10
  260. claude_mpm-5.0.9.dist-info/licenses/LICENSE +0 -21
  261. /claude_mpm/agents/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +0 -0
  262. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/WHEEL +0 -0
  263. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,413 @@
1
+ """
2
+ Document Summarization Command.
3
+
4
+ Shell-based alternative to MCP document_summarizer tool.
5
+ Provides algorithmic summarization without ML dependencies.
6
+
7
+ Design Decision: Uses simple text processing techniques:
8
+ - Brief: First paragraph extraction
9
+ - Detailed: Key sentence extraction based on position and length
10
+ - Bullet Points: Convert to markdown bullet list
11
+ - Executive: Opening + conclusion extraction
12
+
13
+ Why: Lightweight, fast, no dependencies, works offline.
14
+ """
15
+
16
+ import json
17
+ import re
18
+ from enum import Enum
19
+ from pathlib import Path
20
+ from typing import Optional
21
+
22
+
23
+ class SummaryStyle(str, Enum):
24
+ """Summary output styles."""
25
+
26
+ BRIEF = "brief"
27
+ DETAILED = "detailed"
28
+ BULLET_POINTS = "bullet_points"
29
+ EXECUTIVE = "executive"
30
+
31
+
32
+ class OutputFormat(str, Enum):
33
+ """Output format types."""
34
+
35
+ TEXT = "text"
36
+ JSON = "json"
37
+ MARKDOWN = "markdown"
38
+
39
+
40
+ class DocumentSummarizer:
41
+ """
42
+ Algorithmic document summarizer.
43
+
44
+ Design Decision: Use simple heuristics instead of ML:
45
+ - Position-based extraction (opening, closing paragraphs)
46
+ - Length-based filtering (key sentences)
47
+ - Structure detection (headings, lists)
48
+
49
+ Trade-offs:
50
+ - Performance: O(n) single pass vs. complex NLP models
51
+ - Accuracy: ~70% vs. ~90% for ML models
52
+ - Simplicity: Zero dependencies vs. heavy ML packages
53
+ """
54
+
55
+ def __init__(self, max_words: int = 150):
56
+ """Initialize summarizer with word limit."""
57
+ self.max_words = max_words
58
+
59
+ def summarize(
60
+ self, content: str, style: SummaryStyle, lines_limit: Optional[int] = None
61
+ ) -> str:
62
+ """
63
+ Summarize document content.
64
+
65
+ Args:
66
+ content: Document text to summarize
67
+ style: Summary style (brief, detailed, bullet_points, executive)
68
+ lines_limit: Optional line limit (reads first N lines only)
69
+
70
+ Returns:
71
+ Summary text
72
+
73
+ Complexity: O(n) where n is content length
74
+ """
75
+ # Apply line limit if specified
76
+ if lines_limit:
77
+ content = self._limit_lines(content, lines_limit)
78
+
79
+ # Route to style-specific summarizer
80
+ summarizers = {
81
+ SummaryStyle.BRIEF: self._summarize_brief,
82
+ SummaryStyle.DETAILED: self._summarize_detailed,
83
+ SummaryStyle.BULLET_POINTS: self._summarize_bullet_points,
84
+ SummaryStyle.EXECUTIVE: self._summarize_executive,
85
+ }
86
+
87
+ summary = summarizers[style](content)
88
+ return self._truncate_to_word_limit(summary)
89
+
90
+ def _limit_lines(self, content: str, limit: int) -> str:
91
+ """Limit content to first N lines."""
92
+ lines = content.split("\n")
93
+ return "\n".join(lines[:limit])
94
+
95
+ def _truncate_to_word_limit(self, text: str) -> str:
96
+ """Truncate text to max_words limit."""
97
+ words = text.split()
98
+ if len(words) <= self.max_words:
99
+ return text
100
+
101
+ # Truncate and add ellipsis
102
+ truncated = " ".join(words[: self.max_words])
103
+ return f"{truncated}..."
104
+
105
+ def _summarize_brief(self, content: str) -> str:
106
+ """
107
+ Brief summary: Extract first paragraph.
108
+
109
+ Heuristic: First non-empty paragraph usually introduces document.
110
+ """
111
+ paragraphs = self._extract_paragraphs(content)
112
+ if not paragraphs:
113
+ return content.strip()
114
+
115
+ return paragraphs[0]
116
+
117
+ def _summarize_detailed(self, content: str) -> str:
118
+ """
119
+ Detailed summary: Extract key sentences.
120
+
121
+ Heuristics:
122
+ - First paragraph (introduction)
123
+ - Sentences with important markers (however, therefore, important)
124
+ - Last paragraph (conclusion)
125
+ """
126
+ paragraphs = self._extract_paragraphs(content)
127
+ if not paragraphs:
128
+ return content.strip()
129
+
130
+ key_sentences = []
131
+
132
+ # Add first paragraph
133
+ if paragraphs:
134
+ key_sentences.append(paragraphs[0])
135
+
136
+ # Add sentences with key markers from middle paragraphs
137
+ if len(paragraphs) > 2:
138
+ key_markers = [
139
+ "however",
140
+ "therefore",
141
+ "important",
142
+ "note",
143
+ "critical",
144
+ "key",
145
+ "must",
146
+ "should",
147
+ "recommended",
148
+ ]
149
+
150
+ for para in paragraphs[1:-1]:
151
+ sentences = self._split_sentences(para)
152
+ for sentence in sentences:
153
+ if any(marker in sentence.lower() for marker in key_markers):
154
+ key_sentences.append(sentence)
155
+ break # One sentence per paragraph max
156
+
157
+ # Add last paragraph
158
+ if len(paragraphs) > 1:
159
+ key_sentences.append(paragraphs[-1])
160
+
161
+ return " ".join(key_sentences)
162
+
163
+ def _summarize_bullet_points(self, content: str) -> str:
164
+ """
165
+ Bullet point summary: Convert paragraphs to markdown list.
166
+
167
+ Heuristic: Each paragraph becomes a bullet point.
168
+ """
169
+ paragraphs = self._extract_paragraphs(content)
170
+ if not paragraphs:
171
+ return content.strip()
172
+
173
+ # Take key paragraphs (first, middle with markers, last)
174
+ key_paragraphs = []
175
+
176
+ # Always include first
177
+ if paragraphs:
178
+ key_paragraphs.append(paragraphs[0])
179
+
180
+ # Include middle paragraphs with key content
181
+ if len(paragraphs) > 2:
182
+ key_markers = ["however", "therefore", "important", "note", "critical"]
183
+ for para in paragraphs[1:-1]:
184
+ if any(marker in para.lower() for marker in key_markers):
185
+ # Take first sentence only for bullet point
186
+ first_sentence = self._split_sentences(para)[0]
187
+ key_paragraphs.append(first_sentence)
188
+
189
+ # Include last if different from first
190
+ if len(paragraphs) > 1:
191
+ key_paragraphs.append(paragraphs[-1])
192
+
193
+ # Format as markdown bullets
194
+ bullets = [f"- {para}" for para in key_paragraphs]
195
+ return "\n".join(bullets)
196
+
197
+ def _summarize_executive(self, content: str) -> str:
198
+ """
199
+ Executive summary: Opening + conclusion.
200
+
201
+ Heuristic: First and last paragraphs capture overview and conclusion.
202
+ """
203
+ paragraphs = self._extract_paragraphs(content)
204
+ if not paragraphs:
205
+ return content.strip()
206
+
207
+ if len(paragraphs) == 1:
208
+ return paragraphs[0]
209
+
210
+ # Opening paragraph + conclusion paragraph
211
+ return f"{paragraphs[0]}\n\n{paragraphs[-1]}"
212
+
213
+ def _extract_paragraphs(self, content: str) -> list[str]:
214
+ """
215
+ Extract paragraphs from content.
216
+
217
+ Filters out:
218
+ - Empty lines
219
+ - Short lines (< 40 chars, likely headers/formatting artifacts)
220
+ - Code blocks (lines with multiple indentation)
221
+ - Lines that look like code (contain def, class, =, {, etc.)
222
+ """
223
+ # Split on double newlines for paragraph boundaries
224
+ raw_paragraphs = re.split(r"\n\s*\n", content)
225
+
226
+ paragraphs = []
227
+ for para in raw_paragraphs:
228
+ # Clean and normalize whitespace
229
+ para = " ".join(para.split())
230
+
231
+ # Skip empty or very short paragraphs (likely headers)
232
+ if len(para) < 40:
233
+ continue
234
+
235
+ # Skip code blocks (heuristic: contains code-like patterns)
236
+ code_indicators = ["def ", "class ", " = ", "{", "}", "return ", "import "]
237
+ if any(indicator in para for indicator in code_indicators):
238
+ continue
239
+
240
+ paragraphs.append(para)
241
+
242
+ return paragraphs
243
+
244
+ def _split_sentences(self, text: str) -> list[str]:
245
+ """
246
+ Split text into sentences.
247
+
248
+ Simple heuristic: Split on '. ' but handle common abbreviations.
249
+ """
250
+ # Handle common abbreviations to avoid false splits
251
+ text = text.replace("Dr.", "Dr<DOT>")
252
+ text = text.replace("Mr.", "Mr<DOT>")
253
+ text = text.replace("Mrs.", "Mrs<DOT>")
254
+ text = text.replace("e.g.", "e<DOT>g<DOT>")
255
+ text = text.replace("i.e.", "i<DOT>e<DOT>")
256
+
257
+ # Split on sentence boundaries
258
+ sentences = re.split(r"(?<=[.!?])\s+", text)
259
+
260
+ # Restore abbreviations
261
+ sentences = [s.replace("<DOT>", ".") for s in sentences]
262
+
263
+ return [s.strip() for s in sentences if s.strip()]
264
+
265
+
266
+ def format_output(summary: str, output_format: OutputFormat, file_path: Path) -> str:
267
+ """
268
+ Format summary output.
269
+
270
+ Args:
271
+ summary: Summary text
272
+ output_format: Output format (text, json, markdown)
273
+ file_path: Original file path for metadata
274
+
275
+ Returns:
276
+ Formatted output string
277
+ """
278
+ if output_format == OutputFormat.TEXT:
279
+ return summary
280
+
281
+ if output_format == OutputFormat.JSON:
282
+ result = {
283
+ "file": str(file_path),
284
+ "summary": summary,
285
+ "word_count": len(summary.split()),
286
+ }
287
+ return json.dumps(result, indent=2)
288
+
289
+ if output_format == OutputFormat.MARKDOWN:
290
+ return f"# Summary: {file_path.name}\n\n{summary}\n"
291
+
292
+ return summary
293
+
294
+
295
+ def summarize_command(args) -> int:
296
+ """
297
+ Execute summarize command.
298
+
299
+ Args:
300
+ args: Parsed command line arguments with:
301
+ - file_path: Path to file to summarize
302
+ - style: Summary style
303
+ - max_words: Maximum words in summary
304
+ - output: Output format
305
+ - lines: Optional line limit
306
+
307
+ Returns:
308
+ Exit code (0 for success, 1 for error)
309
+ """
310
+ file_path = Path(args.file_path)
311
+
312
+ # Validate file exists
313
+ if not file_path.exists():
314
+ print(f"Error: File not found: {file_path}")
315
+ return 1
316
+
317
+ if not file_path.is_file():
318
+ print(f"Error: Not a file: {file_path}")
319
+ return 1
320
+
321
+ try:
322
+ # Read file content
323
+ content = file_path.read_text(encoding="utf-8")
324
+
325
+ # Create summarizer
326
+ summarizer = DocumentSummarizer(max_words=args.max_words)
327
+
328
+ # Generate summary
329
+ summary = summarizer.summarize(
330
+ content, style=SummaryStyle(args.style), lines_limit=args.lines
331
+ )
332
+
333
+ # Format output
334
+ output = format_output(summary, OutputFormat(args.output), file_path)
335
+
336
+ # Print result
337
+ print(output)
338
+
339
+ return 0
340
+
341
+ except UnicodeDecodeError:
342
+ print(f"Error: Cannot read file (not valid UTF-8): {file_path}")
343
+ return 1
344
+ except Exception as e:
345
+ print(f"Error: {e}")
346
+ return 1
347
+
348
+
349
+ def add_summarize_parser(subparsers) -> None:
350
+ """
351
+ Add summarize subcommand parser.
352
+
353
+ Args:
354
+ subparsers: Subparsers object from argparse
355
+ """
356
+ parser = subparsers.add_parser(
357
+ "summarize",
358
+ help="Summarize document content (shell-based alternative to MCP document_summarizer)",
359
+ description="""
360
+ Algorithmic document summarization without ML dependencies.
361
+
362
+ Styles:
363
+ brief - First paragraph only (quick overview)
364
+ detailed - Key sentences from opening, middle, closing
365
+ bullet_points - Markdown bullet list of key points
366
+ executive - Opening + conclusion (for quick decisions)
367
+
368
+ Examples:
369
+ claude-mpm summarize README.md
370
+ claude-mpm summarize docs/guide.md --style detailed --max-words 200
371
+ claude-mpm summarize src/main.py --style bullet_points --output markdown
372
+ claude-mpm summarize large.txt --lines 100 --style brief
373
+ """,
374
+ formatter_class=lambda prog: __import__("argparse").RawDescriptionHelpFormatter(
375
+ prog, max_help_position=40
376
+ ),
377
+ )
378
+
379
+ # Required arguments
380
+ parser.add_argument("file_path", type=str, help="Path to file to summarize")
381
+
382
+ # Optional arguments
383
+ parser.add_argument(
384
+ "--style",
385
+ type=str,
386
+ choices=["brief", "detailed", "bullet_points", "executive"],
387
+ default="brief",
388
+ help="Summary style (default: brief)",
389
+ )
390
+
391
+ parser.add_argument(
392
+ "--max-words",
393
+ type=int,
394
+ default=150,
395
+ help="Maximum words in summary (default: 150)",
396
+ )
397
+
398
+ parser.add_argument(
399
+ "--output",
400
+ type=str,
401
+ choices=["text", "json", "markdown"],
402
+ default="text",
403
+ help="Output format (default: text)",
404
+ )
405
+
406
+ parser.add_argument(
407
+ "--lines",
408
+ type=int,
409
+ default=None,
410
+ help="Limit to first N lines of file (default: no limit)",
411
+ )
412
+
413
+ parser.set_defaults(command="summarize")
@@ -24,6 +24,7 @@ from .commands import (
24
24
  show_info,
25
25
  )
26
26
  from .commands.analyze_code import manage_analyze_code
27
+ from .commands.config import manage_config
27
28
  from .commands.dashboard import manage_dashboard
28
29
  from .commands.skills import manage_skills
29
30
  from .commands.upgrade import upgrade
@@ -141,6 +142,24 @@ def execute_command(command: str, args) -> int:
141
142
  result = agent_source_command(args)
142
143
  return result if result is not None else 0
143
144
 
145
+ # Handle summarize command with lazy import
146
+ if command == "summarize":
147
+ # Lazy import to avoid loading unless needed
148
+ from .commands.summarize import summarize_command
149
+
150
+ result = summarize_command(args)
151
+ return result if result is not None else 0
152
+
153
+ # Handle profile command with lazy import
154
+ if command == "profile":
155
+ # Lazy import to avoid loading unless needed
156
+ from .commands.profile import ProfileCommand
157
+
158
+ cmd = ProfileCommand()
159
+ result = cmd.run(args)
160
+ # Convert CommandResult to exit code
161
+ return result.exit_code if result else 0
162
+
144
163
  # Handle auto-configure command with lazy import
145
164
  if command == "auto-configure":
146
165
  # Lazy import to avoid loading unless needed
@@ -228,9 +247,8 @@ def execute_command(command: str, args) -> int:
228
247
  CLICommands.MEMORY.value: manage_memory,
229
248
  CLICommands.MONITOR.value: manage_monitor,
230
249
  CLICommands.DASHBOARD.value: manage_dashboard,
231
- # Configuration management commands (synonymous)
232
- # Both 'config' and 'configure' launch the interactive configuration TUI
233
- CLICommands.CONFIG.value: manage_configure, # Alias to configure
250
+ # Configuration management commands
251
+ CLICommands.CONFIG.value: manage_config, # Unified config with subcommands
234
252
  CLICommands.CONFIGURE.value: manage_configure, # Interactive configuration TUI
235
253
  CLICommands.AGGREGATE.value: aggregate_command,
236
254
  CLICommands.ANALYZE_CODE.value: manage_analyze_code,
@@ -6,6 +6,7 @@ local agents with user-friendly prompts, intelligent defaults, and validation.
6
6
 
7
7
  import json
8
8
  import re
9
+ import shutil
9
10
  import sys
10
11
  from pathlib import Path
11
12
  from typing import Any, Dict, List, Optional, Tuple
@@ -61,6 +62,50 @@ class AgentWizard:
61
62
  self.source_manager = None
62
63
  self.discovery_enabled = False
63
64
 
65
+ @staticmethod
66
+ def _calculate_column_widths(
67
+ terminal_width: int, columns: Dict[str, int]
68
+ ) -> Dict[str, int]:
69
+ """Calculate dynamic column widths based on terminal size.
70
+
71
+ Args:
72
+ terminal_width: Current terminal width in characters
73
+ columns: Dict mapping column names to minimum widths
74
+
75
+ Returns:
76
+ Dict mapping column names to calculated widths
77
+
78
+ Design:
79
+ - Ensures minimum widths are respected
80
+ - Distributes extra space proportionally
81
+ - Handles narrow terminals gracefully (minimum 80 chars)
82
+ """
83
+ # Ensure minimum terminal width
84
+ min_terminal_width = 80
85
+ terminal_width = max(terminal_width, min_terminal_width)
86
+
87
+ # Calculate total minimum width needed
88
+ total_min_width = sum(columns.values())
89
+
90
+ # Account for spacing between columns
91
+ overhead = len(columns) + 1
92
+ available_width = terminal_width - overhead
93
+
94
+ # If we have extra space, distribute proportionally
95
+ if available_width > total_min_width:
96
+ extra_space = available_width - total_min_width
97
+ total_weight = sum(columns.values())
98
+
99
+ result = {}
100
+ for col_name, min_width in columns.items():
101
+ # Distribute extra space based on minimum width proportion
102
+ proportion = min_width / total_weight
103
+ extra = int(extra_space * proportion)
104
+ result[col_name] = min_width + extra
105
+ return result
106
+ # Terminal too narrow, use minimum widths
107
+ return columns.copy()
108
+
64
109
  def run_interactive_create(self) -> Tuple[bool, str]:
65
110
  """Run interactive agent creation wizard.
66
111
 
@@ -259,25 +304,55 @@ class AgentWizard:
259
304
  print("❌ Invalid choice. Please try again.")
260
305
  continue
261
306
 
262
- # Show existing agents in a table
307
+ # Show existing agents in a table with dynamic widths
263
308
  print(f"\n📋 Found {len(all_agents)} agent(s):\n")
309
+
310
+ # Calculate dynamic column widths based on terminal size
311
+ terminal_width = shutil.get_terminal_size().columns
312
+ min_widths = {
313
+ "#": 4,
314
+ "Agent ID": 30,
315
+ "Name": 20,
316
+ "Source": 15,
317
+ "Status": 10,
318
+ }
319
+ widths = self._calculate_column_widths(terminal_width, min_widths)
320
+
321
+ # Print header with dynamic widths
264
322
  print(
265
- f"{'#':<4} {'Agent ID':<40} {'Name':<25} {'Source':<20} {'Status':<10}"
323
+ f"{'#':<{widths['#']}} "
324
+ f"{'Agent ID':<{widths['Agent ID']}} "
325
+ f"{'Name':<{widths['Name']}} "
326
+ f"{'Source':<{widths['Source']}} "
327
+ f"{'Status':<{widths['Status']}}"
266
328
  )
267
- print("-" * 105)
329
+ separator_width = sum(widths.values()) + len(widths) - 1
330
+ print("-" * separator_width)
268
331
 
269
332
  for i, agent in enumerate(all_agents, 1):
270
333
  agent_id = agent["agent_id"]
271
- name = (
272
- agent["name"][:24] if len(agent["name"]) > 24 else agent["name"]
273
- )
334
+ # Truncate to fit dynamic width
335
+ if len(agent_id) > widths["Agent ID"]:
336
+ agent_id = agent_id[: widths["Agent ID"] - 1] + "…"
337
+
338
+ name = agent["name"]
339
+ if len(name) > widths["Name"]:
340
+ name = name[: widths["Name"] - 1] + "…"
341
+
274
342
  source_label = (
275
- f"[{agent['source_type']}] {agent['source_identifier']}"[:19]
343
+ f"[{agent['source_type']}] {agent['source_identifier']}"
276
344
  )
345
+ if len(source_label) > widths["Source"]:
346
+ source_label = source_label[: widths["Source"] - 1] + "…"
347
+
277
348
  status = "✓ Deployed" if agent["deployed"] else "Available"
278
349
 
279
350
  print(
280
- f"{i:<4} {agent_id:<40} {name:<25} {source_label:<20} {status:<10}"
351
+ f"{i:<{widths['#']}} "
352
+ f"{agent_id:<{widths['Agent ID']}} "
353
+ f"{name:<{widths['Name']}} "
354
+ f"{source_label:<{widths['Source']}} "
355
+ f"{status:<{widths['Status']}}"
281
356
  )
282
357
 
283
358
  # Build menu choices with arrow-key navigation
@@ -1299,7 +1374,7 @@ class AgentWizard:
1299
1374
  Path.home()
1300
1375
  / ".claude-mpm"
1301
1376
  / "cache"
1302
- / "remote-agents"
1377
+ / "agents"
1303
1378
  / "bobmatnyc"
1304
1379
  / "claude-mpm-agents"
1305
1380
  / "AUTO-DEPLOY-INDEX.md"
@@ -1344,7 +1419,7 @@ class AgentWizard:
1344
1419
  Path.home()
1345
1420
  / ".claude-mpm"
1346
1421
  / "cache"
1347
- / "remote-agents"
1422
+ / "agents"
1348
1423
  / "bobmatnyc"
1349
1424
  / "claude-mpm-agents"
1350
1425
  / "AUTO-DEPLOY-INDEX.md"
@@ -406,15 +406,6 @@ Available commands:
406
406
  help="Show descriptions and metadata for each agent",
407
407
  )
408
408
 
409
- # Auto-configuration commands (TSK-0054 Phase 5)
410
- from .auto_configure_parser import (
411
- add_agents_detect_subparser,
412
- add_agents_recommend_subparser,
413
- )
414
-
415
- add_agents_detect_subparser(agents_subparsers)
416
- add_agents_recommend_subparser(agents_subparsers)
417
-
418
409
  # Phase 3: Agent Selection Modes (single-tier deployment)
419
410
  # Minimal configuration - deploy 6 core agents
420
411
  deploy_minimal_parser = agents_subparsers.add_parser(
@@ -444,6 +435,60 @@ Available commands:
444
435
  help="Show what would be deployed without actually deploying",
445
436
  )
446
437
 
438
+ # ============================================================================
439
+ # Collection-Based Agent Management Commands
440
+ # ============================================================================
441
+ # Purpose: Enable collection-based agent selection and deployment
442
+ # Commands: list-collections, deploy-collection, list-by-collection
443
+ # NEW: Enhanced agent matching with collection_id support
444
+ # ============================================================================
445
+
446
+ # list-collections: List all available agent collections
447
+ agents_subparsers.add_parser(
448
+ "list-collections",
449
+ help="List all available agent collections",
450
+ description="Display all agent collections with agent counts and collection metadata",
451
+ )
452
+
453
+ # deploy-collection: Deploy all agents from a specific collection
454
+ deploy_collection_parser = agents_subparsers.add_parser(
455
+ "deploy-collection",
456
+ help="Deploy all agents from a specific collection",
457
+ description="Deploy all agents from a named collection (e.g., 'bobmatnyc/claude-mpm-agents')",
458
+ )
459
+ deploy_collection_parser.add_argument(
460
+ "collection_id",
461
+ help="Collection ID in format 'owner/repo-name' (e.g., 'bobmatnyc/claude-mpm-agents')",
462
+ )
463
+ deploy_collection_parser.add_argument(
464
+ "--force",
465
+ "-f",
466
+ action="store_true",
467
+ help="Force redeployment even if agents are already deployed",
468
+ )
469
+ deploy_collection_parser.add_argument(
470
+ "--dry-run",
471
+ action="store_true",
472
+ help="Show what would be deployed without actually deploying",
473
+ )
474
+
475
+ # list-by-collection: List agents filtered by collection
476
+ list_by_collection_parser = agents_subparsers.add_parser(
477
+ "list-by-collection",
478
+ help="List agents from a specific collection",
479
+ description="Display agents from a specific collection with metadata",
480
+ )
481
+ list_by_collection_parser.add_argument(
482
+ "collection_id",
483
+ help="Collection ID to filter by (e.g., 'bobmatnyc/claude-mpm-agents')",
484
+ )
485
+ list_by_collection_parser.add_argument(
486
+ "--format",
487
+ choices=["table", "json", "yaml"],
488
+ default="table",
489
+ help="Output format (default: table)",
490
+ )
491
+
447
492
  # ============================================================================
448
493
  # Cache Git Management Commands (claude-mpm Issue 1M-442 Phase 2)
449
494
  # ============================================================================