claude-mpm 4.1.6__py3-none-any.whl → 4.24.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (866) hide show
  1. claude_mpm/BUILD_NUMBER +1 -1
  2. claude_mpm/VERSION +1 -1
  3. claude_mpm/__init__.py +20 -5
  4. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +118 -0
  5. claude_mpm/agents/BASE_DOCUMENTATION.md +53 -0
  6. claude_mpm/agents/BASE_ENGINEER.md +658 -0
  7. claude_mpm/agents/BASE_OPS.md +219 -0
  8. claude_mpm/agents/BASE_PM.md +431 -214
  9. claude_mpm/agents/BASE_PROMPT_ENGINEER.md +787 -0
  10. claude_mpm/agents/BASE_QA.md +167 -0
  11. claude_mpm/agents/BASE_RESEARCH.md +53 -0
  12. claude_mpm/agents/MEMORY.md +3 -0
  13. claude_mpm/agents/OUTPUT_STYLE.md +335 -0
  14. claude_mpm/agents/PM_INSTRUCTIONS.md +1159 -0
  15. claude_mpm/agents/WORKFLOW.md +355 -187
  16. claude_mpm/agents/agent_loader.py +40 -10
  17. claude_mpm/agents/agent_loader_integration.py +3 -2
  18. claude_mpm/agents/agents_metadata.py +57 -0
  19. claude_mpm/agents/async_agent_loader.py +3 -3
  20. claude_mpm/agents/base_agent_loader.py +11 -9
  21. claude_mpm/agents/frontmatter_validator.py +291 -251
  22. claude_mpm/agents/system_agent_config.py +3 -2
  23. claude_mpm/agents/templates/.claude-mpm/memories/README.md +17 -0
  24. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +3 -0
  25. claude_mpm/agents/templates/README.md +465 -0
  26. claude_mpm/agents/templates/agent-manager.json +267 -18
  27. claude_mpm/agents/templates/agentic-coder-optimizer.json +248 -0
  28. claude_mpm/agents/templates/api_qa.json +16 -4
  29. claude_mpm/agents/templates/circuit_breakers.md +638 -0
  30. claude_mpm/agents/templates/clerk-ops.json +235 -0
  31. claude_mpm/agents/templates/code_analyzer.json +25 -9
  32. claude_mpm/agents/templates/content-agent.json +358 -0
  33. claude_mpm/agents/templates/dart_engineer.json +307 -0
  34. claude_mpm/agents/templates/data_engineer.json +87 -14
  35. claude_mpm/agents/templates/documentation.json +76 -13
  36. claude_mpm/agents/templates/engineer.json +44 -10
  37. claude_mpm/agents/templates/gcp_ops_agent.json +253 -0
  38. claude_mpm/agents/templates/git_file_tracking.md +584 -0
  39. claude_mpm/agents/templates/golang_engineer.json +270 -0
  40. claude_mpm/agents/templates/imagemagick.json +5 -2
  41. claude_mpm/agents/templates/java_engineer.json +346 -0
  42. claude_mpm/agents/templates/javascript_engineer_agent.json +380 -0
  43. claude_mpm/agents/templates/local_ops_agent.json +1840 -0
  44. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +39 -0
  45. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +400 -0
  46. claude_mpm/agents/templates/memory_manager.json +6 -3
  47. claude_mpm/agents/templates/nextjs_engineer.json +285 -0
  48. claude_mpm/agents/templates/ops.json +27 -8
  49. claude_mpm/agents/templates/php-engineer.json +287 -0
  50. claude_mpm/agents/templates/pm_examples.md +474 -0
  51. claude_mpm/agents/templates/pm_red_flags.md +262 -0
  52. claude_mpm/agents/templates/product_owner.json +338 -0
  53. claude_mpm/agents/templates/project_organizer.json +19 -5
  54. claude_mpm/agents/templates/prompt-engineer.json +737 -0
  55. claude_mpm/agents/templates/python_engineer.json +387 -0
  56. claude_mpm/agents/templates/qa.json +26 -6
  57. claude_mpm/agents/templates/react_engineer.json +239 -0
  58. claude_mpm/agents/templates/refactoring_engineer.json +15 -5
  59. claude_mpm/agents/templates/research.json +47 -22
  60. claude_mpm/agents/templates/response_format.md +583 -0
  61. claude_mpm/agents/templates/ruby-engineer.json +280 -0
  62. claude_mpm/agents/templates/rust_engineer.json +275 -0
  63. claude_mpm/agents/templates/security.json +59 -10
  64. claude_mpm/agents/templates/svelte-engineer.json +225 -0
  65. claude_mpm/agents/templates/tauri_engineer.json +274 -0
  66. claude_mpm/agents/templates/ticketing.json +16 -7
  67. claude_mpm/agents/templates/typescript_engineer.json +285 -0
  68. claude_mpm/agents/templates/validation_templates.md +312 -0
  69. claude_mpm/agents/templates/vercel_ops_agent.json +164 -33
  70. claude_mpm/agents/templates/version_control.json +16 -4
  71. claude_mpm/agents/templates/web_qa.json +243 -21
  72. claude_mpm/agents/templates/web_ui.json +18 -5
  73. claude_mpm/cli/__init__.py +38 -363
  74. claude_mpm/cli/commands/__init__.py +8 -0
  75. claude_mpm/cli/commands/agent_manager.py +675 -20
  76. claude_mpm/cli/commands/agent_state_manager.py +186 -0
  77. claude_mpm/cli/commands/agents.py +722 -150
  78. claude_mpm/cli/commands/agents_detect.py +380 -0
  79. claude_mpm/cli/commands/agents_recommend.py +309 -0
  80. claude_mpm/cli/commands/aggregate.py +10 -6
  81. claude_mpm/cli/commands/analyze.py +553 -0
  82. claude_mpm/cli/commands/analyze_code.py +528 -0
  83. claude_mpm/cli/commands/auto_configure.py +570 -0
  84. claude_mpm/cli/commands/cleanup.py +12 -12
  85. claude_mpm/cli/commands/config.py +47 -13
  86. claude_mpm/cli/commands/configure.py +488 -884
  87. claude_mpm/cli/commands/configure_agent_display.py +261 -0
  88. claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
  89. claude_mpm/cli/commands/configure_hook_manager.py +225 -0
  90. claude_mpm/cli/commands/configure_models.py +18 -0
  91. claude_mpm/cli/commands/configure_navigation.py +167 -0
  92. claude_mpm/cli/commands/configure_paths.py +104 -0
  93. claude_mpm/cli/commands/configure_persistence.py +254 -0
  94. claude_mpm/cli/commands/configure_startup_manager.py +646 -0
  95. claude_mpm/cli/commands/configure_template_editor.py +497 -0
  96. claude_mpm/cli/commands/configure_validators.py +73 -0
  97. claude_mpm/cli/commands/dashboard.py +286 -0
  98. claude_mpm/cli/commands/debug.py +1386 -0
  99. claude_mpm/cli/commands/doctor.py +43 -7
  100. claude_mpm/cli/commands/info.py +3 -4
  101. claude_mpm/cli/commands/local_deploy.py +537 -0
  102. claude_mpm/cli/commands/mcp.py +17 -10
  103. claude_mpm/cli/commands/mcp_command_router.py +11 -0
  104. claude_mpm/cli/commands/mcp_config.py +154 -0
  105. claude_mpm/cli/commands/mcp_external_commands.py +249 -0
  106. claude_mpm/cli/commands/mcp_install_commands.py +101 -32
  107. claude_mpm/cli/commands/mcp_pipx_config.py +2 -2
  108. claude_mpm/cli/commands/mcp_setup_external.py +868 -0
  109. claude_mpm/cli/commands/memory.py +55 -21
  110. claude_mpm/cli/commands/monitor.py +168 -617
  111. claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
  112. claude_mpm/cli/commands/mpm_init/core.py +525 -0
  113. claude_mpm/cli/commands/mpm_init/display.py +341 -0
  114. claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
  115. claude_mpm/cli/commands/mpm_init/modes.py +397 -0
  116. claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
  117. claude_mpm/cli/commands/mpm_init_cli.py +396 -0
  118. claude_mpm/cli/commands/mpm_init_handler.py +195 -0
  119. claude_mpm/cli/commands/run.py +169 -42
  120. claude_mpm/cli/commands/search.py +458 -0
  121. claude_mpm/cli/commands/skills.py +488 -0
  122. claude_mpm/cli/commands/uninstall.py +176 -0
  123. claude_mpm/cli/commands/upgrade.py +152 -0
  124. claude_mpm/cli/commands/verify.py +119 -0
  125. claude_mpm/cli/executor.py +204 -0
  126. claude_mpm/cli/helpers.py +105 -0
  127. claude_mpm/cli/interactive/__init__.py +21 -0
  128. claude_mpm/cli/interactive/agent_wizard.py +962 -0
  129. claude_mpm/cli/interactive/skills_wizard.py +491 -0
  130. claude_mpm/cli/parser.py +79 -2
  131. claude_mpm/cli/parsers/__init__.py +7 -1
  132. claude_mpm/cli/parsers/agent_manager_parser.py +161 -1
  133. claude_mpm/cli/parsers/agents_parser.py +116 -0
  134. claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
  135. claude_mpm/cli/parsers/analyze_parser.py +135 -0
  136. claude_mpm/cli/parsers/auto_configure_parser.py +245 -0
  137. claude_mpm/cli/parsers/base_parser.py +187 -3
  138. claude_mpm/cli/parsers/configure_parser.py +34 -15
  139. claude_mpm/cli/parsers/dashboard_parser.py +113 -0
  140. claude_mpm/cli/parsers/debug_parser.py +319 -0
  141. claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
  142. claude_mpm/cli/parsers/mcp_parser.py +15 -0
  143. claude_mpm/cli/parsers/monitor_parser.py +12 -2
  144. claude_mpm/cli/parsers/mpm_init_parser.py +311 -0
  145. claude_mpm/cli/parsers/run_parser.py +5 -0
  146. claude_mpm/cli/parsers/search_parser.py +245 -0
  147. claude_mpm/cli/parsers/skills_parser.py +137 -0
  148. claude_mpm/cli/shared/argument_patterns.py +20 -13
  149. claude_mpm/cli/shared/base_command.py +2 -2
  150. claude_mpm/cli/shared/output_formatters.py +28 -19
  151. claude_mpm/cli/startup.py +562 -0
  152. claude_mpm/cli/startup_logging.py +179 -13
  153. claude_mpm/cli/utils.py +53 -2
  154. claude_mpm/commands/__init__.py +14 -0
  155. claude_mpm/commands/mpm-agents-detect.md +168 -0
  156. claude_mpm/commands/mpm-agents-recommend.md +214 -0
  157. claude_mpm/commands/mpm-agents.md +122 -0
  158. claude_mpm/commands/mpm-auto-configure.md +269 -0
  159. claude_mpm/commands/mpm-config.md +141 -0
  160. claude_mpm/commands/mpm-doctor.md +24 -0
  161. claude_mpm/commands/mpm-help.md +290 -0
  162. claude_mpm/commands/mpm-init.md +521 -0
  163. claude_mpm/commands/mpm-monitor.md +409 -0
  164. claude_mpm/commands/mpm-organize.md +295 -0
  165. claude_mpm/commands/mpm-resume.md +372 -0
  166. claude_mpm/commands/mpm-status.md +75 -0
  167. claude_mpm/commands/mpm-tickets.md +151 -0
  168. claude_mpm/commands/mpm-version.md +113 -0
  169. claude_mpm/commands/mpm.md +21 -0
  170. claude_mpm/config/agent_config.py +4 -4
  171. claude_mpm/config/experimental_features.py +7 -7
  172. claude_mpm/config/model_config.py +428 -0
  173. claude_mpm/config/paths.py +3 -2
  174. claude_mpm/config/socketio_config.py +36 -7
  175. claude_mpm/constants.py +27 -1
  176. claude_mpm/core/__init__.py +53 -17
  177. claude_mpm/core/agent_name_normalizer.py +3 -2
  178. claude_mpm/core/agent_registry.py +2 -2
  179. claude_mpm/core/agent_session_manager.py +10 -10
  180. claude_mpm/core/api_validator.py +330 -0
  181. claude_mpm/core/base_service.py +33 -23
  182. claude_mpm/core/cache.py +9 -9
  183. claude_mpm/core/claude_runner.py +19 -8
  184. claude_mpm/core/config.py +103 -8
  185. claude_mpm/core/config_aliases.py +7 -6
  186. claude_mpm/core/constants.py +65 -0
  187. claude_mpm/core/container.py +11 -5
  188. claude_mpm/core/enums.py +452 -0
  189. claude_mpm/core/error_handler.py +623 -0
  190. claude_mpm/core/factories.py +1 -1
  191. claude_mpm/core/file_utils.py +764 -0
  192. claude_mpm/core/framework/__init__.py +38 -0
  193. claude_mpm/core/framework/formatters/__init__.py +11 -0
  194. claude_mpm/core/framework/formatters/capability_generator.py +367 -0
  195. claude_mpm/core/framework/formatters/content_formatter.py +288 -0
  196. claude_mpm/core/framework/formatters/context_generator.py +185 -0
  197. claude_mpm/core/framework/loaders/__init__.py +13 -0
  198. claude_mpm/core/framework/loaders/agent_loader.py +210 -0
  199. claude_mpm/core/framework/loaders/file_loader.py +223 -0
  200. claude_mpm/core/framework/loaders/instruction_loader.py +161 -0
  201. claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
  202. claude_mpm/core/framework/processors/__init__.py +11 -0
  203. claude_mpm/core/framework/processors/memory_processor.py +230 -0
  204. claude_mpm/core/framework/processors/metadata_processor.py +146 -0
  205. claude_mpm/core/framework/processors/template_processor.py +244 -0
  206. claude_mpm/core/framework_loader.py +323 -1491
  207. claude_mpm/core/hook_manager.py +8 -6
  208. claude_mpm/core/injectable_service.py +11 -8
  209. claude_mpm/core/instruction_reinforcement_hook.py +267 -0
  210. claude_mpm/core/interactive_session.py +55 -8
  211. claude_mpm/core/interfaces.py +56 -1
  212. claude_mpm/core/lazy.py +3 -3
  213. claude_mpm/core/log_manager.py +100 -28
  214. claude_mpm/core/logger.py +19 -14
  215. claude_mpm/core/logging_config.py +6 -2
  216. claude_mpm/core/logging_utils.py +520 -0
  217. claude_mpm/core/oneshot_session.py +51 -7
  218. claude_mpm/core/optimized_agent_loader.py +9 -9
  219. claude_mpm/core/optimized_startup.py +1 -1
  220. claude_mpm/core/output_style_manager.py +12 -192
  221. claude_mpm/core/pm_hook_interceptor.py +118 -15
  222. claude_mpm/core/service_registry.py +7 -3
  223. claude_mpm/core/session_manager.py +14 -12
  224. claude_mpm/core/shared/config_loader.py +1 -1
  225. claude_mpm/core/socketio_pool.py +15 -15
  226. claude_mpm/core/tool_access_control.py +3 -2
  227. claude_mpm/core/types.py +4 -11
  228. claude_mpm/core/typing_utils.py +7 -6
  229. claude_mpm/core/unified_agent_registry.py +116 -12
  230. claude_mpm/core/unified_config.py +6 -6
  231. claude_mpm/core/unified_paths.py +23 -20
  232. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +1 -0
  233. claude_mpm/dashboard/__init__.py +12 -0
  234. claude_mpm/dashboard/analysis_runner.py +455 -0
  235. claude_mpm/dashboard/api/simple_directory.py +261 -0
  236. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +188 -0
  237. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +156 -0
  238. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +38 -0
  239. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +92 -0
  240. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +248 -0
  241. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +61 -0
  242. claude_mpm/dashboard/static/archive/test_activity_connection.html +179 -0
  243. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +68 -0
  244. claude_mpm/dashboard/static/archive/test_dashboard.html +409 -0
  245. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +519 -0
  246. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +181 -0
  247. claude_mpm/dashboard/static/archive/test_file_data.html +315 -0
  248. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +243 -0
  249. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +234 -0
  250. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +117 -0
  251. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +115 -0
  252. claude_mpm/dashboard/static/archive/test_file_viewer.html +224 -0
  253. claude_mpm/dashboard/static/archive/test_final_activity.html +220 -0
  254. claude_mpm/dashboard/static/archive/test_tab_fix.html +139 -0
  255. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +1 -0
  256. claude_mpm/dashboard/static/built/components/activity-tree.js +2 -0
  257. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +777 -0
  258. claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
  259. claude_mpm/dashboard/static/built/components/build-tracker.js +333 -0
  260. claude_mpm/dashboard/static/built/components/code-simple.js +857 -0
  261. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +353 -0
  262. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +235 -0
  263. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +409 -0
  264. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +435 -0
  265. claude_mpm/dashboard/static/built/components/code-tree.js +2 -0
  266. claude_mpm/dashboard/static/built/components/code-viewer.js +2 -0
  267. claude_mpm/dashboard/static/built/components/connection-debug.js +654 -0
  268. claude_mpm/dashboard/static/built/components/diff-viewer.js +891 -0
  269. claude_mpm/dashboard/static/built/components/event-processor.js +1 -1
  270. claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
  271. claude_mpm/dashboard/static/built/components/export-manager.js +1 -1
  272. claude_mpm/dashboard/static/built/components/file-change-tracker.js +443 -0
  273. claude_mpm/dashboard/static/built/components/file-change-viewer.js +690 -0
  274. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +1 -1
  275. claude_mpm/dashboard/static/built/components/file-viewer.js +2 -0
  276. claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
  277. claude_mpm/dashboard/static/built/components/nav-bar.js +145 -0
  278. claude_mpm/dashboard/static/built/components/page-structure.js +429 -0
  279. claude_mpm/dashboard/static/built/components/session-manager.js +1 -1
  280. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +2 -0
  281. claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
  282. claude_mpm/dashboard/static/built/connection-manager.js +536 -0
  283. claude_mpm/dashboard/static/built/dashboard.js +1 -1
  284. claude_mpm/dashboard/static/built/extension-error-handler.js +164 -0
  285. claude_mpm/dashboard/static/built/react/events.js +30 -0
  286. claude_mpm/dashboard/static/built/shared/dom-helpers.js +396 -0
  287. claude_mpm/dashboard/static/built/shared/event-bus.js +330 -0
  288. claude_mpm/dashboard/static/built/shared/event-filter-service.js +540 -0
  289. claude_mpm/dashboard/static/built/shared/logger.js +385 -0
  290. claude_mpm/dashboard/static/built/shared/page-structure.js +249 -0
  291. claude_mpm/dashboard/static/built/shared/tooltip-service.js +253 -0
  292. claude_mpm/dashboard/static/built/socket-client.js +1 -1
  293. claude_mpm/dashboard/static/built/tab-isolation-fix.js +185 -0
  294. claude_mpm/dashboard/static/css/activity.css +1958 -0
  295. claude_mpm/dashboard/static/css/dashboard.css +1413 -72
  296. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +1 -0
  297. claude_mpm/dashboard/static/dist/components/activity-tree.js +2 -0
  298. claude_mpm/dashboard/static/dist/components/agent-inference.js +1 -1
  299. claude_mpm/dashboard/static/dist/components/code-tree.js +2 -0
  300. claude_mpm/dashboard/static/dist/components/code-viewer.js +2 -0
  301. claude_mpm/dashboard/static/dist/components/event-processor.js +1 -1
  302. claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
  303. claude_mpm/dashboard/static/dist/components/export-manager.js +1 -1
  304. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +1 -1
  305. claude_mpm/dashboard/static/dist/components/file-viewer.js +2 -0
  306. claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
  307. claude_mpm/dashboard/static/dist/components/session-manager.js +1 -1
  308. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +2 -0
  309. claude_mpm/dashboard/static/dist/components/working-directory.js +1 -1
  310. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  311. claude_mpm/dashboard/static/dist/react/events.js +30 -0
  312. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  313. claude_mpm/dashboard/static/events.html +607 -0
  314. claude_mpm/dashboard/static/index.html +635 -0
  315. claude_mpm/dashboard/static/js/components/activity-tree.js +1871 -0
  316. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +4 -1
  317. claude_mpm/dashboard/static/js/components/agent-inference.js +3 -0
  318. claude_mpm/dashboard/static/js/components/build-tracker.js +23 -13
  319. claude_mpm/dashboard/static/js/components/code-simple.js +857 -0
  320. claude_mpm/dashboard/static/js/components/diff-viewer.js +891 -0
  321. claude_mpm/dashboard/static/js/components/event-processor.js +3 -107
  322. claude_mpm/dashboard/static/js/components/event-viewer.js +98 -11
  323. claude_mpm/dashboard/static/js/components/export-manager.js +3 -0
  324. claude_mpm/dashboard/static/js/components/file-change-tracker.js +443 -0
  325. claude_mpm/dashboard/static/js/components/file-change-viewer.js +690 -0
  326. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +30 -10
  327. claude_mpm/dashboard/static/js/components/file-viewer.js +580 -0
  328. claude_mpm/dashboard/static/js/components/module-viewer.js +68 -205
  329. claude_mpm/dashboard/static/js/components/session-manager.js +46 -10
  330. claude_mpm/dashboard/static/js/components/socket-manager.js +16 -0
  331. claude_mpm/dashboard/static/js/components/ui-state-manager.js +359 -40
  332. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +1824 -0
  333. claude_mpm/dashboard/static/js/components/working-directory.js +61 -10
  334. claude_mpm/dashboard/static/js/connection-manager.js +1 -1
  335. claude_mpm/dashboard/static/js/dashboard.js +523 -622
  336. claude_mpm/dashboard/static/js/shared/dom-helpers.js +396 -0
  337. claude_mpm/dashboard/static/js/shared/event-bus.js +330 -0
  338. claude_mpm/dashboard/static/js/shared/logger.js +385 -0
  339. claude_mpm/dashboard/static/js/shared/tooltip-service.js +253 -0
  340. claude_mpm/dashboard/static/js/socket-client.js +549 -62
  341. claude_mpm/dashboard/static/js/stores/dashboard-store.js +562 -0
  342. claude_mpm/dashboard/static/js/tab-isolation-fix.js +185 -0
  343. claude_mpm/dashboard/static/legacy/activity.html +736 -0
  344. claude_mpm/dashboard/static/legacy/agents.html +786 -0
  345. claude_mpm/dashboard/static/legacy/files.html +747 -0
  346. claude_mpm/dashboard/static/legacy/tools.html +831 -0
  347. claude_mpm/dashboard/static/monitors.html +431 -0
  348. claude_mpm/dashboard/static/production/events.html +659 -0
  349. claude_mpm/dashboard/static/production/main.html +698 -0
  350. claude_mpm/dashboard/static/production/monitors.html +483 -0
  351. claude_mpm/dashboard/static/socket.io.min.js +7 -0
  352. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +7 -0
  353. claude_mpm/dashboard/static/test-archive/dashboard.html +635 -0
  354. claude_mpm/dashboard/static/test-archive/debug-events.html +147 -0
  355. claude_mpm/dashboard/static/test-archive/test-navigation.html +256 -0
  356. claude_mpm/dashboard/static/test-archive/test-react-exports.html +180 -0
  357. claude_mpm/dashboard/static/test-archive/test_debug.html +25 -0
  358. claude_mpm/dashboard/templates/code_simple.html +153 -0
  359. claude_mpm/dashboard/templates/index.html +267 -9
  360. claude_mpm/experimental/__init__.py +10 -0
  361. claude_mpm/experimental/cli_enhancements.py +4 -2
  362. claude_mpm/generators/agent_profile_generator.py +5 -3
  363. claude_mpm/hooks/__init__.py +37 -1
  364. claude_mpm/hooks/base_hook.py +5 -4
  365. claude_mpm/hooks/claude_hooks/connection_pool.py +4 -4
  366. claude_mpm/hooks/claude_hooks/event_handlers.py +21 -18
  367. claude_mpm/hooks/claude_hooks/hook_handler.py +209 -25
  368. claude_mpm/hooks/claude_hooks/installer.py +783 -0
  369. claude_mpm/hooks/claude_hooks/memory_integration.py +3 -3
  370. claude_mpm/hooks/claude_hooks/response_tracking.py +57 -17
  371. claude_mpm/hooks/claude_hooks/services/connection_manager.py +64 -49
  372. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +140 -76
  373. claude_mpm/hooks/claude_hooks/services/state_manager.py +11 -9
  374. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +3 -3
  375. claude_mpm/hooks/failure_learning/__init__.py +60 -0
  376. claude_mpm/hooks/failure_learning/failure_detection_hook.py +235 -0
  377. claude_mpm/hooks/failure_learning/fix_detection_hook.py +217 -0
  378. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +286 -0
  379. claude_mpm/hooks/instruction_reinforcement.py +301 -0
  380. claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
  381. claude_mpm/hooks/kuzu_memory_hook.py +386 -0
  382. claude_mpm/hooks/kuzu_response_hook.py +183 -0
  383. claude_mpm/hooks/memory_integration_hook.py +1 -1
  384. claude_mpm/hooks/session_resume_hook.py +121 -0
  385. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  386. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  387. claude_mpm/hooks/tool_call_interceptor.py +8 -5
  388. claude_mpm/hooks/validation_hooks.py +3 -3
  389. claude_mpm/init.py +23 -4
  390. claude_mpm/models/agent_session.py +8 -6
  391. claude_mpm/models/resume_log.py +340 -0
  392. claude_mpm/schemas/__init__.py +12 -0
  393. claude_mpm/scripts/claude-hook-handler.sh +187 -0
  394. claude_mpm/scripts/launch_monitor.py +85 -0
  395. claude_mpm/scripts/mcp_server.py +3 -5
  396. claude_mpm/scripts/mpm_doctor.py +3 -2
  397. claude_mpm/scripts/socketio_daemon.py +156 -396
  398. claude_mpm/services/__init__.py +144 -160
  399. claude_mpm/services/agents/__init__.py +18 -5
  400. claude_mpm/services/agents/agent_builder.py +13 -11
  401. claude_mpm/services/agents/auto_config_manager.py +796 -0
  402. claude_mpm/services/agents/deployment/agent_config_provider.py +127 -27
  403. claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
  404. claude_mpm/services/agents/deployment/agent_deployment.py +38 -15
  405. claude_mpm/services/agents/deployment/agent_discovery_service.py +125 -7
  406. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +5 -5
  407. claude_mpm/services/agents/deployment/agent_format_converter.py +56 -12
  408. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +4 -2
  409. claude_mpm/services/agents/deployment/agent_operation_service.py +2 -2
  410. claude_mpm/services/agents/deployment/agent_record_service.py +5 -6
  411. claude_mpm/services/agents/deployment/agent_state_service.py +2 -2
  412. claude_mpm/services/agents/deployment/agent_template_builder.py +722 -37
  413. claude_mpm/services/agents/deployment/agent_validator.py +31 -7
  414. claude_mpm/services/agents/deployment/agent_version_manager.py +9 -1
  415. claude_mpm/services/agents/deployment/agent_versioning.py +1 -1
  416. claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
  417. claude_mpm/services/agents/deployment/deployment_config_loader.py +131 -7
  418. claude_mpm/services/agents/deployment/deployment_type_detector.py +10 -14
  419. claude_mpm/services/agents/deployment/deployment_wrapper.py +58 -0
  420. claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
  421. claude_mpm/services/agents/deployment/local_template_deployment.py +360 -0
  422. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +134 -38
  423. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +8 -7
  424. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
  425. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
  426. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +7 -5
  427. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
  428. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
  429. claude_mpm/services/agents/deployment/system_instructions_deployer.py +9 -6
  430. claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
  431. claude_mpm/services/agents/deployment/validation/template_validator.py +64 -44
  432. claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
  433. claude_mpm/services/agents/loading/agent_profile_loader.py +10 -9
  434. claude_mpm/services/agents/loading/base_agent_manager.py +16 -6
  435. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -2
  436. claude_mpm/services/agents/local_template_manager.py +744 -0
  437. claude_mpm/services/agents/management/agent_capabilities_generator.py +3 -2
  438. claude_mpm/services/agents/management/agent_management_service.py +5 -5
  439. claude_mpm/services/agents/memory/agent_memory_manager.py +32 -29
  440. claude_mpm/services/agents/memory/content_manager.py +17 -9
  441. claude_mpm/services/agents/memory/memory_categorization_service.py +4 -2
  442. claude_mpm/services/agents/memory/memory_file_service.py +32 -6
  443. claude_mpm/services/agents/memory/memory_format_service.py +7 -7
  444. claude_mpm/services/agents/memory/memory_limits_service.py +4 -2
  445. claude_mpm/services/agents/memory/template_generator.py +3 -3
  446. claude_mpm/services/agents/observers.py +547 -0
  447. claude_mpm/services/agents/recommender.py +615 -0
  448. claude_mpm/services/agents/registry/deployed_agent_discovery.py +3 -3
  449. claude_mpm/services/agents/registry/modification_tracker.py +30 -19
  450. claude_mpm/services/async_session_logger.py +141 -98
  451. claude_mpm/services/claude_session_logger.py +82 -74
  452. claude_mpm/services/cli/agent_cleanup_service.py +6 -5
  453. claude_mpm/services/cli/agent_dependency_service.py +1 -1
  454. claude_mpm/services/cli/agent_listing_service.py +5 -5
  455. claude_mpm/services/cli/agent_validation_service.py +6 -5
  456. claude_mpm/services/cli/memory_crud_service.py +12 -7
  457. claude_mpm/services/cli/memory_output_formatter.py +2 -2
  458. claude_mpm/services/cli/resume_service.py +617 -0
  459. claude_mpm/services/cli/session_manager.py +104 -13
  460. claude_mpm/services/cli/session_pause_manager.py +504 -0
  461. claude_mpm/services/cli/session_resume_helper.py +372 -0
  462. claude_mpm/services/cli/startup_checker.py +13 -21
  463. claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
  464. claude_mpm/services/command_deployment_service.py +17 -9
  465. claude_mpm/services/command_handler_service.py +11 -5
  466. claude_mpm/services/core/__init__.py +33 -1
  467. claude_mpm/services/core/base.py +26 -11
  468. claude_mpm/services/core/cache_manager.py +1 -3
  469. claude_mpm/services/core/interfaces/__init__.py +90 -3
  470. claude_mpm/services/core/interfaces/agent.py +184 -0
  471. claude_mpm/services/core/interfaces/health.py +172 -0
  472. claude_mpm/services/core/interfaces/model.py +281 -0
  473. claude_mpm/services/core/interfaces/process.py +372 -0
  474. claude_mpm/services/core/interfaces/project.py +121 -0
  475. claude_mpm/services/core/interfaces/restart.py +307 -0
  476. claude_mpm/services/core/interfaces/stability.py +260 -0
  477. claude_mpm/services/core/interfaces.py +56 -1
  478. claude_mpm/services/core/memory_manager.py +92 -47
  479. claude_mpm/services/core/models/__init__.py +79 -0
  480. claude_mpm/services/core/models/agent_config.py +384 -0
  481. claude_mpm/services/core/models/health.py +162 -0
  482. claude_mpm/services/core/models/process.py +239 -0
  483. claude_mpm/services/core/models/restart.py +302 -0
  484. claude_mpm/services/core/models/stability.py +264 -0
  485. claude_mpm/services/core/models/toolchain.py +306 -0
  486. claude_mpm/services/core/path_resolver.py +37 -18
  487. claude_mpm/services/core/service_container.py +2 -2
  488. claude_mpm/services/diagnostics/__init__.py +2 -2
  489. claude_mpm/services/diagnostics/checks/__init__.py +4 -2
  490. claude_mpm/services/diagnostics/checks/agent_check.py +30 -32
  491. claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
  492. claude_mpm/services/diagnostics/checks/common_issues_check.py +28 -27
  493. claude_mpm/services/diagnostics/checks/configuration_check.py +26 -25
  494. claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
  495. claude_mpm/services/diagnostics/checks/installation_check.py +165 -60
  496. claude_mpm/services/diagnostics/checks/instructions_check.py +22 -24
  497. claude_mpm/services/diagnostics/checks/mcp_check.py +57 -43
  498. claude_mpm/services/diagnostics/checks/mcp_services_check.py +1066 -0
  499. claude_mpm/services/diagnostics/checks/monitor_check.py +24 -23
  500. claude_mpm/services/diagnostics/checks/startup_log_check.py +14 -11
  501. claude_mpm/services/diagnostics/diagnostic_runner.py +22 -13
  502. claude_mpm/services/diagnostics/doctor_reporter.py +275 -47
  503. claude_mpm/services/diagnostics/models.py +37 -21
  504. claude_mpm/services/event_aggregator.py +5 -3
  505. claude_mpm/services/event_bus/direct_relay.py +152 -13
  506. claude_mpm/services/event_bus/event_bus.py +51 -9
  507. claude_mpm/services/event_bus/relay.py +33 -14
  508. claude_mpm/services/events/consumers/dead_letter.py +7 -5
  509. claude_mpm/services/events/core.py +5 -6
  510. claude_mpm/services/events/producers/hook.py +6 -6
  511. claude_mpm/services/events/producers/system.py +8 -8
  512. claude_mpm/services/exceptions.py +5 -5
  513. claude_mpm/services/framework_claude_md_generator/__init__.py +1 -1
  514. claude_mpm/services/framework_claude_md_generator/content_assembler.py +5 -5
  515. claude_mpm/services/framework_claude_md_generator/content_validator.py +2 -2
  516. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +3 -3
  517. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +2 -2
  518. claude_mpm/services/framework_claude_md_generator/version_manager.py +1 -1
  519. claude_mpm/services/hook_installer_service.py +506 -0
  520. claude_mpm/services/hook_service.py +5 -6
  521. claude_mpm/services/infrastructure/context_preservation.py +13 -11
  522. claude_mpm/services/infrastructure/daemon_manager.py +9 -9
  523. claude_mpm/services/infrastructure/logging.py +2 -2
  524. claude_mpm/services/infrastructure/monitoring/__init__.py +12 -12
  525. claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
  526. claude_mpm/services/infrastructure/monitoring/base.py +5 -13
  527. claude_mpm/services/infrastructure/monitoring/network.py +7 -6
  528. claude_mpm/services/infrastructure/monitoring/process.py +13 -12
  529. claude_mpm/services/infrastructure/monitoring/resources.py +8 -7
  530. claude_mpm/services/infrastructure/monitoring/service.py +16 -15
  531. claude_mpm/services/infrastructure/monitoring.py +12 -12
  532. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  533. claude_mpm/services/local_ops/__init__.py +165 -0
  534. claude_mpm/services/local_ops/crash_detector.py +257 -0
  535. claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
  536. claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
  537. claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
  538. claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
  539. claude_mpm/services/local_ops/health_manager.py +430 -0
  540. claude_mpm/services/local_ops/log_monitor.py +396 -0
  541. claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
  542. claude_mpm/services/local_ops/process_manager.py +595 -0
  543. claude_mpm/services/local_ops/resource_monitor.py +331 -0
  544. claude_mpm/services/local_ops/restart_manager.py +401 -0
  545. claude_mpm/services/local_ops/restart_policy.py +387 -0
  546. claude_mpm/services/local_ops/state_manager.py +372 -0
  547. claude_mpm/services/local_ops/unified_manager.py +600 -0
  548. claude_mpm/services/mcp_config_manager.py +1612 -0
  549. claude_mpm/services/mcp_gateway/__init__.py +97 -93
  550. claude_mpm/services/mcp_gateway/auto_configure.py +43 -38
  551. claude_mpm/services/mcp_gateway/config/config_loader.py +3 -3
  552. claude_mpm/services/mcp_gateway/config/configuration.py +23 -4
  553. claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
  554. claude_mpm/services/mcp_gateway/core/base.py +20 -33
  555. claude_mpm/services/mcp_gateway/core/process_pool.py +585 -31
  556. claude_mpm/services/mcp_gateway/core/singleton_manager.py +2 -2
  557. claude_mpm/services/mcp_gateway/core/startup_verification.py +3 -3
  558. claude_mpm/services/mcp_gateway/main.py +90 -15
  559. claude_mpm/services/mcp_gateway/registry/service_registry.py +4 -2
  560. claude_mpm/services/mcp_gateway/registry/tool_registry.py +12 -9
  561. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +4 -4
  562. claude_mpm/services/mcp_gateway/server/stdio_server.py +9 -15
  563. claude_mpm/services/mcp_gateway/tools/__init__.py +14 -2
  564. claude_mpm/services/mcp_gateway/tools/base_adapter.py +15 -15
  565. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +10 -9
  566. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +654 -0
  567. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +36 -34
  568. claude_mpm/services/mcp_gateway/tools/hello_world.py +8 -8
  569. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +551 -0
  570. claude_mpm/services/mcp_gateway/utils/__init__.py +14 -0
  571. claude_mpm/services/mcp_gateway/utils/package_version_checker.py +160 -0
  572. claude_mpm/services/mcp_gateway/utils/update_preferences.py +170 -0
  573. claude_mpm/services/mcp_service_verifier.py +729 -0
  574. claude_mpm/services/memory/builder.py +9 -8
  575. claude_mpm/services/memory/cache/shared_prompt_cache.py +2 -1
  576. claude_mpm/services/memory/cache/simple_cache.py +2 -2
  577. claude_mpm/services/memory/failure_tracker.py +578 -0
  578. claude_mpm/services/memory/indexed_memory.py +8 -8
  579. claude_mpm/services/memory/optimizer.py +8 -9
  580. claude_mpm/services/memory/router.py +3 -3
  581. claude_mpm/services/memory_hook_service.py +165 -4
  582. claude_mpm/services/model/__init__.py +147 -0
  583. claude_mpm/services/model/base_provider.py +365 -0
  584. claude_mpm/services/model/claude_provider.py +412 -0
  585. claude_mpm/services/model/model_router.py +453 -0
  586. claude_mpm/services/model/ollama_provider.py +415 -0
  587. claude_mpm/services/monitor/__init__.py +20 -0
  588. claude_mpm/services/monitor/daemon.py +671 -0
  589. claude_mpm/services/monitor/daemon_manager.py +963 -0
  590. claude_mpm/services/monitor/event_emitter.py +350 -0
  591. claude_mpm/services/monitor/handlers/__init__.py +21 -0
  592. claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
  593. claude_mpm/services/monitor/handlers/dashboard.py +299 -0
  594. claude_mpm/services/monitor/handlers/file.py +264 -0
  595. claude_mpm/services/monitor/handlers/hooks.py +512 -0
  596. claude_mpm/services/monitor/management/__init__.py +18 -0
  597. claude_mpm/services/monitor/management/health.py +124 -0
  598. claude_mpm/services/monitor/management/lifecycle.py +724 -0
  599. claude_mpm/services/monitor/server.py +817 -0
  600. claude_mpm/services/monitor_build_service.py +2 -2
  601. claude_mpm/services/native_agent_converter.py +356 -0
  602. claude_mpm/services/orphan_detection.py +786 -0
  603. claude_mpm/services/port_manager.py +2 -2
  604. claude_mpm/services/project/__init__.py +23 -0
  605. claude_mpm/services/project/analyzer.py +3 -3
  606. claude_mpm/services/project/architecture_analyzer.py +6 -6
  607. claude_mpm/services/project/archive_manager.py +1045 -0
  608. claude_mpm/services/project/dependency_analyzer.py +8 -8
  609. claude_mpm/services/project/detection_strategies.py +719 -0
  610. claude_mpm/services/project/documentation_manager.py +553 -0
  611. claude_mpm/services/project/enhanced_analyzer.py +572 -0
  612. claude_mpm/services/project/language_analyzer.py +3 -3
  613. claude_mpm/services/project/metrics_collector.py +7 -10
  614. claude_mpm/services/project/project_organizer.py +1005 -0
  615. claude_mpm/services/project/registry.py +13 -7
  616. claude_mpm/services/project/toolchain_analyzer.py +581 -0
  617. claude_mpm/services/project_port_allocator.py +596 -0
  618. claude_mpm/services/response_tracker.py +21 -10
  619. claude_mpm/services/runner_configuration_service.py +1 -0
  620. claude_mpm/services/self_upgrade_service.py +500 -0
  621. claude_mpm/services/session_management_service.py +7 -5
  622. claude_mpm/services/session_manager.py +380 -0
  623. claude_mpm/services/shared/__init__.py +2 -1
  624. claude_mpm/services/shared/async_service_base.py +16 -27
  625. claude_mpm/services/shared/config_service_base.py +17 -14
  626. claude_mpm/services/shared/lifecycle_service_base.py +1 -14
  627. claude_mpm/services/shared/service_factory.py +8 -5
  628. claude_mpm/services/socketio/client_proxy.py +60 -5
  629. claude_mpm/services/socketio/dashboard_server.py +361 -0
  630. claude_mpm/services/socketio/event_normalizer.py +74 -6
  631. claude_mpm/services/socketio/handlers/__init__.py +5 -0
  632. claude_mpm/services/socketio/handlers/base.py +2 -2
  633. claude_mpm/services/socketio/handlers/code_analysis.py +682 -0
  634. claude_mpm/services/socketio/handlers/connection.py +21 -40
  635. claude_mpm/services/socketio/handlers/connection_handler.py +16 -28
  636. claude_mpm/services/socketio/handlers/file.py +46 -10
  637. claude_mpm/services/socketio/handlers/git.py +8 -8
  638. claude_mpm/services/socketio/handlers/hook.py +29 -17
  639. claude_mpm/services/socketio/handlers/registry.py +4 -0
  640. claude_mpm/services/socketio/monitor_client.py +364 -0
  641. claude_mpm/services/socketio/server/broadcaster.py +9 -7
  642. claude_mpm/services/socketio/server/connection_manager.py +131 -68
  643. claude_mpm/services/socketio/server/core.py +275 -22
  644. claude_mpm/services/socketio/server/eventbus_integration.py +20 -14
  645. claude_mpm/services/socketio/server/main.py +99 -29
  646. claude_mpm/services/socketio_client_manager.py +4 -4
  647. claude_mpm/services/subprocess_launcher_service.py +19 -15
  648. claude_mpm/services/system_instructions_service.py +2 -2
  649. claude_mpm/services/ticket_services/formatter_service.py +1 -1
  650. claude_mpm/services/ticket_services/validation_service.py +5 -5
  651. claude_mpm/services/unified/__init__.py +65 -0
  652. claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
  653. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
  654. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
  655. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +903 -0
  656. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +746 -0
  657. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
  658. claude_mpm/services/unified/config_strategies/__init__.py +175 -0
  659. claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
  660. claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
  661. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
  662. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
  663. claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
  664. claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
  665. claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
  666. claude_mpm/services/unified/deployment_strategies/base.py +553 -0
  667. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
  668. claude_mpm/services/unified/deployment_strategies/local.py +607 -0
  669. claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
  670. claude_mpm/services/unified/deployment_strategies/vercel.py +475 -0
  671. claude_mpm/services/unified/interfaces.py +475 -0
  672. claude_mpm/services/unified/migration.py +509 -0
  673. claude_mpm/services/unified/strategies.py +534 -0
  674. claude_mpm/services/unified/unified_analyzer.py +542 -0
  675. claude_mpm/services/unified/unified_config.py +691 -0
  676. claude_mpm/services/unified/unified_deployment.py +470 -0
  677. claude_mpm/services/utility_service.py +6 -3
  678. claude_mpm/services/version_control/branch_strategy.py +2 -2
  679. claude_mpm/services/version_control/conflict_resolution.py +8 -4
  680. claude_mpm/services/version_control/git_operations.py +26 -24
  681. claude_mpm/services/version_control/semantic_versioning.py +14 -14
  682. claude_mpm/services/version_control/version_parser.py +14 -11
  683. claude_mpm/services/version_service.py +104 -1
  684. claude_mpm/services/visualization/__init__.py +19 -0
  685. claude_mpm/services/visualization/mermaid_generator.py +938 -0
  686. claude_mpm/skills/__init__.py +42 -0
  687. claude_mpm/skills/agent_skills_injector.py +324 -0
  688. claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
  689. claude_mpm/skills/bundled/__init__.py +6 -0
  690. claude_mpm/skills/bundled/api-documentation.md +393 -0
  691. claude_mpm/skills/bundled/async-testing.md +571 -0
  692. claude_mpm/skills/bundled/code-review.md +143 -0
  693. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  694. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  695. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  696. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  697. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  698. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  699. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  700. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  701. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  702. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  703. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  704. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  705. claude_mpm/skills/bundled/database-migration.md +199 -0
  706. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  707. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  708. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  709. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  710. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  711. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  712. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  713. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  714. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  715. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  716. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  717. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  718. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  719. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  720. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  721. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  722. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  723. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  724. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  725. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  726. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  727. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  728. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  729. claude_mpm/skills/bundled/git-workflow.md +414 -0
  730. claude_mpm/skills/bundled/imagemagick.md +204 -0
  731. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  732. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  733. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  734. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  735. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  736. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  737. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  738. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  739. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  740. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  741. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  742. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  743. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  744. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  745. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  746. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
  747. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
  748. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  749. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  750. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  751. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  752. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  753. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  754. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
  755. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
  756. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
  757. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  758. claude_mpm/skills/bundled/pdf.md +141 -0
  759. claude_mpm/skills/bundled/performance-profiling.md +573 -0
  760. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  761. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  762. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  763. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  764. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  765. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  766. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  767. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  768. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  769. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  770. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  771. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  772. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  773. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  774. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  775. claude_mpm/skills/bundled/security-scanning.md +327 -0
  776. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  777. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  778. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  779. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  780. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  781. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  782. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  783. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  784. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  785. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  786. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  787. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  788. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  789. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  790. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  791. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  792. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  793. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
  794. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
  795. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
  796. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  797. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  798. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
  799. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  800. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  801. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  802. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  803. claude_mpm/skills/bundled/xlsx.md +157 -0
  804. claude_mpm/skills/registry.py +286 -0
  805. claude_mpm/skills/skill_manager.py +310 -0
  806. claude_mpm/skills/skills_registry.py +348 -0
  807. claude_mpm/skills/skills_service.py +739 -0
  808. claude_mpm/storage/state_storage.py +31 -31
  809. claude_mpm/tools/__init__.py +10 -0
  810. claude_mpm/tools/__main__.py +208 -0
  811. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  812. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  813. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  814. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  815. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  816. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  817. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  818. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  819. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  820. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  821. claude_mpm/tools/code_tree_builder.py +631 -0
  822. claude_mpm/tools/code_tree_events.py +420 -0
  823. claude_mpm/tools/socketio_debug.py +671 -0
  824. claude_mpm/utils/agent_dependency_loader.py +108 -27
  825. claude_mpm/utils/common.py +544 -0
  826. claude_mpm/utils/config_manager.py +12 -6
  827. claude_mpm/utils/database_connector.py +298 -0
  828. claude_mpm/utils/dependency_cache.py +2 -2
  829. claude_mpm/utils/dependency_strategies.py +15 -10
  830. claude_mpm/utils/display_helper.py +260 -0
  831. claude_mpm/utils/environment_context.py +4 -3
  832. claude_mpm/utils/error_handler.py +5 -3
  833. claude_mpm/utils/file_utils.py +13 -14
  834. claude_mpm/utils/git_analyzer.py +407 -0
  835. claude_mpm/utils/log_cleanup.py +627 -0
  836. claude_mpm/utils/path_operations.py +7 -4
  837. claude_mpm/utils/robust_installer.py +133 -24
  838. claude_mpm/utils/session_logging.py +2 -2
  839. claude_mpm/utils/subprocess_utils.py +9 -8
  840. claude_mpm/validation/agent_validator.py +6 -6
  841. claude_mpm/validation/frontmatter_validator.py +6 -6
  842. claude_mpm-4.24.0.dist-info/METADATA +675 -0
  843. claude_mpm-4.24.0.dist-info/RECORD +1018 -0
  844. {claude_mpm-4.1.6.dist-info → claude_mpm-4.24.0.dist-info}/entry_points.txt +1 -0
  845. claude_mpm/agents/INSTRUCTIONS.md +0 -237
  846. claude_mpm/agents/schema/agent_schema.json +0 -314
  847. claude_mpm/agents/templates/agent-manager.md +0 -304
  848. claude_mpm/cli/commands/configure_tui.py +0 -1921
  849. claude_mpm/cli/commands/socketio_monitor.py +0 -233
  850. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
  851. claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1040
  852. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
  853. claude_mpm/scripts/socketio_daemon_hardened.py +0 -937
  854. claude_mpm/scripts/socketio_server_manager.py +0 -349
  855. claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
  856. claude_mpm/services/cli/dashboard_launcher.py +0 -424
  857. claude_mpm/services/cli/socketio_manager.py +0 -498
  858. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +0 -286
  859. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +0 -645
  860. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +0 -602
  861. claude_mpm/services/project/analyzer_refactored.py +0 -450
  862. claude_mpm-4.1.6.dist-info/METADATA +0 -325
  863. claude_mpm-4.1.6.dist-info/RECORD +0 -550
  864. {claude_mpm-4.1.6.dist-info → claude_mpm-4.24.0.dist-info}/WHEEL +0 -0
  865. {claude_mpm-4.1.6.dist-info → claude_mpm-4.24.0.dist-info}/licenses/LICENSE +0 -0
  866. {claude_mpm-4.1.6.dist-info → claude_mpm-4.24.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1045 @@
1
+ """
2
+ Archive Manager Service for Claude MPM Documentation Versioning
3
+ ==============================================================
4
+
5
+ This service manages archival and versioning of project documentation,
6
+ particularly CLAUDE.md and related files during updates.
7
+
8
+ Key Features:
9
+ - Automatic backup before updates
10
+ - Timestamped archive files
11
+ - Version comparison and diff generation
12
+ - Archive cleanup and rotation
13
+ - Restoration capabilities
14
+
15
+ Author: Claude MPM Development Team
16
+ Created: 2025-01-26
17
+ """
18
+
19
+ import contextlib
20
+ import difflib
21
+ import gzip
22
+ import hashlib
23
+ import json
24
+ import re
25
+ import shutil
26
+ import subprocess
27
+ from datetime import datetime, timedelta, timezone
28
+ from pathlib import Path
29
+ from typing import Dict, List, Optional, Tuple
30
+
31
+ from rich.console import Console
32
+ from rich.table import Table
33
+
34
+ from claude_mpm.core.logging_utils import get_logger
35
+
36
+ logger = get_logger(__name__)
37
+ console = Console()
38
+
39
+
40
+ class ArchiveManager:
41
+ """Manages documentation archival and versioning."""
42
+
43
+ # Archive settings
44
+ ARCHIVE_DIR = "docs/_archive"
45
+ MAX_ARCHIVES = 10 # Maximum number of archives to keep per file
46
+ COMPRESS_AFTER_DAYS = 7 # Compress archives older than this
47
+ DELETE_AFTER_DAYS = 90 # Delete archives older than this
48
+
49
+ def __init__(self, project_path: Path):
50
+ """Initialize the archive manager."""
51
+ self.project_path = project_path
52
+ self.archive_path = project_path / self.ARCHIVE_DIR
53
+ self.is_git_repo = (project_path / ".git").exists()
54
+ self._ensure_archive_directory()
55
+
56
+ # Documentation patterns
57
+ self.version_patterns = {
58
+ "semantic": re.compile(r"v?(\d+)\.(\d+)\.(\d+)"),
59
+ "date": re.compile(r"(\d{4})-(\d{2})-(\d{2})"),
60
+ "build": re.compile(r"build[.\-](\d+)"),
61
+ }
62
+
63
+ # Key documentation files to track
64
+ self.key_docs = {
65
+ "CLAUDE.md": "Project instructions and guidelines",
66
+ "README.md": "Project overview and setup",
67
+ "CHANGELOG.md": "Version history and changes",
68
+ "docs/README.md": "Documentation index",
69
+ }
70
+
71
+ def _ensure_archive_directory(self) -> None:
72
+ """Ensure archive directory exists."""
73
+ self.archive_path.mkdir(parents=True, exist_ok=True)
74
+
75
+ # Create README if not exists
76
+ readme_path = self.archive_path / "README.md"
77
+ if not readme_path.exists():
78
+ readme_content = """# Documentation Archives
79
+
80
+ This directory contains archived versions of project documentation files.
81
+
82
+ ## Archive Naming Convention
83
+
84
+ Files are archived with timestamps:
85
+ - `CLAUDE.md.2024-01-15T10-30-45.md` - Regular archive
86
+ - `CLAUDE.md.2024-01-15T10-30-45.md.gz` - Compressed archive (older than 7 days)
87
+
88
+ ## Archive Management
89
+
90
+ - Archives are created automatically when documentation is updated
91
+ - Older archives are compressed after 7 days
92
+ - Archives older than 90 days are automatically deleted
93
+ - Maximum of 10 archives kept per file
94
+
95
+ ## Restoration
96
+
97
+ To restore an archived file:
98
+ 1. Find the desired version by timestamp
99
+ 2. Copy it back to the project root
100
+ 3. Rename to remove the timestamp
101
+
102
+ Generated by Claude MPM Archive Manager
103
+ """
104
+ readme_path.write_text(readme_content)
105
+
106
+ def archive_file(
107
+ self,
108
+ file_path: Path,
109
+ reason: Optional[str] = None,
110
+ metadata: Optional[Dict] = None,
111
+ ) -> Optional[Path]:
112
+ """Archive a file with timestamp and optional metadata."""
113
+ if not file_path.exists():
114
+ logger.warning(f"File {file_path} does not exist, cannot archive")
115
+ return None
116
+
117
+ try:
118
+ # Generate archive filename
119
+ timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H-%M-%S")
120
+ archive_name = f"{file_path.name}.{timestamp}{file_path.suffix}"
121
+ archive_file_path = self.archive_path / archive_name
122
+
123
+ # Copy file to archive
124
+ shutil.copy2(file_path, archive_file_path)
125
+ logger.info(f"Archived {file_path.name} to {archive_file_path}")
126
+
127
+ # Create metadata file if provided
128
+ if metadata or reason:
129
+ meta_data = metadata or {}
130
+ meta_data.update(
131
+ {
132
+ "original_path": str(file_path),
133
+ "archived_at": datetime.now(timezone.utc).isoformat(),
134
+ "reason": reason or "Manual archive",
135
+ "file_size": file_path.stat().st_size,
136
+ "file_hash": self._calculate_file_hash(file_path),
137
+ }
138
+ )
139
+
140
+ meta_path = self.archive_path / f"{archive_name}.meta.json"
141
+ meta_path.write_text(json.dumps(meta_data, indent=2))
142
+
143
+ # Cleanup old archives
144
+ self._cleanup_archives(file_path.name)
145
+
146
+ return archive_file_path
147
+
148
+ except Exception as e:
149
+ logger.error(f"Failed to archive {file_path}: {e}")
150
+ return None
151
+
152
+ def _calculate_file_hash(self, file_path: Path) -> str:
153
+ """Calculate MD5 hash of file."""
154
+ hasher = hashlib.md5()
155
+ with file_path.open("rb") as f:
156
+ for chunk in iter(lambda: f.read(4096), b""):
157
+ hasher.update(chunk)
158
+ return hasher.hexdigest()
159
+
160
+ def _cleanup_archives(self, original_filename: str) -> None:
161
+ """Clean up old archives for a specific file."""
162
+ # Find all archives for this file
163
+ archives = self._find_archives(original_filename)
164
+
165
+ # Sort by modification time
166
+ archives.sort(key=lambda p: p.stat().st_mtime)
167
+
168
+ # Remove oldest if exceeding max count
169
+ if len(archives) > self.MAX_ARCHIVES:
170
+ for archive in archives[: -self.MAX_ARCHIVES]:
171
+ self._remove_archive(archive)
172
+ logger.info(f"Removed old archive: {archive.name}")
173
+
174
+ # Compress old archives
175
+ cutoff_compress = datetime.now(timezone.utc) - timedelta(
176
+ days=self.COMPRESS_AFTER_DAYS
177
+ )
178
+ for archive in archives:
179
+ if archive.suffix != ".gz":
180
+ mtime = datetime.fromtimestamp(archive.stat().st_mtime)
181
+ if mtime < cutoff_compress:
182
+ self._compress_archive(archive)
183
+
184
+ # Delete very old archives
185
+ cutoff_delete = datetime.now(timezone.utc) - timedelta(
186
+ days=self.DELETE_AFTER_DAYS
187
+ )
188
+ for archive in archives:
189
+ mtime = datetime.fromtimestamp(archive.stat().st_mtime)
190
+ if mtime < cutoff_delete:
191
+ self._remove_archive(archive)
192
+ logger.info(f"Deleted old archive: {archive.name}")
193
+
194
+ def _find_archives(self, original_filename: str) -> List[Path]:
195
+ """Find all archives for a specific file."""
196
+ archives = []
197
+ pattern = f"{original_filename}.*"
198
+
199
+ for file in self.archive_path.glob(pattern):
200
+ # Skip metadata files
201
+ if not file.name.endswith(".meta.json"):
202
+ archives.append(file)
203
+
204
+ return archives
205
+
206
+ def _compress_archive(self, archive_path: Path) -> None:
207
+ """Compress an archive file using gzip."""
208
+ try:
209
+ compressed_path = archive_path.with_suffix(archive_path.suffix + ".gz")
210
+
211
+ with archive_path.open("rb") as f_in:
212
+ with gzip.open(compressed_path, "wb") as f_out:
213
+ shutil.copyfileobj(f_in, f_out)
214
+
215
+ # Remove original after successful compression
216
+ archive_path.unlink()
217
+ logger.debug(f"Compressed archive: {archive_path.name}")
218
+
219
+ # Update metadata file if exists
220
+ meta_path = self.archive_path / f"{archive_path.name}.meta.json"
221
+ if meta_path.exists():
222
+ new_meta_path = self.archive_path / f"{compressed_path.name}.meta.json"
223
+ meta_path.rename(new_meta_path)
224
+
225
+ except Exception as e:
226
+ logger.error(f"Failed to compress {archive_path}: {e}")
227
+
228
+ def _remove_archive(self, archive_path: Path) -> None:
229
+ """Remove an archive and its metadata."""
230
+ try:
231
+ # Remove main file
232
+ if archive_path.exists():
233
+ archive_path.unlink()
234
+
235
+ # Remove metadata if exists
236
+ meta_path = self.archive_path / f"{archive_path.name}.meta.json"
237
+ if meta_path.exists():
238
+ meta_path.unlink()
239
+
240
+ except Exception as e:
241
+ logger.error(f"Failed to remove archive {archive_path}: {e}")
242
+
243
+ def list_archives(
244
+ self, filename: Optional[str] = None, include_metadata: bool = False
245
+ ) -> List[Dict]:
246
+ """List all archives or archives for a specific file."""
247
+ archives = []
248
+
249
+ if filename:
250
+ archive_files = self._find_archives(filename)
251
+ else:
252
+ archive_files = [
253
+ f
254
+ for f in self.archive_path.glob("*")
255
+ if not f.name.endswith(".meta.json") and f.name != "README.md"
256
+ ]
257
+
258
+ for archive_file in archive_files:
259
+ info = {
260
+ "name": archive_file.name,
261
+ "path": str(archive_file),
262
+ "size": archive_file.stat().st_size,
263
+ "modified": datetime.fromtimestamp(
264
+ archive_file.stat().st_mtime
265
+ ).isoformat(),
266
+ "compressed": archive_file.suffix == ".gz",
267
+ }
268
+
269
+ # Add metadata if requested and available
270
+ if include_metadata:
271
+ meta_path = self.archive_path / f"{archive_file.name}.meta.json"
272
+ if meta_path.exists():
273
+ with contextlib.suppress(Exception):
274
+ info["metadata"] = json.loads(meta_path.read_text())
275
+
276
+ archives.append(info)
277
+
278
+ # Sort by modification time, newest first
279
+ archives.sort(key=lambda x: x["modified"], reverse=True)
280
+
281
+ return archives
282
+
283
+ def get_latest_archive(self, filename: str) -> Optional[Path]:
284
+ """Get the most recent archive for a file."""
285
+ archives = self._find_archives(filename)
286
+ if not archives:
287
+ return None
288
+
289
+ # Sort by modification time and return latest
290
+ archives.sort(key=lambda p: p.stat().st_mtime, reverse=True)
291
+ return archives[0]
292
+
293
+ def restore_archive(
294
+ self, archive_name: str, target_path: Optional[Path] = None
295
+ ) -> Tuple[bool, str]:
296
+ """Restore an archived file to its original location or specified path."""
297
+ archive_file = self.archive_path / archive_name
298
+
299
+ if not archive_file.exists():
300
+ return False, f"Archive {archive_name} not found"
301
+
302
+ try:
303
+ # Determine target path
304
+ if target_path is None:
305
+ # Extract original filename from archive name
306
+ # Format: original.ext.timestamp.ext[.gz]
307
+ parts = archive_name.split(".")
308
+ if archive_name.endswith(".gz"):
309
+ # Remove .gz and timestamp
310
+ original_name = ".".join(parts[:-3])
311
+ else:
312
+ # Remove timestamp
313
+ original_name = ".".join(parts[:-2])
314
+ target_path = self.project_path / original_name
315
+
316
+ # Backup current file if it exists
317
+ if target_path.exists():
318
+ self.archive_file(
319
+ target_path,
320
+ reason="Backup before restoration",
321
+ metadata={"restoration_from": archive_name},
322
+ )
323
+
324
+ # Restore file
325
+ if archive_file.suffix == ".gz":
326
+ # Decompress first
327
+ with gzip.open(archive_file, "rb") as f_in:
328
+ with target_path.open("wb") as f_out:
329
+ shutil.copyfileobj(f_in, f_out)
330
+ else:
331
+ shutil.copy2(archive_file, target_path)
332
+
333
+ logger.info(f"Restored {archive_name} to {target_path}")
334
+ return True, f"Successfully restored to {target_path}"
335
+
336
+ except Exception as e:
337
+ logger.error(f"Failed to restore {archive_name}: {e}")
338
+ return False, f"Restoration failed: {e!s}"
339
+
340
+ def compare_with_archive(self, current_file: Path, archive_name: str) -> Dict:
341
+ """Compare current file with an archived version."""
342
+ archive_file = self.archive_path / archive_name
343
+
344
+ if not archive_file.exists():
345
+ return {"error": f"Archive {archive_name} not found"}
346
+
347
+ if not current_file.exists():
348
+ return {"error": f"Current file {current_file} not found"}
349
+
350
+ try:
351
+ # Read archived content
352
+ if archive_file.suffix == ".gz":
353
+ with gzip.open(archive_file, "rt", encoding="utf-8") as f:
354
+ archive_content = f.read()
355
+ else:
356
+ archive_content = archive_file.read_text()
357
+
358
+ # Read current content
359
+ current_content = current_file.read_text()
360
+
361
+ # Calculate differences
362
+ current_lines = current_content.splitlines()
363
+ archive_lines = archive_content.splitlines()
364
+
365
+ return {
366
+ "current_file": str(current_file),
367
+ "archive_file": archive_name,
368
+ "current_lines": len(current_lines),
369
+ "archive_lines": len(archive_lines),
370
+ "lines_added": len(current_lines) - len(archive_lines),
371
+ "current_size": len(current_content),
372
+ "archive_size": len(archive_content),
373
+ "size_change": len(current_content) - len(archive_content),
374
+ "current_hash": self._calculate_file_hash(current_file),
375
+ "identical": current_content == archive_content,
376
+ }
377
+
378
+ except Exception as e:
379
+ return {"error": f"Comparison failed: {e!s}"}
380
+
381
+ def create_archive_report(self) -> Dict:
382
+ """Generate a report of all archives."""
383
+ report = {
384
+ "archive_directory": str(self.archive_path),
385
+ "total_archives": 0,
386
+ "total_size": 0,
387
+ "compressed_count": 0,
388
+ "files_tracked": {},
389
+ "oldest_archive": None,
390
+ "newest_archive": None,
391
+ }
392
+
393
+ archives = self.list_archives(include_metadata=True)
394
+ report["total_archives"] = len(archives)
395
+
396
+ for archive in archives:
397
+ report["total_size"] += archive["size"]
398
+ if archive["compressed"]:
399
+ report["compressed_count"] += 1
400
+
401
+ # Track by original file
402
+ original = archive["name"].split(".")[0]
403
+ if original not in report["files_tracked"]:
404
+ report["files_tracked"][original] = {
405
+ "count": 0,
406
+ "total_size": 0,
407
+ "versions": [],
408
+ }
409
+
410
+ report["files_tracked"][original]["count"] += 1
411
+ report["files_tracked"][original]["total_size"] += archive["size"]
412
+ report["files_tracked"][original]["versions"].append(archive["name"])
413
+
414
+ # Find oldest and newest
415
+ if archives:
416
+ report["oldest_archive"] = archives[-1]["name"]
417
+ report["newest_archive"] = archives[0]["name"]
418
+
419
+ return report
420
+
421
+ def auto_archive_before_update(
422
+ self, file_path: Path, update_reason: str = "Before update"
423
+ ) -> bool:
424
+ """Automatically archive a file before updating it."""
425
+ if not file_path.exists():
426
+ logger.debug(f"File {file_path} does not exist, skipping archive")
427
+ return True
428
+
429
+ # Check if content has changed since last archive
430
+ latest = self.get_latest_archive(file_path.name)
431
+ if latest:
432
+ comparison = self.compare_with_archive(file_path, latest.name)
433
+ if comparison.get("identical"):
434
+ logger.debug(f"File {file_path.name} unchanged, skipping archive")
435
+ return True
436
+
437
+ # Archive the file
438
+ result = self.archive_file(
439
+ file_path,
440
+ reason=update_reason,
441
+ metadata={
442
+ "update_type": "mpm-init",
443
+ "auto_archive": True,
444
+ },
445
+ )
446
+
447
+ return result is not None
448
+
449
+ # ========== Git Integration Methods ==========
450
+
451
+ def _run_git_command(self, args: List[str]) -> Optional[str]:
452
+ """Run a git command and return output."""
453
+ if not self.is_git_repo:
454
+ return None
455
+
456
+ try:
457
+ result = subprocess.run(
458
+ ["git", *args],
459
+ cwd=self.project_path,
460
+ capture_output=True,
461
+ text=True,
462
+ check=True,
463
+ )
464
+ return result.stdout.strip()
465
+ except subprocess.CalledProcessError as e:
466
+ logger.debug(f"Git command failed: {e}")
467
+ return None
468
+
469
+ def get_file_git_history(self, file_path: Path, limit: int = 10) -> List[Dict]:
470
+ """Get git commit history for a specific file."""
471
+ if not self.is_git_repo or not file_path.exists():
472
+ return []
473
+
474
+ relative_path = file_path.relative_to(self.project_path)
475
+ output = self._run_git_command(
476
+ [
477
+ "log",
478
+ f"-{limit}",
479
+ "--pretty=format:%H|%an|%at|%s",
480
+ "--follow",
481
+ str(relative_path),
482
+ ]
483
+ )
484
+
485
+ if not output:
486
+ return []
487
+
488
+ commits = []
489
+ for line in output.splitlines():
490
+ parts = line.split("|", 3)
491
+ if len(parts) == 4:
492
+ commits.append(
493
+ {
494
+ "hash": parts[0][:8],
495
+ "author": parts[1],
496
+ "date": datetime.fromtimestamp(int(parts[2])).isoformat(),
497
+ "message": parts[3],
498
+ }
499
+ )
500
+ return commits
501
+
502
+ def get_file_last_modified(self, file_path: Path) -> Optional[datetime]:
503
+ """Get the last git modification date for a file."""
504
+ if not self.is_git_repo or not file_path.exists():
505
+ return None
506
+
507
+ relative_path = file_path.relative_to(self.project_path)
508
+ output = self._run_git_command(
509
+ [
510
+ "log",
511
+ "-1",
512
+ "--format=%at",
513
+ str(relative_path),
514
+ ]
515
+ )
516
+
517
+ if output:
518
+ return datetime.fromtimestamp(int(output))
519
+ return None
520
+
521
+ # ========== Documentation Review Methods ==========
522
+
523
+ def review_documentation(self, check_git: bool = True) -> Dict:
524
+ """Comprehensive documentation review with outdated detection."""
525
+ report = {
526
+ "timestamp": datetime.now(timezone.utc).isoformat(),
527
+ "files_reviewed": {},
528
+ "outdated_sections": [],
529
+ "synchronization_issues": [],
530
+ "recommendations": [],
531
+ }
532
+
533
+ # Review each key documentation file
534
+ for doc_file, _description in self.key_docs.items():
535
+ file_path = self.project_path / doc_file
536
+ if file_path.exists():
537
+ file_report = self._review_single_doc(file_path, check_git)
538
+ report["files_reviewed"][doc_file] = file_report
539
+
540
+ # Check for outdated content
541
+ if file_report.get("outdated_indicators"):
542
+ report["outdated_sections"].append(
543
+ {
544
+ "file": doc_file,
545
+ "indicators": file_report["outdated_indicators"],
546
+ }
547
+ )
548
+
549
+ # Check synchronization between docs
550
+ sync_issues = self._check_documentation_sync()
551
+ if sync_issues:
552
+ report["synchronization_issues"] = sync_issues
553
+
554
+ # Generate recommendations
555
+ report["recommendations"] = self._generate_recommendations(report)
556
+
557
+ return report
558
+
559
+ def _review_single_doc(self, file_path: Path, check_git: bool) -> Dict:
560
+ """Review a single documentation file for outdated content."""
561
+ content = file_path.read_text()
562
+ report = {
563
+ "exists": True,
564
+ "size": len(content),
565
+ "lines": len(content.splitlines()),
566
+ "last_modified": file_path.stat().st_mtime,
567
+ "outdated_indicators": [],
568
+ "version_references": [],
569
+ }
570
+
571
+ # Check git history if available
572
+ if check_git and self.is_git_repo:
573
+ git_history = self.get_file_git_history(file_path, limit=5)
574
+ if git_history:
575
+ report["last_git_update"] = git_history[0]["date"]
576
+ report["recent_changes"] = len(git_history)
577
+
578
+ # Find version references
579
+ for pattern_name, pattern in self.version_patterns.items():
580
+ matches = pattern.findall(content)
581
+ if matches:
582
+ report["version_references"].append(
583
+ {
584
+ "type": pattern_name,
585
+ "versions": matches[:5], # First 5 matches
586
+ }
587
+ )
588
+
589
+ # Detect outdated indicators
590
+ outdated_indicators = self._detect_outdated_content(content, file_path.name)
591
+ if outdated_indicators:
592
+ report["outdated_indicators"] = outdated_indicators
593
+
594
+ return report
595
+
596
+ def _detect_outdated_content(self, content: str, filename: str) -> List[Dict]:
597
+ """Detect potentially outdated content in documentation."""
598
+ indicators = []
599
+ lines = content.splitlines()
600
+
601
+ # Pattern-based outdated detection
602
+ outdated_patterns = [
603
+ (r"TODO|FIXME|XXX", "Unresolved TODOs"),
604
+ (r"deprecated|obsolete|legacy", "Deprecated references"),
605
+ (r"coming soon|upcoming|future release", "Future tense content"),
606
+ (r"alpha|beta|experimental", "Pre-release indicators"),
607
+ (r"temporary|workaround|hack", "Temporary solutions"),
608
+ ]
609
+
610
+ for pattern, description in outdated_patterns:
611
+ regex = re.compile(pattern, re.IGNORECASE)
612
+ for i, line in enumerate(lines, 1):
613
+ if regex.search(line):
614
+ indicators.append(
615
+ {
616
+ "line": i,
617
+ "type": description,
618
+ "content": line.strip()[:100], # First 100 chars
619
+ }
620
+ )
621
+
622
+ # Check for old version numbers if VERSION file exists
623
+ version_file = self.project_path / "VERSION"
624
+ if version_file.exists():
625
+ current_version = version_file.read_text().strip()
626
+ old_version_pattern = re.compile(r"v?(\d+)\.(\d+)\.(\d+)")
627
+
628
+ for match in old_version_pattern.finditer(content):
629
+ found_version = match.group(0)
630
+ if found_version != current_version and self._is_older_version(
631
+ found_version, current_version
632
+ ):
633
+ pos = content[: match.start()].count("\n") + 1
634
+ indicators.append(
635
+ {
636
+ "line": pos,
637
+ "type": "Old version reference",
638
+ "content": f"Found {found_version} (current: {current_version})",
639
+ }
640
+ )
641
+
642
+ return indicators[:20] # Limit to 20 most relevant
643
+
644
+ def _is_older_version(self, version1: str, version2: str) -> bool:
645
+ """Compare two version strings."""
646
+ try:
647
+ # Parse semantic versions
648
+ v1_match = self.version_patterns["semantic"].search(version1)
649
+ v2_match = self.version_patterns["semantic"].search(version2)
650
+
651
+ if v1_match and v2_match:
652
+ v1 = tuple(map(int, v1_match.groups()))
653
+ v2 = tuple(map(int, v2_match.groups()))
654
+ return v1 < v2
655
+ except Exception:
656
+ pass
657
+ return False
658
+
659
+ def _check_documentation_sync(self) -> List[Dict]:
660
+ """Check synchronization between key documentation files."""
661
+ issues = []
662
+
663
+ # Check CLAUDE.md vs README.md
664
+ claude_path = self.project_path / "CLAUDE.md"
665
+ readme_path = self.project_path / "README.md"
666
+
667
+ if claude_path.exists() and readme_path.exists():
668
+ claude_content = claude_path.read_text()
669
+ readme_content = readme_path.read_text()
670
+
671
+ # Check for version discrepancies
672
+ claude_versions = self.version_patterns["semantic"].findall(claude_content)
673
+ readme_versions = self.version_patterns["semantic"].findall(readme_content)
674
+
675
+ if claude_versions and readme_versions:
676
+ if claude_versions[0] != readme_versions[0]:
677
+ issues.append(
678
+ {
679
+ "type": "Version mismatch",
680
+ "files": ["CLAUDE.md", "README.md"],
681
+ "details": f"CLAUDE.md: {claude_versions[0]}, README.md: {readme_versions[0]}",
682
+ }
683
+ )
684
+
685
+ # Check for project name consistency
686
+ project_names = re.findall(
687
+ r"Claude MPM|claude-mpm", readme_content, re.IGNORECASE
688
+ )
689
+ if project_names:
690
+ unique_names = set(project_names)
691
+ if len(unique_names) > 1:
692
+ issues.append(
693
+ {
694
+ "type": "Inconsistent project naming",
695
+ "files": ["README.md"],
696
+ "details": f"Found variations: {', '.join(unique_names)}",
697
+ }
698
+ )
699
+
700
+ # Check CHANGELOG.md exists and is recent
701
+ changelog_path = self.project_path / "CHANGELOG.md"
702
+ if changelog_path.exists():
703
+ last_modified = self.get_file_last_modified(changelog_path)
704
+ if last_modified:
705
+ days_old = (datetime.now(timezone.utc) - last_modified).days
706
+ if days_old > 30:
707
+ issues.append(
708
+ {
709
+ "type": "Stale changelog",
710
+ "files": ["CHANGELOG.md"],
711
+ "details": f"Last updated {days_old} days ago",
712
+ }
713
+ )
714
+ else:
715
+ issues.append(
716
+ {
717
+ "type": "Missing file",
718
+ "files": ["CHANGELOG.md"],
719
+ "details": "CHANGELOG.md does not exist",
720
+ }
721
+ )
722
+
723
+ return issues
724
+
725
+ def _generate_recommendations(self, report: Dict) -> List[str]:
726
+ """Generate actionable recommendations from review report."""
727
+ recommendations = []
728
+
729
+ # Check for outdated content
730
+ if report["outdated_sections"]:
731
+ recommendations.append(
732
+ f"📝 Review and update {len(report['outdated_sections'])} files with outdated content"
733
+ )
734
+
735
+ # Check for sync issues
736
+ if report["synchronization_issues"]:
737
+ for issue in report["synchronization_issues"]:
738
+ if issue["type"] == "Version mismatch":
739
+ recommendations.append(
740
+ "🔄 Synchronize version numbers across documentation files"
741
+ )
742
+ elif issue["type"] == "Stale changelog":
743
+ recommendations.append("📅 Update CHANGELOG.md with recent changes")
744
+ elif issue["type"] == "Missing file":
745
+ recommendations.append(f"➕ Create missing {issue['files'][0]}")
746
+
747
+ # Check for TODO items
748
+ total_todos = sum(
749
+ len(
750
+ [
751
+ i
752
+ for i in file_report.get("outdated_indicators", [])
753
+ if i["type"] == "Unresolved TODOs"
754
+ ]
755
+ )
756
+ for file_report in report["files_reviewed"].values()
757
+ )
758
+ if total_todos > 0:
759
+ recommendations.append(
760
+ f"✅ Resolve {total_todos} TODO items in documentation"
761
+ )
762
+
763
+ # Check for deprecated references
764
+ deprecated_count = sum(
765
+ len(
766
+ [
767
+ i
768
+ for i in file_report.get("outdated_indicators", [])
769
+ if "deprecated" in i["type"].lower()
770
+ ]
771
+ )
772
+ for file_report in report["files_reviewed"].values()
773
+ )
774
+ if deprecated_count > 0:
775
+ recommendations.append(f"⚠️ Update {deprecated_count} deprecated references")
776
+
777
+ return recommendations
778
+
779
+ def auto_detect_and_archive_outdated(self, dry_run: bool = False) -> Dict:
780
+ """Automatically detect and archive outdated documentation."""
781
+ result = {
782
+ "reviewed_files": [],
783
+ "archived_files": [],
784
+ "skipped_files": [],
785
+ }
786
+
787
+ # Review documentation
788
+ review = self.review_documentation()
789
+
790
+ for filename, file_report in review["files_reviewed"].items():
791
+ file_path = self.project_path / filename
792
+ result["reviewed_files"].append(filename)
793
+
794
+ # Determine if file should be archived
795
+ should_archive = False
796
+ archive_reason = []
797
+
798
+ # Check for significant outdated content
799
+ outdated_count = len(file_report.get("outdated_indicators", []))
800
+ if outdated_count > 10:
801
+ should_archive = True
802
+ archive_reason.append(f"{outdated_count} outdated indicators")
803
+
804
+ # Check if file hasn't been updated in git for long time
805
+ if file_report.get("last_git_update"):
806
+ last_update = datetime.fromisoformat(file_report["last_git_update"])
807
+ days_old = (datetime.now(timezone.utc) - last_update).days
808
+ if days_old > 90:
809
+ should_archive = True
810
+ archive_reason.append(f"No updates for {days_old} days")
811
+
812
+ # Archive if needed
813
+ if should_archive and not dry_run:
814
+ archive_result = self.archive_file(
815
+ file_path,
816
+ reason=f"Auto-archived: {', '.join(archive_reason)}",
817
+ metadata={
818
+ "auto_detection": True,
819
+ "indicators": file_report.get("outdated_indicators", [])[:5],
820
+ "review_timestamp": review["timestamp"],
821
+ },
822
+ )
823
+ if archive_result:
824
+ result["archived_files"].append(
825
+ {
826
+ "file": filename,
827
+ "reason": archive_reason,
828
+ "archive_path": str(archive_result),
829
+ }
830
+ )
831
+ elif should_archive:
832
+ result["skipped_files"].append(
833
+ {
834
+ "file": filename,
835
+ "reason": archive_reason,
836
+ "action": "Would archive (dry run)",
837
+ }
838
+ )
839
+
840
+ return result
841
+
842
+ def generate_documentation_diff_report(
843
+ self, file1: Path, file2: Optional[Path] = None
844
+ ) -> str:
845
+ """Generate a diff report between two documentation files or versions."""
846
+ if not file1.exists():
847
+ return f"Error: {file1} does not exist"
848
+
849
+ # If file2 not specified, compare with latest archive
850
+ if file2 is None:
851
+ latest = self.get_latest_archive(file1.name)
852
+ if not latest:
853
+ return f"No archive found for {file1.name}"
854
+ file2 = latest
855
+
856
+ # Read contents
857
+ content1 = file1.read_text()
858
+
859
+ if file2.suffix == ".gz":
860
+ with gzip.open(file2, "rt", encoding="utf-8") as f:
861
+ content2 = f.read()
862
+ else:
863
+ content2 = file2.read_text() if isinstance(file2, Path) else file2
864
+
865
+ # Generate diff
866
+ diff = difflib.unified_diff(
867
+ content2.splitlines(keepends=True),
868
+ content1.splitlines(keepends=True),
869
+ fromfile=str(file2) if isinstance(file2, Path) else "Archive",
870
+ tofile=str(file1),
871
+ n=3,
872
+ )
873
+
874
+ return "".join(diff)
875
+
876
+ def sync_with_readme_and_changelog(self) -> Dict:
877
+ """Sync key information between CLAUDE.md, README.md, and CHANGELOG.md."""
878
+ result = {
879
+ "synced": False,
880
+ "changes": [],
881
+ "errors": [],
882
+ }
883
+
884
+ claude_path = self.project_path / "CLAUDE.md"
885
+ readme_path = self.project_path / "README.md"
886
+ changelog_path = self.project_path / "CHANGELOG.md"
887
+
888
+ if not claude_path.exists():
889
+ result["errors"].append("CLAUDE.md not found")
890
+ return result
891
+
892
+ try:
893
+ # Extract current version
894
+ version_file = self.project_path / "VERSION"
895
+ if version_file.exists():
896
+ current_version = version_file.read_text().strip()
897
+ else:
898
+ current_version = None
899
+
900
+ # Update README.md if exists
901
+ if readme_path.exists() and current_version:
902
+ readme_content = readme_path.read_text()
903
+ # Update version badges or references
904
+ updated_readme = self._update_version_references(
905
+ readme_content, current_version
906
+ )
907
+ if updated_readme != readme_content:
908
+ # Archive before update
909
+ self.archive_file(readme_path, reason="Before version sync")
910
+ readme_path.write_text(updated_readme)
911
+ result["changes"].append(
912
+ f"Updated README.md to version {current_version}"
913
+ )
914
+
915
+ # Update CHANGELOG.md header if exists
916
+ if changelog_path.exists() and current_version:
917
+ changelog_content = changelog_path.read_text()
918
+ if f"## [{current_version}]" not in changelog_content:
919
+ # Add new version section
920
+ today = datetime.now(timezone.utc).strftime("%Y-%m-%d")
921
+ new_section = f"\n## [{current_version}] - {today}\n\n### Added\n\n### Changed\n\n### Fixed\n\n"
922
+
923
+ # Insert after header
924
+ lines = changelog_content.splitlines()
925
+ insert_pos = 0
926
+ for i, line in enumerate(lines):
927
+ if line.startswith("## "):
928
+ insert_pos = i
929
+ break
930
+
931
+ if insert_pos > 0:
932
+ lines.insert(insert_pos, new_section)
933
+ updated_changelog = "\n".join(lines)
934
+
935
+ # Archive before update
936
+ self.archive_file(
937
+ changelog_path, reason="Before adding new version"
938
+ )
939
+ changelog_path.write_text(updated_changelog)
940
+ result["changes"].append(
941
+ f"Added {current_version} section to CHANGELOG.md"
942
+ )
943
+
944
+ result["synced"] = len(result["changes"]) > 0
945
+
946
+ except Exception as e:
947
+ result["errors"].append(f"Sync failed: {e!s}")
948
+ logger.error(f"Documentation sync failed: {e}")
949
+
950
+ return result
951
+
952
+ def _update_version_references(self, content: str, new_version: str) -> str:
953
+ """Update version references in documentation content."""
954
+ # Update version badges
955
+ content = re.sub(
956
+ r"badge/version-v?\d+\.\d+\.\d+",
957
+ f"badge/version-v{new_version}",
958
+ content,
959
+ )
960
+
961
+ # Update explicit version mentions
962
+ return re.sub(
963
+ r"(?:Version|version|v)\s*\d+\.\d+\.\d+",
964
+ f"v{new_version}",
965
+ content,
966
+ )
967
+
968
+ def display_review_summary(self, review: Dict) -> None:
969
+ """Display a formatted summary of the documentation review."""
970
+ console.print("\n[bold cyan]📚 Documentation Review Summary[/bold cyan]\n")
971
+
972
+ # Create summary table
973
+ table = Table(title="Documentation Files Status")
974
+ table.add_column("File", style="cyan")
975
+ table.add_column("Status", style="green")
976
+ table.add_column("Issues", style="yellow")
977
+ table.add_column("Last Updated", style="magenta")
978
+
979
+ for filename, report in review["files_reviewed"].items():
980
+ status = (
981
+ "✅ OK" if not report.get("outdated_indicators") else "⚠️ Needs Review"
982
+ )
983
+ issues = len(report.get("outdated_indicators", []))
984
+
985
+ last_updated = "Unknown"
986
+ if report.get("last_git_update"):
987
+ last_date = datetime.fromisoformat(report["last_git_update"])
988
+ days_ago = (datetime.now(timezone.utc) - last_date).days
989
+ last_updated = f"{days_ago} days ago"
990
+
991
+ table.add_row(filename, status, str(issues), last_updated)
992
+
993
+ console.print(table)
994
+
995
+ # Print synchronization issues
996
+ if review["synchronization_issues"]:
997
+ console.print("\n[bold yellow]⚠️ Synchronization Issues:[/bold yellow]")
998
+ for issue in review["synchronization_issues"]:
999
+ console.print(f" • {issue['type']}: {issue['details']}")
1000
+
1001
+ # Print recommendations
1002
+ if review["recommendations"]:
1003
+ console.print("\n[bold green]💡 Recommendations:[/bold green]")
1004
+ for rec in review["recommendations"]:
1005
+ console.print(f" {rec}")
1006
+
1007
+ def restore_from_archive_with_review(
1008
+ self, archive_name: str, review_changes: bool = True
1009
+ ) -> Tuple[bool, str]:
1010
+ """Restore an archive with optional change review."""
1011
+ archive_file = self.archive_path / archive_name
1012
+
1013
+ if not archive_file.exists():
1014
+ return False, f"Archive {archive_name} not found"
1015
+
1016
+ # Extract target file name
1017
+ parts = archive_name.split(".")
1018
+ if archive_name.endswith(".gz"):
1019
+ original_name = ".".join(parts[:-3])
1020
+ else:
1021
+ original_name = ".".join(parts[:-2])
1022
+
1023
+ target_path = self.project_path / original_name
1024
+
1025
+ # Generate diff if current file exists and review requested
1026
+ if target_path.exists() and review_changes:
1027
+ diff_report = self.generate_documentation_diff_report(
1028
+ target_path, archive_file
1029
+ )
1030
+
1031
+ console.print("\n[bold cyan]📝 Changes to be applied:[/bold cyan]")
1032
+ console.print(diff_report)
1033
+
1034
+ # Ask for confirmation
1035
+ console.print(
1036
+ "\n[bold yellow]Proceed with restoration? (y/n): [/bold yellow]", end=""
1037
+ )
1038
+ # In automated context, assume yes
1039
+ confirm = True
1040
+
1041
+ if not confirm:
1042
+ return False, "Restoration cancelled by user"
1043
+
1044
+ # Proceed with restoration
1045
+ return self.restore_archive(archive_name, target_path)