claude-mpm 4.3.12__py3-none-any.whl → 4.3.14__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 (206) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/PM_INSTRUCTIONS.md +414 -28
  3. claude_mpm/agents/templates/data_engineer.json +39 -14
  4. claude_mpm/agents/templates/engineer.json +11 -3
  5. claude_mpm/cli/commands/agent_manager.py +3 -3
  6. claude_mpm/cli/commands/agents.py +2 -2
  7. claude_mpm/cli/commands/aggregate.py +1 -1
  8. claude_mpm/cli/commands/config.py +2 -2
  9. claude_mpm/cli/commands/configure.py +5 -5
  10. claude_mpm/cli/commands/configure_tui.py +7 -7
  11. claude_mpm/cli/commands/dashboard.py +1 -1
  12. claude_mpm/cli/commands/debug.py +5 -5
  13. claude_mpm/cli/commands/mcp.py +1 -1
  14. claude_mpm/cli/commands/mcp_command_router.py +1 -1
  15. claude_mpm/cli/commands/mcp_config.py +7 -10
  16. claude_mpm/cli/commands/mcp_external_commands.py +40 -32
  17. claude_mpm/cli/commands/mcp_install_commands.py +38 -10
  18. claude_mpm/cli/commands/mcp_setup_external.py +143 -102
  19. claude_mpm/cli/commands/monitor.py +2 -2
  20. claude_mpm/cli/commands/mpm_init_handler.py +1 -1
  21. claude_mpm/cli/commands/run.py +54 -2
  22. claude_mpm/cli/commands/search.py +41 -34
  23. claude_mpm/cli/interactive/agent_wizard.py +6 -2
  24. claude_mpm/cli/parsers/mcp_parser.py +1 -3
  25. claude_mpm/cli/parsers/search_parser.py +10 -4
  26. claude_mpm/cli/startup_logging.py +158 -5
  27. claude_mpm/cli/utils.py +1 -1
  28. claude_mpm/core/agent_registry.py +2 -2
  29. claude_mpm/core/agent_session_manager.py +8 -8
  30. claude_mpm/core/api_validator.py +6 -4
  31. claude_mpm/core/base_service.py +10 -10
  32. claude_mpm/core/cache.py +5 -5
  33. claude_mpm/core/config_constants.py +1 -1
  34. claude_mpm/core/container.py +1 -1
  35. claude_mpm/core/error_handler.py +2 -2
  36. claude_mpm/core/file_utils.py +1 -1
  37. claude_mpm/core/framework_loader.py +3 -3
  38. claude_mpm/core/hook_manager.py +8 -6
  39. claude_mpm/core/instruction_reinforcement_hook.py +2 -2
  40. claude_mpm/core/interactive_session.py +3 -1
  41. claude_mpm/core/lazy.py +3 -3
  42. claude_mpm/core/log_manager.py +16 -12
  43. claude_mpm/core/logger.py +16 -11
  44. claude_mpm/core/optimized_agent_loader.py +6 -6
  45. claude_mpm/core/output_style_manager.py +1 -1
  46. claude_mpm/core/pm_hook_interceptor.py +3 -3
  47. claude_mpm/core/service_registry.py +1 -1
  48. claude_mpm/core/session_manager.py +11 -9
  49. claude_mpm/core/socketio_pool.py +13 -13
  50. claude_mpm/core/types.py +2 -2
  51. claude_mpm/core/unified_agent_registry.py +2 -2
  52. claude_mpm/core/unified_paths.py +1 -1
  53. claude_mpm/dashboard/analysis_runner.py +4 -4
  54. claude_mpm/dashboard/api/simple_directory.py +1 -1
  55. claude_mpm/generators/agent_profile_generator.py +4 -2
  56. claude_mpm/hooks/base_hook.py +2 -2
  57. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  58. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
  59. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
  60. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-313.pyc +0 -0
  61. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
  62. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
  63. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
  64. claude_mpm/hooks/claude_hooks/connection_pool.py +4 -4
  65. claude_mpm/hooks/claude_hooks/event_handlers.py +12 -12
  66. claude_mpm/hooks/claude_hooks/hook_handler.py +4 -4
  67. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +3 -3
  68. claude_mpm/hooks/claude_hooks/hook_handler_original.py +15 -14
  69. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +4 -4
  70. claude_mpm/hooks/claude_hooks/installer.py +3 -3
  71. claude_mpm/hooks/claude_hooks/memory_integration.py +3 -3
  72. claude_mpm/hooks/claude_hooks/response_tracking.py +3 -3
  73. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
  74. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-313.pyc +0 -0
  75. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
  76. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
  77. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
  78. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
  79. claude_mpm/hooks/claude_hooks/services/connection_manager.py +8 -5
  80. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +3 -3
  81. claude_mpm/hooks/claude_hooks/services/state_manager.py +8 -7
  82. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +3 -3
  83. claude_mpm/hooks/claude_hooks/tool_analysis.py +2 -2
  84. claude_mpm/hooks/memory_integration_hook.py +1 -1
  85. claude_mpm/hooks/tool_call_interceptor.py +2 -2
  86. claude_mpm/models/agent_session.py +7 -5
  87. claude_mpm/scripts/mcp_server.py +0 -0
  88. claude_mpm/scripts/start_activity_logging.py +0 -0
  89. claude_mpm/services/__init__.py +1 -1
  90. claude_mpm/services/agent_capabilities_service.py +1 -1
  91. claude_mpm/services/agents/agent_builder.py +3 -3
  92. claude_mpm/services/agents/deployment/agent_deployment.py +2 -1
  93. claude_mpm/services/agents/deployment/agent_discovery_service.py +9 -3
  94. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +5 -5
  95. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +3 -1
  96. claude_mpm/services/agents/deployment/agent_metrics_collector.py +1 -1
  97. claude_mpm/services/agents/deployment/agent_operation_service.py +2 -2
  98. claude_mpm/services/agents/deployment/agent_state_service.py +2 -2
  99. claude_mpm/services/agents/deployment/agent_template_builder.py +1 -1
  100. claude_mpm/services/agents/deployment/agent_versioning.py +1 -1
  101. claude_mpm/services/agents/deployment/deployment_wrapper.py +2 -3
  102. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +1 -1
  103. claude_mpm/services/agents/loading/agent_profile_loader.py +5 -3
  104. claude_mpm/services/agents/loading/base_agent_manager.py +2 -2
  105. claude_mpm/services/agents/local_template_manager.py +6 -6
  106. claude_mpm/services/agents/management/agent_management_service.py +3 -3
  107. claude_mpm/services/agents/memory/content_manager.py +3 -3
  108. claude_mpm/services/agents/memory/memory_format_service.py +2 -2
  109. claude_mpm/services/agents/memory/template_generator.py +3 -3
  110. claude_mpm/services/agents/registry/modification_tracker.py +2 -2
  111. claude_mpm/services/async_session_logger.py +3 -3
  112. claude_mpm/services/claude_session_logger.py +4 -4
  113. claude_mpm/services/cli/agent_listing_service.py +3 -1
  114. claude_mpm/services/cli/agent_validation_service.py +2 -0
  115. claude_mpm/services/cli/memory_crud_service.py +11 -6
  116. claude_mpm/services/cli/memory_output_formatter.py +1 -1
  117. claude_mpm/services/cli/session_manager.py +15 -11
  118. claude_mpm/services/core/memory_manager.py +81 -23
  119. claude_mpm/services/core/path_resolver.py +1 -1
  120. claude_mpm/services/diagnostics/checks/installation_check.py +1 -1
  121. claude_mpm/services/event_aggregator.py +4 -2
  122. claude_mpm/services/event_bus/direct_relay.py +5 -3
  123. claude_mpm/services/event_bus/event_bus.py +3 -3
  124. claude_mpm/services/event_bus/relay.py +6 -4
  125. claude_mpm/services/events/consumers/dead_letter.py +5 -3
  126. claude_mpm/services/events/core.py +3 -3
  127. claude_mpm/services/events/producers/hook.py +6 -6
  128. claude_mpm/services/events/producers/system.py +8 -8
  129. claude_mpm/services/exceptions.py +5 -5
  130. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -3
  131. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +2 -2
  132. claude_mpm/services/hook_installer_service.py +1 -1
  133. claude_mpm/services/infrastructure/context_preservation.py +6 -4
  134. claude_mpm/services/infrastructure/daemon_manager.py +2 -2
  135. claude_mpm/services/infrastructure/logging.py +2 -2
  136. claude_mpm/services/mcp_config_manager.py +175 -30
  137. claude_mpm/services/mcp_gateway/__init__.py +1 -1
  138. claude_mpm/services/mcp_gateway/auto_configure.py +3 -3
  139. claude_mpm/services/mcp_gateway/config/config_loader.py +1 -1
  140. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  141. claude_mpm/services/mcp_gateway/core/base.py +2 -2
  142. claude_mpm/services/mcp_gateway/main.py +21 -7
  143. claude_mpm/services/mcp_gateway/registry/tool_registry.py +10 -8
  144. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +4 -4
  145. claude_mpm/services/mcp_gateway/server/stdio_handler.py +1 -1
  146. claude_mpm/services/mcp_gateway/server/stdio_server.py +5 -2
  147. claude_mpm/services/mcp_gateway/tools/base_adapter.py +15 -15
  148. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +7 -5
  149. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +190 -137
  150. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +5 -5
  151. claude_mpm/services/mcp_gateway/tools/hello_world.py +9 -9
  152. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +16 -16
  153. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +16 -16
  154. claude_mpm/services/memory/builder.py +7 -5
  155. claude_mpm/services/memory/indexed_memory.py +4 -4
  156. claude_mpm/services/memory/optimizer.py +6 -6
  157. claude_mpm/services/memory/router.py +3 -3
  158. claude_mpm/services/monitor/daemon.py +1 -1
  159. claude_mpm/services/monitor/daemon_manager.py +6 -6
  160. claude_mpm/services/monitor/event_emitter.py +2 -2
  161. claude_mpm/services/monitor/management/lifecycle.py +3 -1
  162. claude_mpm/services/monitor/server.py +4 -4
  163. claude_mpm/services/monitor_build_service.py +2 -2
  164. claude_mpm/services/port_manager.py +3 -1
  165. claude_mpm/services/response_tracker.py +2 -2
  166. claude_mpm/services/session_management_service.py +3 -2
  167. claude_mpm/services/socketio/client_proxy.py +2 -2
  168. claude_mpm/services/socketio/dashboard_server.py +4 -3
  169. claude_mpm/services/socketio/event_normalizer.py +11 -7
  170. claude_mpm/services/socketio/handlers/base.py +2 -2
  171. claude_mpm/services/socketio/handlers/connection.py +10 -10
  172. claude_mpm/services/socketio/handlers/connection_handler.py +13 -10
  173. claude_mpm/services/socketio/handlers/hook.py +16 -15
  174. claude_mpm/services/socketio/migration_utils.py +1 -1
  175. claude_mpm/services/socketio/monitor_client.py +5 -5
  176. claude_mpm/services/socketio/server/broadcaster.py +9 -7
  177. claude_mpm/services/socketio/server/connection_manager.py +2 -2
  178. claude_mpm/services/socketio/server/core.py +7 -5
  179. claude_mpm/services/socketio/server/eventbus_integration.py +18 -12
  180. claude_mpm/services/socketio/server/main.py +13 -13
  181. claude_mpm/services/socketio_client_manager.py +4 -4
  182. claude_mpm/services/system_instructions_service.py +2 -2
  183. claude_mpm/services/utility_service.py +5 -2
  184. claude_mpm/services/version_control/branch_strategy.py +2 -2
  185. claude_mpm/services/version_control/git_operations.py +22 -20
  186. claude_mpm/services/version_control/semantic_versioning.py +3 -3
  187. claude_mpm/services/version_control/version_parser.py +7 -5
  188. claude_mpm/services/visualization/mermaid_generator.py +3 -1
  189. claude_mpm/storage/state_storage.py +1 -1
  190. claude_mpm/tools/code_tree_analyzer.py +23 -18
  191. claude_mpm/tools/code_tree_builder.py +2 -2
  192. claude_mpm/tools/code_tree_events.py +10 -8
  193. claude_mpm/tools/socketio_debug.py +3 -3
  194. claude_mpm/utils/agent_dependency_loader.py +6 -2
  195. claude_mpm/utils/dependency_strategies.py +8 -3
  196. claude_mpm/utils/environment_context.py +1 -1
  197. claude_mpm/utils/error_handler.py +2 -2
  198. claude_mpm/utils/file_utils.py +1 -1
  199. claude_mpm/utils/log_cleanup.py +21 -7
  200. claude_mpm/validation/agent_validator.py +2 -2
  201. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/METADATA +1 -1
  202. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/RECORD +204 -191
  203. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/WHEEL +0 -0
  204. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/entry_points.txt +0 -0
  205. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/licenses/LICENSE +0 -0
  206. {claude_mpm-4.3.12.dist-info → claude_mpm-4.3.14.dist-info}/top_level.txt +0 -0
@@ -19,7 +19,7 @@ import threading
19
19
  import time
20
20
  from collections import deque
21
21
  from dataclasses import asdict, dataclass
22
- from datetime import datetime
22
+ from datetime import datetime, timezone
23
23
  from typing import Any, Dict, List, Optional
24
24
 
25
25
  try:
@@ -54,7 +54,7 @@ class CodeNodeEvent:
54
54
  def to_dict(self) -> Dict[str, Any]:
55
55
  """Convert to dictionary for JSON serialization."""
56
56
  data = asdict(self)
57
- data["timestamp"] = datetime.utcnow().isoformat()
57
+ data["timestamp"] = datetime.now(timezone.utc).isoformat()
58
58
  return data
59
59
 
60
60
 
@@ -157,7 +157,7 @@ class CodeTreeEventEmitter:
157
157
 
158
158
  def start(self):
159
159
  """Start the event emitter and background tasks."""
160
- self.stats["start_time"] = datetime.utcnow()
160
+ self.stats["start_time"] = datetime.now(timezone.utc)
161
161
  self._stop_event.clear()
162
162
 
163
163
  # Start background emit task
@@ -168,7 +168,7 @@ class CodeTreeEventEmitter:
168
168
  self.emit(
169
169
  self.EVENT_ANALYSIS_START,
170
170
  {
171
- "timestamp": datetime.utcnow().isoformat(),
171
+ "timestamp": datetime.now(timezone.utc).isoformat(),
172
172
  "batch_size": self.batch_size,
173
173
  "batch_timeout": self.batch_timeout,
174
174
  },
@@ -183,9 +183,11 @@ class CodeTreeEventEmitter:
183
183
  self.emit(
184
184
  self.EVENT_ANALYSIS_COMPLETE,
185
185
  {
186
- "timestamp": datetime.utcnow().isoformat(),
186
+ "timestamp": datetime.now(timezone.utc).isoformat(),
187
187
  "duration": (
188
- (datetime.utcnow() - self.stats["start_time"]).total_seconds()
188
+ (
189
+ datetime.now(timezone.utc) - self.stats["start_time"]
190
+ ).total_seconds()
189
191
  if self.stats["start_time"]
190
192
  else 0
191
193
  ),
@@ -213,7 +215,7 @@ class CodeTreeEventEmitter:
213
215
  event = {
214
216
  "type": event_type,
215
217
  "data": data,
216
- "timestamp": datetime.utcnow().isoformat(),
218
+ "timestamp": datetime.now(timezone.utc).isoformat(),
217
219
  }
218
220
 
219
221
  if batch:
@@ -393,7 +395,7 @@ class CodeTreeEventEmitter:
393
395
  "events": list(self.event_buffer),
394
396
  "count": len(self.event_buffer),
395
397
  },
396
- "timestamp": datetime.utcnow().isoformat(),
398
+ "timestamp": datetime.now(timezone.utc).isoformat(),
397
399
  }
398
400
 
399
401
  self._emit_event(batch_event)
@@ -13,7 +13,7 @@ import signal
13
13
  import sys
14
14
  import time
15
15
  from dataclasses import dataclass, field
16
- from datetime import datetime
16
+ from datetime import datetime, timezone
17
17
  from enum import Enum
18
18
  from pathlib import Path
19
19
  from typing import Any, Dict, List, Optional, Set
@@ -232,7 +232,7 @@ class SocketIODebugger:
232
232
 
233
233
  def _display_event(self, data: Dict[str, Any]):
234
234
  """Display an event based on current mode."""
235
- timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
235
+ timestamp = datetime.now(timezone.utc).strftime("%H:%M:%S.%f")[:-3]
236
236
  event_type = data.get("type", "unknown")
237
237
  event_data = data.get("data", {})
238
238
 
@@ -449,7 +449,7 @@ class SocketIODebugger:
449
449
  if self.quiet and level not in ["error", "critical"]:
450
450
  return
451
451
 
452
- timestamp = datetime.now().strftime("%H:%M:%S")
452
+ timestamp = datetime.now(timezone.utc).strftime("%H:%M:%S")
453
453
 
454
454
  if RICH_AVAILABLE:
455
455
  styles = {
@@ -107,7 +107,9 @@ class AgentDependencyLoader:
107
107
  logger.info(f"Loaded dependencies for {len(agent_dependencies)} agents")
108
108
  return agent_dependencies
109
109
 
110
- def check_python_dependency(self, package_spec: str) -> Tuple[bool, Optional[str]]:
110
+ def check_python_dependency(
111
+ self, package_spec: str
112
+ ) -> Tuple[bool, Optional[str]]:
111
113
  """
112
114
  Check if a Python package dependency is satisfied.
113
115
 
@@ -442,7 +444,9 @@ class AgentDependencyLoader:
442
444
 
443
445
  return compatible, incompatible
444
446
 
445
- def install_missing_dependencies(self, dependencies: List[str]) -> Tuple[bool, str]:
447
+ def install_missing_dependencies(
448
+ self, dependencies: List[str]
449
+ ) -> Tuple[bool, str]:
446
450
  """
447
451
  Install missing Python dependencies using robust retry logic.
448
452
 
@@ -10,7 +10,7 @@ based on the execution context and user preferences.
10
10
  import json
11
11
  import os
12
12
  import sys
13
- from datetime import datetime, timedelta
13
+ from datetime import datetime, timedelta, timezone
14
14
  from enum import Enum
15
15
  from typing import Any, Dict, Optional, Tuple
16
16
 
@@ -160,7 +160,9 @@ class DependencyStrategy:
160
160
  last_check = datetime.fromisoformat(cache.get("timestamp", ""))
161
161
 
162
162
  # Check if cache is still valid
163
- if datetime.now() - last_check < timedelta(seconds=cache_ttl):
163
+ if datetime.now(timezone.utc) - last_check < timedelta(
164
+ seconds=cache_ttl
165
+ ):
164
166
  logger.debug(f"Using cached dependency check from {last_check}")
165
167
  return False
166
168
 
@@ -179,7 +181,10 @@ class DependencyStrategy:
179
181
  try:
180
182
  self.cache_path.parent.mkdir(parents=True, exist_ok=True)
181
183
 
182
- cache_data = {"timestamp": datetime.now().isoformat(), "results": results}
184
+ cache_data = {
185
+ "timestamp": datetime.now(timezone.utc).isoformat(),
186
+ "results": results,
187
+ }
183
188
 
184
189
  with open(self.cache_path, "w") as f:
185
190
  json.dump(cache_data, f, indent=2)
@@ -189,7 +189,7 @@ class EnvironmentContext:
189
189
  get_ipython = globals().get("get_ipython")
190
190
  if get_ipython is not None:
191
191
  return True
192
- except:
192
+ except Exception:
193
193
  pass
194
194
 
195
195
  # Check for Jupyter-specific environment variables
@@ -6,7 +6,7 @@ Inspired by awesome-claude-code's comprehensive error handling approach.
6
6
 
7
7
  import logging
8
8
  import sys
9
- from datetime import datetime
9
+ from datetime import datetime, timezone
10
10
  from functools import wraps
11
11
  from typing import Any, Callable, Dict, List, Optional, Type
12
12
 
@@ -26,7 +26,7 @@ class MPMError(Exception):
26
26
  super().__init__(message)
27
27
  self.details = details or {}
28
28
  self.suggestions = suggestions or []
29
- self.timestamp = datetime.now()
29
+ self.timestamp = datetime.now(timezone.utc)
30
30
 
31
31
  def get_user_friendly_message(self) -> str:
32
32
  """Get a user-friendly error message."""
@@ -150,7 +150,7 @@ def atomic_write(
150
150
  try:
151
151
  if "temp_path" in locals():
152
152
  os.unlink(temp_path)
153
- except:
153
+ except Exception:
154
154
  pass
155
155
  raise FileOperationError(f"Failed to atomically write file {path}: {e}")
156
156
 
@@ -107,7 +107,9 @@ class LogCleanupUtility:
107
107
 
108
108
  try:
109
109
  # Check directory modification time
110
- mtime = datetime.fromtimestamp(session_dir.stat().st_mtime, tz=timezone.utc)
110
+ mtime = datetime.fromtimestamp(
111
+ session_dir.stat().st_mtime, tz=timezone.utc
112
+ )
111
113
 
112
114
  if mtime < cutoff_time:
113
115
  # Calculate directory size
@@ -169,7 +171,9 @@ class LogCleanupUtility:
169
171
  for ext in LogCleanupConfig.ARCHIVE_EXTENSIONS:
170
172
  for archive_file in self.base_log_dir.rglob(f"*{ext}"):
171
173
  try:
172
- mtime = datetime.fromtimestamp(archive_file.stat().st_mtime, tz=timezone.utc)
174
+ mtime = datetime.fromtimestamp(
175
+ archive_file.stat().st_mtime, tz=timezone.utc
176
+ )
173
177
 
174
178
  if mtime < cutoff_time:
175
179
  file_size = archive_file.stat().st_size / (1024 * 1024) # MB
@@ -238,7 +242,9 @@ class LogCleanupUtility:
238
242
 
239
243
  for log_file in log_dir.glob(pattern):
240
244
  try:
241
- mtime = datetime.fromtimestamp(log_file.stat().st_mtime, tz=timezone.utc)
245
+ mtime = datetime.fromtimestamp(
246
+ log_file.stat().st_mtime, tz=timezone.utc
247
+ )
242
248
 
243
249
  if mtime < cutoff_time:
244
250
  file_size = log_file.stat().st_size / (1024 * 1024) # MB
@@ -283,7 +289,7 @@ class LogCleanupUtility:
283
289
  removed_count = 0
284
290
 
285
291
  # Walk bottom-up to remove empty parent directories
286
- for root, dirs, files in os.walk(self.base_log_dir, topdown=False):
292
+ for root, _dirs, _files in os.walk(self.base_log_dir, topdown=False):
287
293
  root_path = Path(root)
288
294
 
289
295
  # Skip the base log directory itself
@@ -331,7 +337,9 @@ class LogCleanupUtility:
331
337
  continue
332
338
 
333
339
  try:
334
- mtime = datetime.fromtimestamp(log_file.stat().st_mtime, tz=timezone.utc)
340
+ mtime = datetime.fromtimestamp(
341
+ log_file.stat().st_mtime, tz=timezone.utc
342
+ )
335
343
 
336
344
  if mtime < cutoff_time:
337
345
  original_size = log_file.stat().st_size / (1024 * 1024) # MB
@@ -408,7 +416,10 @@ class LogCleanupUtility:
408
416
  stats["oldest_session"] = {
409
417
  "name": oldest.name,
410
418
  "age_days": (
411
- datetime.now(timezone.utc) - datetime.fromtimestamp(oldest.stat().st_mtime, tz=timezone.utc)
419
+ datetime.now(timezone.utc)
420
+ - datetime.fromtimestamp(
421
+ oldest.stat().st_mtime, tz=timezone.utc
422
+ )
412
423
  ).days,
413
424
  }
414
425
 
@@ -429,7 +440,10 @@ class LogCleanupUtility:
429
440
  "name": oldest_log.name,
430
441
  "path": str(oldest_log.relative_to(self.base_log_dir)),
431
442
  "age_days": (
432
- datetime.now(timezone.utc) - datetime.fromtimestamp(oldest_log.stat().st_mtime, tz=timezone.utc)
443
+ datetime.now(timezone.utc)
444
+ - datetime.fromtimestamp(
445
+ oldest_log.stat().st_mtime, tz=timezone.utc
446
+ )
433
447
  ).days,
434
448
  }
435
449
 
@@ -22,7 +22,7 @@ Security Considerations:
22
22
  import json
23
23
  import logging
24
24
  from dataclasses import dataclass, field
25
- from datetime import datetime
25
+ from datetime import datetime, timezone
26
26
  from pathlib import Path
27
27
  from typing import Any, Dict, List, Optional, Tuple
28
28
 
@@ -182,7 +182,7 @@ class AgentValidator:
182
182
 
183
183
  # Add metadata
184
184
  result.metadata = {
185
- "validated_at": datetime.utcnow().isoformat(),
185
+ "validated_at": datetime.now(timezone.utc).isoformat(),
186
186
  "schema_version": self.schema.get("version", "1.1.0"),
187
187
  "agent_id": agent_data.get("id", "unknown"),
188
188
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-mpm
3
- Version: 4.3.12
3
+ Version: 4.3.14
4
4
  Summary: Claude Multi-Agent Project Manager - Orchestrate Claude with agent delegation and ticket tracking
5
5
  Author-email: Bob Matsuoka <bob@matsuoka.com>
6
6
  Maintainer: Claude MPM Team