claude-mpm 4.3.12__py3-none-any.whl → 4.3.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/PM_INSTRUCTIONS.md +390 -28
  3. claude_mpm/agents/templates/data_engineer.json +39 -14
  4. claude_mpm/cli/commands/agent_manager.py +3 -3
  5. claude_mpm/cli/commands/agents.py +2 -2
  6. claude_mpm/cli/commands/aggregate.py +1 -1
  7. claude_mpm/cli/commands/config.py +2 -2
  8. claude_mpm/cli/commands/configure.py +5 -5
  9. claude_mpm/cli/commands/configure_tui.py +7 -7
  10. claude_mpm/cli/commands/dashboard.py +1 -1
  11. claude_mpm/cli/commands/debug.py +5 -5
  12. claude_mpm/cli/commands/mcp.py +1 -1
  13. claude_mpm/cli/commands/mcp_command_router.py +1 -1
  14. claude_mpm/cli/commands/mcp_config.py +7 -10
  15. claude_mpm/cli/commands/mcp_external_commands.py +40 -32
  16. claude_mpm/cli/commands/mcp_install_commands.py +38 -10
  17. claude_mpm/cli/commands/mcp_setup_external.py +143 -102
  18. claude_mpm/cli/commands/monitor.py +2 -2
  19. claude_mpm/cli/commands/mpm_init_handler.py +1 -1
  20. claude_mpm/cli/commands/run.py +46 -2
  21. claude_mpm/cli/commands/search.py +41 -34
  22. claude_mpm/cli/interactive/agent_wizard.py +2 -2
  23. claude_mpm/cli/parsers/mcp_parser.py +1 -3
  24. claude_mpm/cli/parsers/search_parser.py +10 -4
  25. claude_mpm/cli/startup_logging.py +3 -5
  26. claude_mpm/cli/utils.py +1 -1
  27. claude_mpm/core/agent_registry.py +12 -8
  28. claude_mpm/core/agent_session_manager.py +8 -8
  29. claude_mpm/core/api_validator.py +4 -4
  30. claude_mpm/core/base_service.py +10 -10
  31. claude_mpm/core/cache.py +5 -5
  32. claude_mpm/core/config_constants.py +1 -1
  33. claude_mpm/core/container.py +1 -1
  34. claude_mpm/core/error_handler.py +2 -2
  35. claude_mpm/core/file_utils.py +1 -1
  36. claude_mpm/core/framework_loader.py +3 -3
  37. claude_mpm/core/hook_manager.py +8 -6
  38. claude_mpm/core/instruction_reinforcement_hook.py +2 -2
  39. claude_mpm/core/interactive_session.py +1 -1
  40. claude_mpm/core/lazy.py +3 -3
  41. claude_mpm/core/log_manager.py +16 -12
  42. claude_mpm/core/logger.py +16 -11
  43. claude_mpm/core/logging_config.py +4 -2
  44. claude_mpm/core/oneshot_session.py +1 -1
  45. claude_mpm/core/optimized_agent_loader.py +6 -6
  46. claude_mpm/core/output_style_manager.py +1 -1
  47. claude_mpm/core/pm_hook_interceptor.py +3 -3
  48. claude_mpm/core/service_registry.py +1 -1
  49. claude_mpm/core/session_manager.py +11 -9
  50. claude_mpm/core/socketio_pool.py +13 -13
  51. claude_mpm/core/types.py +2 -2
  52. claude_mpm/core/unified_agent_registry.py +2 -2
  53. claude_mpm/core/unified_paths.py +1 -1
  54. claude_mpm/dashboard/analysis_runner.py +4 -4
  55. claude_mpm/dashboard/api/simple_directory.py +1 -1
  56. claude_mpm/generators/agent_profile_generator.py +4 -2
  57. claude_mpm/hooks/base_hook.py +2 -2
  58. claude_mpm/hooks/claude_hooks/connection_pool.py +4 -4
  59. claude_mpm/hooks/claude_hooks/event_handlers.py +12 -12
  60. claude_mpm/hooks/claude_hooks/hook_handler.py +4 -4
  61. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +3 -3
  62. claude_mpm/hooks/claude_hooks/hook_handler_original.py +15 -14
  63. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +4 -4
  64. claude_mpm/hooks/claude_hooks/installer.py +3 -3
  65. claude_mpm/hooks/claude_hooks/memory_integration.py +3 -3
  66. claude_mpm/hooks/claude_hooks/response_tracking.py +3 -3
  67. claude_mpm/hooks/claude_hooks/services/connection_manager.py +5 -5
  68. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +3 -3
  69. claude_mpm/hooks/claude_hooks/services/state_manager.py +8 -7
  70. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +3 -3
  71. claude_mpm/hooks/claude_hooks/tool_analysis.py +2 -2
  72. claude_mpm/hooks/memory_integration_hook.py +1 -1
  73. claude_mpm/hooks/tool_call_interceptor.py +2 -2
  74. claude_mpm/models/agent_session.py +5 -5
  75. claude_mpm/services/__init__.py +1 -1
  76. claude_mpm/services/agent_capabilities_service.py +1 -1
  77. claude_mpm/services/agents/agent_builder.py +3 -3
  78. claude_mpm/services/agents/deployment/agent_deployment.py +2 -1
  79. claude_mpm/services/agents/deployment/agent_discovery_service.py +9 -3
  80. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +7 -5
  81. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +3 -1
  82. claude_mpm/services/agents/deployment/agent_metrics_collector.py +1 -1
  83. claude_mpm/services/agents/deployment/agent_operation_service.py +2 -2
  84. claude_mpm/services/agents/deployment/agent_state_service.py +2 -2
  85. claude_mpm/services/agents/deployment/agent_template_builder.py +1 -1
  86. claude_mpm/services/agents/deployment/agent_versioning.py +1 -1
  87. claude_mpm/services/agents/deployment/deployment_wrapper.py +2 -3
  88. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +1 -1
  89. claude_mpm/services/agents/loading/agent_profile_loader.py +5 -3
  90. claude_mpm/services/agents/loading/base_agent_manager.py +2 -2
  91. claude_mpm/services/agents/local_template_manager.py +6 -6
  92. claude_mpm/services/agents/management/agent_management_service.py +3 -3
  93. claude_mpm/services/agents/memory/content_manager.py +3 -3
  94. claude_mpm/services/agents/memory/memory_format_service.py +2 -2
  95. claude_mpm/services/agents/memory/template_generator.py +3 -3
  96. claude_mpm/services/agents/registry/__init__.py +1 -1
  97. claude_mpm/services/agents/registry/modification_tracker.py +2 -2
  98. claude_mpm/services/async_session_logger.py +3 -3
  99. claude_mpm/services/claude_session_logger.py +4 -4
  100. claude_mpm/services/cli/agent_listing_service.py +1 -1
  101. claude_mpm/services/cli/agent_validation_service.py +1 -0
  102. claude_mpm/services/cli/memory_crud_service.py +11 -6
  103. claude_mpm/services/cli/memory_output_formatter.py +1 -1
  104. claude_mpm/services/cli/session_manager.py +15 -11
  105. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  106. claude_mpm/services/core/memory_manager.py +81 -23
  107. claude_mpm/services/core/path_resolver.py +2 -2
  108. claude_mpm/services/diagnostics/checks/installation_check.py +1 -1
  109. claude_mpm/services/event_aggregator.py +4 -2
  110. claude_mpm/services/event_bus/direct_relay.py +5 -3
  111. claude_mpm/services/event_bus/event_bus.py +3 -3
  112. claude_mpm/services/event_bus/relay.py +6 -4
  113. claude_mpm/services/events/consumers/dead_letter.py +5 -3
  114. claude_mpm/services/events/core.py +3 -3
  115. claude_mpm/services/events/producers/hook.py +6 -6
  116. claude_mpm/services/events/producers/system.py +8 -8
  117. claude_mpm/services/exceptions.py +5 -5
  118. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -3
  119. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +2 -2
  120. claude_mpm/services/hook_installer_service.py +1 -1
  121. claude_mpm/services/infrastructure/context_preservation.py +6 -4
  122. claude_mpm/services/infrastructure/daemon_manager.py +2 -2
  123. claude_mpm/services/infrastructure/logging.py +2 -2
  124. claude_mpm/services/mcp_config_manager.py +175 -30
  125. claude_mpm/services/mcp_gateway/__init__.py +1 -1
  126. claude_mpm/services/mcp_gateway/auto_configure.py +3 -3
  127. claude_mpm/services/mcp_gateway/config/config_loader.py +1 -1
  128. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  129. claude_mpm/services/mcp_gateway/core/base.py +2 -2
  130. claude_mpm/services/mcp_gateway/main.py +21 -7
  131. claude_mpm/services/mcp_gateway/registry/tool_registry.py +10 -8
  132. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +4 -4
  133. claude_mpm/services/mcp_gateway/server/stdio_handler.py +1 -1
  134. claude_mpm/services/mcp_gateway/server/stdio_server.py +4 -3
  135. claude_mpm/services/mcp_gateway/tools/base_adapter.py +15 -15
  136. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +7 -5
  137. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +190 -137
  138. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +5 -5
  139. claude_mpm/services/mcp_gateway/tools/hello_world.py +9 -9
  140. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +16 -16
  141. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +17 -17
  142. claude_mpm/services/memory/builder.py +7 -5
  143. claude_mpm/services/memory/indexed_memory.py +4 -4
  144. claude_mpm/services/memory/optimizer.py +6 -6
  145. claude_mpm/services/memory/router.py +3 -3
  146. claude_mpm/services/monitor/daemon.py +1 -1
  147. claude_mpm/services/monitor/daemon_manager.py +6 -6
  148. claude_mpm/services/monitor/event_emitter.py +2 -2
  149. claude_mpm/services/monitor/handlers/file.py +1 -1
  150. claude_mpm/services/monitor/management/lifecycle.py +1 -1
  151. claude_mpm/services/monitor/server.py +4 -4
  152. claude_mpm/services/monitor_build_service.py +2 -2
  153. claude_mpm/services/port_manager.py +2 -2
  154. claude_mpm/services/response_tracker.py +2 -2
  155. claude_mpm/services/session_management_service.py +3 -2
  156. claude_mpm/services/socketio/client_proxy.py +2 -2
  157. claude_mpm/services/socketio/dashboard_server.py +4 -3
  158. claude_mpm/services/socketio/event_normalizer.py +12 -8
  159. claude_mpm/services/socketio/handlers/base.py +2 -2
  160. claude_mpm/services/socketio/handlers/connection.py +10 -10
  161. claude_mpm/services/socketio/handlers/connection_handler.py +13 -10
  162. claude_mpm/services/socketio/handlers/file.py +1 -1
  163. claude_mpm/services/socketio/handlers/git.py +1 -1
  164. claude_mpm/services/socketio/handlers/hook.py +16 -15
  165. claude_mpm/services/socketio/migration_utils.py +1 -1
  166. claude_mpm/services/socketio/monitor_client.py +5 -5
  167. claude_mpm/services/socketio/server/broadcaster.py +9 -7
  168. claude_mpm/services/socketio/server/connection_manager.py +2 -2
  169. claude_mpm/services/socketio/server/core.py +7 -5
  170. claude_mpm/services/socketio/server/eventbus_integration.py +18 -11
  171. claude_mpm/services/socketio/server/main.py +13 -13
  172. claude_mpm/services/socketio_client_manager.py +4 -4
  173. claude_mpm/services/system_instructions_service.py +2 -2
  174. claude_mpm/services/ticket_services/validation_service.py +1 -1
  175. claude_mpm/services/utility_service.py +5 -2
  176. claude_mpm/services/version_control/branch_strategy.py +2 -2
  177. claude_mpm/services/version_control/git_operations.py +22 -20
  178. claude_mpm/services/version_control/semantic_versioning.py +3 -3
  179. claude_mpm/services/version_control/version_parser.py +7 -5
  180. claude_mpm/services/visualization/mermaid_generator.py +1 -1
  181. claude_mpm/storage/state_storage.py +1 -1
  182. claude_mpm/tools/code_tree_analyzer.py +19 -18
  183. claude_mpm/tools/code_tree_builder.py +2 -2
  184. claude_mpm/tools/code_tree_events.py +10 -8
  185. claude_mpm/tools/socketio_debug.py +3 -3
  186. claude_mpm/utils/agent_dependency_loader.py +2 -2
  187. claude_mpm/utils/dependency_strategies.py +8 -3
  188. claude_mpm/utils/environment_context.py +2 -2
  189. claude_mpm/utils/error_handler.py +2 -2
  190. claude_mpm/utils/file_utils.py +1 -1
  191. claude_mpm/utils/imports.py +1 -1
  192. claude_mpm/utils/log_cleanup.py +21 -7
  193. claude_mpm/validation/agent_validator.py +2 -2
  194. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.13.dist-info}/METADATA +1 -1
  195. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.13.dist-info}/RECORD +199 -199
  196. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.13.dist-info}/WHEEL +0 -0
  197. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.13.dist-info}/entry_points.txt +0 -0
  198. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.13.dist-info}/licenses/LICENSE +0 -0
  199. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.13.dist-info}/top_level.txt +0 -0
@@ -13,7 +13,7 @@ import asyncio
13
13
  import threading
14
14
  import time
15
15
  from collections import deque
16
- from datetime import datetime
16
+ from datetime import datetime, timezone
17
17
  from pathlib import Path
18
18
  from typing import Any, Dict, Set
19
19
 
@@ -211,7 +211,7 @@ class SocketIOServerCore:
211
211
  await self.site.start()
212
212
 
213
213
  self.running = True
214
- self.stats["start_time"] = datetime.now()
214
+ self.stats["start_time"] = datetime.now(timezone.utc)
215
215
 
216
216
  self.logger.info(
217
217
  f"Socket.IO server listening on http://{self.host}:{self.port}"
@@ -428,7 +428,7 @@ class SocketIOServerCore:
428
428
  )
429
429
 
430
430
  # Add file reading endpoint for source viewer
431
- async def file_read_handler(request):
431
+ async def file_read_handler(request): # noqa: PLR0911
432
432
  """Handle GET /api/file/read for reading source files."""
433
433
  import os
434
434
 
@@ -749,7 +749,9 @@ class SocketIOServerCore:
749
749
  uptime_seconds = 0
750
750
  if self.stats.get("start_time"):
751
751
  uptime_seconds = int(
752
- (datetime.now() - self.stats["start_time"]).total_seconds()
752
+ (
753
+ datetime.now(timezone.utc) - self.stats["start_time"]
754
+ ).total_seconds()
753
755
  )
754
756
 
755
757
  # Get active sessions from main server if available
@@ -766,7 +768,7 @@ class SocketIOServerCore:
766
768
  heartbeat_data = {
767
769
  "type": "system",
768
770
  "subtype": "heartbeat",
769
- "timestamp": datetime.now().isoformat(),
771
+ "timestamp": datetime.now(timezone.utc).isoformat(),
770
772
  "source": "server",
771
773
  "data": {
772
774
  "uptime_seconds": uptime_seconds,
@@ -8,6 +8,7 @@ WHY this integration module:
8
8
  """
9
9
 
10
10
  import logging
11
+ from datetime import datetime, timezone
11
12
  from typing import Optional
12
13
 
13
14
  from claude_mpm.services.event_bus import EventBus
@@ -51,14 +52,14 @@ class EventBusIntegration:
51
52
  from datetime import datetime
52
53
 
53
54
  print(
54
- f"[{datetime.now().isoformat()}] EventBusIntegration.setup() called",
55
+ f"[{datetime.now(timezone.utc).isoformat()}] EventBusIntegration.setup() called",
55
56
  flush=True,
56
57
  )
57
58
 
58
59
  if not self.enabled:
59
60
  logger.info("EventBus integration disabled by configuration")
60
61
  print(
61
- f"[{datetime.now().isoformat()}] EventBus integration disabled by configuration",
62
+ f"[{datetime.now(timezone.utc).isoformat()}] EventBus integration disabled by configuration",
62
63
  flush=True,
63
64
  )
64
65
  return False
@@ -66,12 +67,13 @@ class EventBusIntegration:
66
67
  try:
67
68
  # Get EventBus instance
68
69
  print(
69
- f"[{datetime.now().isoformat()}] Getting EventBus instance...",
70
+ f"[{datetime.now(timezone.utc).isoformat()}] Getting EventBus instance...",
70
71
  flush=True,
71
72
  )
72
73
  self.event_bus = EventBus.get_instance()
73
74
  print(
74
- f"[{datetime.now().isoformat()}] EventBus instance obtained", flush=True
75
+ f"[{datetime.now(timezone.utc).isoformat()}] EventBus instance obtained",
76
+ flush=True,
75
77
  )
76
78
 
77
79
  # Apply configuration
@@ -79,31 +81,36 @@ class EventBusIntegration:
79
81
 
80
82
  # Create direct relay that uses server's broadcaster
81
83
  print(
82
- f"[{datetime.now().isoformat()}] Creating DirectSocketIORelay...",
84
+ f"[{datetime.now(timezone.utc).isoformat()}] Creating DirectSocketIORelay...",
83
85
  flush=True,
84
86
  )
85
87
  if self.server:
86
88
  self.relay = DirectSocketIORelay(self.server)
87
89
  print(
88
- f"[{datetime.now().isoformat()}] DirectSocketIORelay created with server instance",
90
+ f"[{datetime.now(timezone.utc).isoformat()}] DirectSocketIORelay created with server instance",
89
91
  flush=True,
90
92
  )
91
93
  else:
92
94
  logger.warning("No server instance provided, relay won't work")
93
95
  print(
94
- f"[{datetime.now().isoformat()}] WARNING: No server instance for relay",
96
+ f"[{datetime.now(timezone.utc).isoformat()}] WARNING: No server instance for relay",
95
97
  flush=True,
96
98
  )
97
99
  return False
98
100
 
99
101
  # Start the relay
100
- print(f"[{datetime.now().isoformat()}] Starting relay...", flush=True)
102
+ print(
103
+ f"[{datetime.now(timezone.utc).isoformat()}] Starting relay...",
104
+ flush=True,
105
+ )
101
106
  self.relay.start()
102
- print(f"[{datetime.now().isoformat()}] Relay started", flush=True)
107
+ print(
108
+ f"[{datetime.now(timezone.utc).isoformat()}] Relay started", flush=True
109
+ )
103
110
 
104
111
  logger.info("EventBus integration setup complete with DirectSocketIORelay")
105
112
  print(
106
- f"[{datetime.now().isoformat()}] EventBus integration setup complete with DirectSocketIORelay",
113
+ f"[{datetime.now(timezone.utc).isoformat()}] EventBus integration setup complete with DirectSocketIORelay",
107
114
  flush=True,
108
115
  )
109
116
  return True
@@ -111,7 +118,7 @@ class EventBusIntegration:
111
118
  except Exception as e:
112
119
  logger.error(f"Failed to setup EventBus integration: {e}")
113
120
  print(
114
- f"[{datetime.now().isoformat()}] Failed to setup EventBus integration: {e}",
121
+ f"[{datetime.now(timezone.utc).isoformat()}] Failed to setup EventBus integration: {e}",
115
122
  flush=True,
116
123
  )
117
124
  import traceback
@@ -13,7 +13,7 @@ import asyncio
13
13
  import threading
14
14
  import time
15
15
  from collections import deque
16
- from datetime import datetime
16
+ from datetime import datetime, timezone
17
17
  from typing import Any, Dict, List, Optional, Set
18
18
 
19
19
  try:
@@ -107,7 +107,7 @@ class SocketIOServer(SocketIOServiceInterface):
107
107
  # Debug logging for EventBus initialization
108
108
  self.logger.info("Starting Socket.IO server with EventBus integration...")
109
109
  print(
110
- f"[{datetime.now().isoformat()}] SocketIOServer.start_sync() called",
110
+ f"[{datetime.now(timezone.utc).isoformat()}] SocketIOServer.start_sync() called",
111
111
  flush=True,
112
112
  )
113
113
 
@@ -172,7 +172,7 @@ class SocketIOServer(SocketIOServiceInterface):
172
172
  # WHY: This connects the EventBus to the Socket.IO server, allowing
173
173
  # events from other parts of the system to be broadcast to dashboard
174
174
  print(
175
- f"[{datetime.now().isoformat()}] Setting up EventBus integration...",
175
+ f"[{datetime.now(timezone.utc).isoformat()}] Setting up EventBus integration...",
176
176
  flush=True,
177
177
  )
178
178
 
@@ -183,26 +183,26 @@ class SocketIOServer(SocketIOServiceInterface):
183
183
  "Broadcaster not initialized - cannot setup EventBus integration"
184
184
  )
185
185
  print(
186
- f"[{datetime.now().isoformat()}] ERROR: Broadcaster not initialized",
186
+ f"[{datetime.now(timezone.utc).isoformat()}] ERROR: Broadcaster not initialized",
187
187
  flush=True,
188
188
  )
189
189
  else:
190
190
  print(
191
- f"[{datetime.now().isoformat()}] Broadcaster ready, proceeding with EventBus setup",
191
+ f"[{datetime.now(timezone.utc).isoformat()}] Broadcaster ready, proceeding with EventBus setup",
192
192
  flush=True,
193
193
  )
194
194
 
195
195
  try:
196
196
  self.eventbus_integration = EventBusIntegration(self)
197
197
  print(
198
- f"[{datetime.now().isoformat()}] EventBusIntegration instance created",
198
+ f"[{datetime.now(timezone.utc).isoformat()}] EventBusIntegration instance created",
199
199
  flush=True,
200
200
  )
201
201
 
202
202
  if self.eventbus_integration.setup(self.port):
203
203
  self.logger.info("EventBus integration setup successful")
204
204
  print(
205
- f"[{datetime.now().isoformat()}] EventBus integration setup successful",
205
+ f"[{datetime.now(timezone.utc).isoformat()}] EventBus integration setup successful",
206
206
  flush=True,
207
207
  )
208
208
 
@@ -214,19 +214,19 @@ class SocketIOServer(SocketIOServiceInterface):
214
214
  relay_stats = self.eventbus_integration.relay.get_stats()
215
215
  self.logger.info(f"EventBus relay stats: {relay_stats}")
216
216
  print(
217
- f"[{datetime.now().isoformat()}] EventBus relay stats: {relay_stats}",
217
+ f"[{datetime.now(timezone.utc).isoformat()}] EventBus relay stats: {relay_stats}",
218
218
  flush=True,
219
219
  )
220
220
  else:
221
221
  self.logger.warning("EventBus integration setup failed or disabled")
222
222
  print(
223
- f"[{datetime.now().isoformat()}] EventBus integration setup failed or disabled",
223
+ f"[{datetime.now(timezone.utc).isoformat()}] EventBus integration setup failed or disabled",
224
224
  flush=True,
225
225
  )
226
226
  except Exception as e:
227
227
  self.logger.error(f"Failed to setup EventBus integration: {e}")
228
228
  print(
229
- f"[{datetime.now().isoformat()}] Failed to setup EventBus integration: {e}",
229
+ f"[{datetime.now(timezone.utc).isoformat()}] Failed to setup EventBus integration: {e}",
230
230
  flush=True,
231
231
  )
232
232
  import traceback
@@ -382,7 +382,7 @@ class SocketIOServer(SocketIOServiceInterface):
382
382
  # Track active session for heartbeat
383
383
  self.active_sessions[session_id] = {
384
384
  "session_id": session_id,
385
- "start_time": datetime.now().isoformat(),
385
+ "start_time": datetime.now(timezone.utc).isoformat(),
386
386
  "agent": "pm", # Default to PM, will be updated if delegated
387
387
  "status": "active",
388
388
  "launch_method": launch_method,
@@ -472,7 +472,7 @@ class SocketIOServer(SocketIOServiceInterface):
472
472
  WHY: Provides session information for system heartbeat events.
473
473
  """
474
474
  # Clean up old sessions (older than 1 hour)
475
- cutoff_time = datetime.now().timestamp() - 3600
475
+ cutoff_time = datetime.now(timezone.utc).timestamp() - 3600
476
476
  sessions_to_remove = []
477
477
 
478
478
  for session_id, session_data in self.active_sessions.items():
@@ -480,7 +480,7 @@ class SocketIOServer(SocketIOServiceInterface):
480
480
  start_time = datetime.fromisoformat(session_data["start_time"])
481
481
  if start_time.timestamp() < cutoff_time:
482
482
  sessions_to_remove.append(session_id)
483
- except:
483
+ except Exception:
484
484
  pass
485
485
 
486
486
  for session_id in sessions_to_remove:
@@ -18,7 +18,7 @@ import importlib.metadata
18
18
  import socket
19
19
  import threading
20
20
  import time
21
- from datetime import datetime
21
+ from datetime import datetime, timezone
22
22
  from typing import Any, Dict, List, Optional, Tuple
23
23
 
24
24
  from claude_mpm.core.constants import NetworkConfig, PerformanceConfig, TimeoutConfig
@@ -59,7 +59,7 @@ class ServerInfo:
59
59
  "supported_client_versions", []
60
60
  )
61
61
  self.compatibility_matrix = response_data.get("compatibility_matrix", {})
62
- self.detected_at = datetime.utcnow()
62
+ self.detected_at = datetime.now(timezone.utc)
63
63
 
64
64
  @property
65
65
  def url(self) -> str:
@@ -161,7 +161,7 @@ class SocketIOClientManager:
161
161
  self.logger.debug(f"Error checking {host}:{port}: {e}")
162
162
  continue
163
163
 
164
- self.last_discovery = datetime.utcnow()
164
+ self.last_discovery = datetime.now(timezone.utc)
165
165
  return discovered
166
166
 
167
167
  def find_best_server(
@@ -323,7 +323,7 @@ class SocketIOClientManager:
323
323
  try:
324
324
  event_data = {
325
325
  "type": event_type,
326
- "timestamp": datetime.utcnow().isoformat() + "Z",
326
+ "timestamp": datetime.now(timezone.utc).isoformat() + "Z",
327
327
  "data": data,
328
328
  "client_version": self.client_version,
329
329
  }
@@ -10,7 +10,7 @@ Extracted from ClaudeRunner to follow Single Responsibility Principle.
10
10
  """
11
11
 
12
12
  import re
13
- from datetime import datetime
13
+ from datetime import datetime, timezone
14
14
  from typing import List, Optional, Tuple
15
15
 
16
16
  from claude_mpm.config.paths import paths
@@ -126,7 +126,7 @@ class SystemInstructionsService(BaseService, SystemInstructionsInterface):
126
126
 
127
127
  # Replace current date
128
128
  if "{{CURRENT_DATE}}" in base_pm_content:
129
- current_date = datetime.now().strftime("%Y-%m-%d")
129
+ current_date = datetime.now(timezone.utc).strftime("%Y-%m-%d")
130
130
  base_pm_content = base_pm_content.replace(
131
131
  "{{CURRENT_DATE}}", current_date
132
132
  )
@@ -158,7 +158,7 @@ class TicketValidationService:
158
158
 
159
159
  def validate_create_params(
160
160
  self, params: Dict[str, Any]
161
- ) -> Tuple[bool, Optional[str]]:
161
+ ) -> Tuple[bool, Optional[str]]: # noqa: PLR0911
162
162
  """
163
163
  Validate parameters for ticket creation.
164
164
 
@@ -14,7 +14,7 @@ Extracted from ClaudeRunner to follow Single Responsibility Principle.
14
14
  import json
15
15
  import re
16
16
  import uuid
17
- from datetime import datetime
17
+ from datetime import datetime, timezone
18
18
  from typing import Any, Dict, Optional, Tuple
19
19
 
20
20
  from claude_mpm.core.base_service import BaseService
@@ -105,7 +105,10 @@ class UtilityService(BaseService, UtilityServiceInterface):
105
105
  return
106
106
 
107
107
  try:
108
- log_entry = {"timestamp": datetime.now().isoformat(), **event_data}
108
+ log_entry = {
109
+ "timestamp": datetime.now(timezone.utc).isoformat(),
110
+ **event_data,
111
+ }
109
112
 
110
113
  with open(log_file, "a") as f:
111
114
  f.write(json.dumps(log_entry) + "\n")
@@ -14,7 +14,7 @@ This module provides comprehensive branch strategy management including:
14
14
  import logging
15
15
  import re
16
16
  from dataclasses import dataclass, field
17
- from datetime import datetime
17
+ from datetime import datetime, timezone
18
18
  from enum import Enum
19
19
  from typing import Any, Dict, List, Optional, Tuple
20
20
 
@@ -396,7 +396,7 @@ class BranchStrategyManager:
396
396
  return f"{prefix}{ticket_id}"
397
397
  if description:
398
398
  return f"{prefix}{self._sanitize_branch_name(description)}"
399
- return f"{prefix}{datetime.now().strftime('%Y%m%d')}"
399
+ return f"{prefix}{datetime.now(timezone.utc).strftime('%Y%m%d')}"
400
400
 
401
401
  # Generate name based on rule
402
402
  if strategy.strategy_type == BranchStrategyType.ISSUE_DRIVEN:
@@ -15,7 +15,7 @@ import logging
15
15
  import os
16
16
  import subprocess
17
17
  from dataclasses import dataclass, field
18
- from datetime import datetime
18
+ from datetime import datetime, timezone
19
19
  from typing import Any, Dict, List, Optional
20
20
 
21
21
 
@@ -366,7 +366,7 @@ class GitOperationsManager:
366
366
  Returns:
367
367
  GitOperationResult with operation details
368
368
  """
369
- start_time = datetime.now()
369
+ start_time = datetime.now(timezone.utc)
370
370
  current_branch = self.get_current_branch()
371
371
 
372
372
  # Generate full branch name with prefix
@@ -398,7 +398,7 @@ class GitOperationsManager:
398
398
  # Remote push failed, continue without remote tracking
399
399
  pass
400
400
 
401
- execution_time = (datetime.now() - start_time).total_seconds()
401
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
402
402
 
403
403
  return GitOperationResult(
404
404
  success=True,
@@ -411,7 +411,7 @@ class GitOperationsManager:
411
411
  )
412
412
 
413
413
  except GitOperationError as e:
414
- execution_time = (datetime.now() - start_time).total_seconds()
414
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
415
415
 
416
416
  return GitOperationResult(
417
417
  success=False,
@@ -433,7 +433,7 @@ class GitOperationsManager:
433
433
  Returns:
434
434
  GitOperationResult with operation details
435
435
  """
436
- start_time = datetime.now()
436
+ start_time = datetime.now(timezone.utc)
437
437
  current_branch = self.get_current_branch()
438
438
 
439
439
  try:
@@ -448,13 +448,15 @@ class GitOperationsManager:
448
448
  branch_before=current_branch,
449
449
  branch_after=current_branch,
450
450
  files_changed=modified_files,
451
- execution_time=(datetime.now() - start_time).total_seconds(),
451
+ execution_time=(
452
+ datetime.now(timezone.utc) - start_time
453
+ ).total_seconds(),
452
454
  )
453
455
 
454
456
  # Switch to the branch
455
457
  result = self._run_git_command(["checkout", branch_name])
456
458
 
457
- execution_time = (datetime.now() - start_time).total_seconds()
459
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
458
460
 
459
461
  return GitOperationResult(
460
462
  success=True,
@@ -467,7 +469,7 @@ class GitOperationsManager:
467
469
  )
468
470
 
469
471
  except GitOperationError as e:
470
- execution_time = (datetime.now() - start_time).total_seconds()
472
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
471
473
 
472
474
  return GitOperationResult(
473
475
  success=False,
@@ -498,7 +500,7 @@ class GitOperationsManager:
498
500
  Returns:
499
501
  GitOperationResult with operation details
500
502
  """
501
- start_time = datetime.now()
503
+ start_time = datetime.now(timezone.utc)
502
504
  current_branch = self.get_current_branch()
503
505
 
504
506
  try:
@@ -542,7 +544,7 @@ class GitOperationsManager:
542
544
  # Branch deletion failed, but merge was successful
543
545
  pass
544
546
 
545
- execution_time = (datetime.now() - start_time).total_seconds()
547
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
546
548
 
547
549
  return GitOperationResult(
548
550
  success=True,
@@ -555,7 +557,7 @@ class GitOperationsManager:
555
557
  )
556
558
 
557
559
  except GitOperationError as e:
558
- execution_time = (datetime.now() - start_time).total_seconds()
560
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
559
561
 
560
562
  return GitOperationResult(
561
563
  success=False,
@@ -651,7 +653,7 @@ class GitOperationsManager:
651
653
  Returns:
652
654
  GitOperationResult with operation details
653
655
  """
654
- start_time = datetime.now()
656
+ start_time = datetime.now(timezone.utc)
655
657
  current_branch = self.get_current_branch()
656
658
 
657
659
  if not branch_name:
@@ -668,7 +670,7 @@ class GitOperationsManager:
668
670
 
669
671
  result = self._run_git_command(push_args)
670
672
 
671
- execution_time = (datetime.now() - start_time).total_seconds()
673
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
672
674
 
673
675
  return GitOperationResult(
674
676
  success=True,
@@ -681,7 +683,7 @@ class GitOperationsManager:
681
683
  )
682
684
 
683
685
  except GitOperationError as e:
684
- execution_time = (datetime.now() - start_time).total_seconds()
686
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
685
687
 
686
688
  return GitOperationResult(
687
689
  success=False,
@@ -706,7 +708,7 @@ class GitOperationsManager:
706
708
  Returns:
707
709
  GitOperationResult with operation details
708
710
  """
709
- start_time = datetime.now()
711
+ start_time = datetime.now(timezone.utc)
710
712
  current_branch = self.get_current_branch()
711
713
 
712
714
  if not branch_name:
@@ -725,7 +727,7 @@ class GitOperationsManager:
725
727
  result = self._run_git_command(["pull", remote, branch_name])
726
728
  self._run_git_command(["checkout", current_branch])
727
729
 
728
- execution_time = (datetime.now() - start_time).total_seconds()
730
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
729
731
 
730
732
  return GitOperationResult(
731
733
  success=True,
@@ -738,7 +740,7 @@ class GitOperationsManager:
738
740
  )
739
741
 
740
742
  except GitOperationError as e:
741
- execution_time = (datetime.now() - start_time).total_seconds()
743
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
742
744
 
743
745
  return GitOperationResult(
744
746
  success=False,
@@ -762,7 +764,7 @@ class GitOperationsManager:
762
764
  Returns:
763
765
  GitOperationResult with cleanup details
764
766
  """
765
- start_time = datetime.now()
767
+ start_time = datetime.now(timezone.utc)
766
768
  current_branch = self.get_current_branch()
767
769
 
768
770
  try:
@@ -789,7 +791,7 @@ class GitOperationsManager:
789
791
  # Clean up remote tracking branches
790
792
  self._run_git_command(["remote", "prune", "origin"], check=False)
791
793
 
792
- execution_time = (datetime.now() - start_time).total_seconds()
794
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
793
795
 
794
796
  return GitOperationResult(
795
797
  success=True,
@@ -802,7 +804,7 @@ class GitOperationsManager:
802
804
  )
803
805
 
804
806
  except GitOperationError as e:
805
- execution_time = (datetime.now() - start_time).total_seconds()
807
+ execution_time = (datetime.now(timezone.utc) - start_time).total_seconds()
806
808
 
807
809
  return GitOperationResult(
808
810
  success=False,
@@ -42,7 +42,7 @@ Change Analysis:
42
42
  import logging
43
43
  import re
44
44
  from dataclasses import dataclass, field
45
- from datetime import datetime
45
+ from datetime import datetime, timezone
46
46
  from enum import Enum
47
47
  from typing import Dict, List, Optional, Tuple
48
48
 
@@ -100,7 +100,7 @@ class SemanticVersion:
100
100
  version += f"+{self.build}"
101
101
  return version
102
102
 
103
- def __lt__(self, other: "SemanticVersion") -> bool:
103
+ def __lt__(self, other: "SemanticVersion") -> bool: # noqa: PLR0911
104
104
  """Compare versions for sorting according to semver precedence.
105
105
 
106
106
  Comparison Rules:
@@ -748,7 +748,7 @@ class SemanticVersionManager:
748
748
  Returns:
749
749
  Formatted changelog entry
750
750
  """
751
- date_str = datetime.now().strftime("%Y-%m-%d")
751
+ date_str = datetime.now(timezone.utc).strftime("%Y-%m-%d")
752
752
  if metadata and metadata.release_date:
753
753
  date_str = metadata.release_date.strftime("%Y-%m-%d")
754
754
 
@@ -20,7 +20,7 @@ import json
20
20
  import logging
21
21
  import re
22
22
  import subprocess
23
- from datetime import datetime, timedelta
23
+ from datetime import datetime, timedelta, timezone
24
24
  from functools import lru_cache
25
25
  from typing import Dict, List, Optional, Tuple
26
26
 
@@ -61,7 +61,7 @@ class VersionMetadata:
61
61
  ):
62
62
  self.version = version
63
63
  self.source = source
64
- self.release_date = release_date or datetime.now()
64
+ self.release_date = release_date or datetime.now(timezone.utc)
65
65
  self.commit_hash = commit_hash
66
66
  self.author = author
67
67
  self.message = message
@@ -119,14 +119,16 @@ class EnhancedVersionParser:
119
119
  """Get cached value if still valid."""
120
120
  if key in self._cache:
121
121
  timestamp, value = self._cache[key]
122
- if datetime.now() - timestamp < timedelta(seconds=self.cache_ttl):
122
+ if datetime.now(timezone.utc) - timestamp < timedelta(
123
+ seconds=self.cache_ttl
124
+ ):
123
125
  return value
124
126
  del self._cache[key]
125
127
  return None
126
128
 
127
129
  def _set_cached(self, key: str, value: any) -> any:
128
130
  """Set cached value with timestamp."""
129
- self._cache[key] = (datetime.now(), value)
131
+ self._cache[key] = (datetime.now(timezone.utc), value)
130
132
  return value
131
133
 
132
134
  def get_current_version(
@@ -332,7 +334,7 @@ class EnhancedVersionParser:
332
334
  )
333
335
  if result.returncode == 0:
334
336
  commit_hash = result.stdout.strip()[:7]
335
- except:
337
+ except Exception:
336
338
  pass
337
339
 
338
340
  return VersionMetadata(
@@ -801,7 +801,7 @@ class MermaidGeneratorService(SyncBaseService):
801
801
 
802
802
  return False
803
803
 
804
- def validate_mermaid_syntax(self, diagram: str) -> Tuple[bool, Optional[str]]:
804
+ def validate_mermaid_syntax(self, diagram: str) -> Tuple[bool, Optional[str]]: # noqa: PLR0911
805
805
  """
806
806
  Validate that the generated Mermaid syntax is correct.
807
807
 
@@ -397,7 +397,7 @@ class StateStorage:
397
397
  temp_file.unlink()
398
398
  cleaned += 1
399
399
  self.logger.debug(f"Cleaned up temp file: {temp_file}")
400
- except:
400
+ except Exception:
401
401
  pass
402
402
 
403
403
  # Clean up orphaned checksum files