claude-mpm 4.5.11__py3-none-any.whl → 4.5.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 (190) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_ENGINEER.md +47 -0
  3. claude_mpm/agents/BASE_QA.md +60 -0
  4. claude_mpm/agents/frontmatter_validator.py +4 -4
  5. claude_mpm/agents/templates/nextjs_engineer.json +2 -2
  6. claude_mpm/agents/templates/qa.json +13 -3
  7. claude_mpm/agents/templates/react_engineer.json +2 -2
  8. claude_mpm/agents/templates/typescript_engineer.json +2 -2
  9. claude_mpm/agents/templates/web_qa.json +14 -3
  10. claude_mpm/cli/commands/agent_manager.py +3 -3
  11. claude_mpm/cli/commands/agents.py +6 -6
  12. claude_mpm/cli/commands/aggregate.py +4 -4
  13. claude_mpm/cli/commands/analyze.py +2 -2
  14. claude_mpm/cli/commands/analyze_code.py +1 -1
  15. claude_mpm/cli/commands/cleanup.py +3 -3
  16. claude_mpm/cli/commands/config.py +2 -2
  17. claude_mpm/cli/commands/configure.py +14 -14
  18. claude_mpm/cli/commands/dashboard.py +1 -1
  19. claude_mpm/cli/commands/debug.py +3 -3
  20. claude_mpm/cli/commands/doctor.py +1 -1
  21. claude_mpm/cli/commands/mcp.py +7 -7
  22. claude_mpm/cli/commands/mcp_command_router.py +1 -1
  23. claude_mpm/cli/commands/mcp_config.py +2 -2
  24. claude_mpm/cli/commands/mcp_external_commands.py +2 -2
  25. claude_mpm/cli/commands/mcp_install_commands.py +3 -3
  26. claude_mpm/cli/commands/mcp_pipx_config.py +2 -2
  27. claude_mpm/cli/commands/mcp_setup_external.py +3 -3
  28. claude_mpm/cli/commands/monitor.py +1 -1
  29. claude_mpm/cli/commands/mpm_init_handler.py +1 -1
  30. claude_mpm/cli/interactive/agent_wizard.py +1 -1
  31. claude_mpm/cli/parsers/search_parser.py +1 -1
  32. claude_mpm/cli/shared/argument_patterns.py +2 -2
  33. claude_mpm/cli/shared/base_command.py +1 -1
  34. claude_mpm/cli/startup_logging.py +6 -4
  35. claude_mpm/config/experimental_features.py +4 -4
  36. claude_mpm/config/socketio_config.py +2 -2
  37. claude_mpm/core/agent_session_manager.py +2 -2
  38. claude_mpm/core/api_validator.py +3 -3
  39. claude_mpm/core/base_service.py +10 -1
  40. claude_mpm/core/cache.py +2 -2
  41. claude_mpm/core/config.py +4 -4
  42. claude_mpm/core/config_aliases.py +4 -4
  43. claude_mpm/core/config_constants.py +1 -1
  44. claude_mpm/core/error_handler.py +1 -1
  45. claude_mpm/core/file_utils.py +5 -5
  46. claude_mpm/core/framework/formatters/capability_generator.py +5 -5
  47. claude_mpm/core/framework/loaders/agent_loader.py +1 -1
  48. claude_mpm/core/framework/processors/metadata_processor.py +1 -1
  49. claude_mpm/core/framework/processors/template_processor.py +3 -3
  50. claude_mpm/core/framework_loader.py +2 -2
  51. claude_mpm/core/log_manager.py +4 -4
  52. claude_mpm/core/logger.py +2 -2
  53. claude_mpm/core/optimized_startup.py +1 -1
  54. claude_mpm/core/output_style_manager.py +1 -1
  55. claude_mpm/core/service_registry.py +2 -2
  56. claude_mpm/core/session_manager.py +3 -3
  57. claude_mpm/core/shared/config_loader.py +1 -1
  58. claude_mpm/core/socketio_pool.py +2 -2
  59. claude_mpm/core/unified_agent_registry.py +2 -2
  60. claude_mpm/core/unified_config.py +6 -6
  61. claude_mpm/core/unified_paths.py +2 -2
  62. claude_mpm/dashboard/api/simple_directory.py +1 -1
  63. claude_mpm/generators/agent_profile_generator.py +1 -1
  64. claude_mpm/hooks/claude_hooks/event_handlers.py +2 -2
  65. claude_mpm/hooks/claude_hooks/installer.py +9 -9
  66. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +7 -2
  67. claude_mpm/hooks/claude_hooks/tool_analysis.py +2 -2
  68. claude_mpm/hooks/memory_integration_hook.py +1 -1
  69. claude_mpm/hooks/validation_hooks.py +1 -1
  70. claude_mpm/init.py +4 -4
  71. claude_mpm/models/agent_session.py +1 -1
  72. claude_mpm/scripts/socketio_daemon.py +5 -5
  73. claude_mpm/services/__init__.py +2 -2
  74. claude_mpm/services/agent_capabilities_service.py +1 -1
  75. claude_mpm/services/agents/agent_builder.py +6 -4
  76. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -1
  77. claude_mpm/services/agents/deployment/agent_metrics_collector.py +1 -1
  78. claude_mpm/services/agents/deployment/agent_record_service.py +3 -3
  79. claude_mpm/services/agents/deployment/deployment_wrapper.py +1 -1
  80. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +2 -2
  81. claude_mpm/services/agents/loading/agent_profile_loader.py +2 -2
  82. claude_mpm/services/agents/local_template_manager.py +5 -5
  83. claude_mpm/services/agents/registry/deployed_agent_discovery.py +1 -1
  84. claude_mpm/services/agents/registry/modification_tracker.py +19 -11
  85. claude_mpm/services/async_session_logger.py +1 -1
  86. claude_mpm/services/claude_session_logger.py +1 -1
  87. claude_mpm/services/cli/agent_listing_service.py +3 -3
  88. claude_mpm/services/cli/agent_validation_service.py +1 -1
  89. claude_mpm/services/cli/session_manager.py +2 -2
  90. claude_mpm/services/core/path_resolver.py +1 -1
  91. claude_mpm/services/diagnostics/checks/agent_check.py +1 -1
  92. claude_mpm/services/diagnostics/checks/claude_code_check.py +2 -2
  93. claude_mpm/services/diagnostics/checks/common_issues_check.py +3 -3
  94. claude_mpm/services/diagnostics/checks/configuration_check.py +2 -2
  95. claude_mpm/services/diagnostics/checks/installation_check.py +1 -1
  96. claude_mpm/services/diagnostics/checks/mcp_check.py +1 -1
  97. claude_mpm/services/diagnostics/checks/mcp_services_check.py +9 -9
  98. claude_mpm/services/diagnostics/checks/monitor_check.py +1 -1
  99. claude_mpm/services/diagnostics/doctor_reporter.py +1 -1
  100. claude_mpm/services/event_aggregator.py +1 -1
  101. claude_mpm/services/event_bus/event_bus.py +9 -2
  102. claude_mpm/services/events/consumers/dead_letter.py +2 -2
  103. claude_mpm/services/framework_claude_md_generator/__init__.py +1 -1
  104. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +3 -3
  105. claude_mpm/services/framework_claude_md_generator/version_manager.py +1 -1
  106. claude_mpm/services/hook_installer_service.py +7 -7
  107. claude_mpm/services/infrastructure/context_preservation.py +7 -7
  108. claude_mpm/services/infrastructure/daemon_manager.py +5 -5
  109. claude_mpm/services/mcp_config_manager.py +10 -10
  110. claude_mpm/services/mcp_gateway/auto_configure.py +5 -5
  111. claude_mpm/services/mcp_gateway/config/config_loader.py +2 -2
  112. claude_mpm/services/mcp_gateway/config/configuration.py +5 -3
  113. claude_mpm/services/mcp_gateway/core/process_pool.py +3 -3
  114. claude_mpm/services/mcp_gateway/core/singleton_manager.py +2 -2
  115. claude_mpm/services/mcp_gateway/core/startup_verification.py +1 -1
  116. claude_mpm/services/mcp_gateway/main.py +1 -1
  117. claude_mpm/services/mcp_gateway/registry/service_registry.py +4 -2
  118. claude_mpm/services/mcp_gateway/registry/tool_registry.py +2 -1
  119. claude_mpm/services/mcp_gateway/server/stdio_handler.py +1 -1
  120. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
  121. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +1 -1
  122. claude_mpm/services/mcp_gateway/tools/hello_world.py +1 -1
  123. claude_mpm/services/mcp_gateway/utils/package_version_checker.py +5 -5
  124. claude_mpm/services/mcp_gateway/utils/update_preferences.py +2 -2
  125. claude_mpm/services/mcp_service_verifier.py +1 -1
  126. claude_mpm/services/memory/builder.py +1 -1
  127. claude_mpm/services/memory/cache/shared_prompt_cache.py +2 -1
  128. claude_mpm/services/memory/indexed_memory.py +3 -3
  129. claude_mpm/services/monitor/daemon.py +1 -1
  130. claude_mpm/services/monitor/daemon_manager.py +9 -9
  131. claude_mpm/services/monitor/handlers/file.py +1 -1
  132. claude_mpm/services/monitor/handlers/hooks.py +3 -3
  133. claude_mpm/services/monitor/management/lifecycle.py +7 -7
  134. claude_mpm/services/monitor/server.py +2 -2
  135. claude_mpm/services/orphan_detection.py +11 -16
  136. claude_mpm/services/port_manager.py +2 -2
  137. claude_mpm/services/project/analyzer.py +3 -3
  138. claude_mpm/services/project/archive_manager.py +17 -13
  139. claude_mpm/services/project/dependency_analyzer.py +4 -4
  140. claude_mpm/services/project/documentation_manager.py +4 -4
  141. claude_mpm/services/project/enhanced_analyzer.py +19 -8
  142. claude_mpm/services/project/registry.py +4 -4
  143. claude_mpm/services/project_port_allocator.py +7 -12
  144. claude_mpm/services/session_management_service.py +1 -1
  145. claude_mpm/services/socketio/event_normalizer.py +1 -1
  146. claude_mpm/services/socketio/handlers/code_analysis.py +14 -12
  147. claude_mpm/services/socketio/handlers/file.py +1 -1
  148. claude_mpm/services/socketio/migration_utils.py +1 -1
  149. claude_mpm/services/socketio/server/core.py +1 -1
  150. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +1 -1
  151. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +4 -4
  152. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +1 -1
  153. claude_mpm/services/unified/config_strategies/config_schema.py +4 -4
  154. claude_mpm/services/unified/config_strategies/context_strategy.py +8 -6
  155. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +10 -10
  156. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +5 -5
  157. claude_mpm/services/unified/config_strategies/unified_config_service.py +8 -8
  158. claude_mpm/services/unified/config_strategies/validation_strategy.py +15 -15
  159. claude_mpm/services/unified/deployment_strategies/base.py +4 -4
  160. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +15 -15
  161. claude_mpm/services/unified/deployment_strategies/local.py +11 -11
  162. claude_mpm/services/unified/deployment_strategies/utils.py +11 -9
  163. claude_mpm/services/unified/deployment_strategies/vercel.py +7 -9
  164. claude_mpm/services/unified/unified_config.py +5 -5
  165. claude_mpm/services/unified/unified_deployment.py +2 -2
  166. claude_mpm/services/utility_service.py +1 -1
  167. claude_mpm/services/version_control/conflict_resolution.py +2 -2
  168. claude_mpm/services/version_control/git_operations.py +3 -3
  169. claude_mpm/services/version_control/semantic_versioning.py +13 -13
  170. claude_mpm/services/version_control/version_parser.py +1 -1
  171. claude_mpm/storage/state_storage.py +12 -13
  172. claude_mpm/tools/code_tree_analyzer.py +5 -5
  173. claude_mpm/tools/code_tree_builder.py +4 -4
  174. claude_mpm/tools/socketio_debug.py +1 -1
  175. claude_mpm/utils/agent_dependency_loader.py +4 -4
  176. claude_mpm/utils/common.py +2 -2
  177. claude_mpm/utils/config_manager.py +3 -3
  178. claude_mpm/utils/dependency_cache.py +2 -2
  179. claude_mpm/utils/dependency_strategies.py +6 -6
  180. claude_mpm/utils/file_utils.py +11 -11
  181. claude_mpm/utils/log_cleanup.py +1 -1
  182. claude_mpm/utils/path_operations.py +1 -1
  183. claude_mpm/validation/agent_validator.py +2 -2
  184. claude_mpm/validation/frontmatter_validator.py +1 -1
  185. {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.13.dist-info}/METADATA +1 -1
  186. {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.13.dist-info}/RECORD +190 -190
  187. {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.13.dist-info}/WHEEL +0 -0
  188. {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.13.dist-info}/entry_points.txt +0 -0
  189. {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.13.dist-info}/licenses/LICENSE +0 -0
  190. {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.13.dist-info}/top_level.txt +0 -0
@@ -15,7 +15,7 @@ This module provides:
15
15
 
16
16
  from abc import abstractmethod
17
17
  from dataclasses import dataclass, field
18
- from datetime import datetime
18
+ from datetime import datetime, timezone
19
19
  from enum import Enum
20
20
  from pathlib import Path
21
21
  from typing import Any, Dict, List, Optional, Union
@@ -255,7 +255,7 @@ class DeploymentStrategy(BaseDeploymentStrategy):
255
255
  result = DeploymentResult(
256
256
  success=False,
257
257
  status=DeploymentStatus.PENDING,
258
- started_at=datetime.now(),
258
+ started_at=datetime.now(timezone.utc),
259
259
  )
260
260
 
261
261
  try:
@@ -334,7 +334,7 @@ class DeploymentStrategy(BaseDeploymentStrategy):
334
334
  result.errors.append(f"Rollback failed: {rollback_error!s}")
335
335
 
336
336
  finally:
337
- result.completed_at = datetime.now()
337
+ result.completed_at = datetime.now(timezone.utc)
338
338
  if result.started_at:
339
339
  result.duration_seconds = (
340
340
  result.completed_at - result.started_at
@@ -532,7 +532,7 @@ class DeploymentStrategy(BaseDeploymentStrategy):
532
532
  return {
533
533
  "deployment_id": deployment_info.get("deployment_id"),
534
534
  "deployed_path": str(deployment_info.get("deployed_path")),
535
- "timestamp": datetime.now().isoformat(),
535
+ "timestamp": datetime.now(timezone.utc).isoformat(),
536
536
  "artifacts": deployment_info.get("artifacts", []),
537
537
  }
538
538
 
@@ -8,7 +8,7 @@ Reduces duplication by sharing common cloud deployment patterns.
8
8
 
9
9
  import json
10
10
  import subprocess
11
- from datetime import datetime
11
+ from datetime import datetime, timezone
12
12
  from pathlib import Path
13
13
  from typing import Any, Dict, List
14
14
 
@@ -48,7 +48,7 @@ class RailwayDeploymentStrategy(DeploymentStrategy):
48
48
  # Check Railway CLI
49
49
  try:
50
50
  subprocess.run(["railway", "--version"], capture_output=True, check=True)
51
- except:
51
+ except (subprocess.CalledProcessError, FileNotFoundError, OSError):
52
52
  errors.append(
53
53
  "Railway CLI not installed. Install with: npm i -g @railway/cli"
54
54
  )
@@ -56,7 +56,7 @@ class RailwayDeploymentStrategy(DeploymentStrategy):
56
56
  # Check authentication
57
57
  try:
58
58
  subprocess.run(["railway", "whoami"], capture_output=True, check=True)
59
- except:
59
+ except (subprocess.CalledProcessError, FileNotFoundError, OSError):
60
60
  errors.append("Not authenticated with Railway. Run: railway login")
61
61
 
62
62
  return errors
@@ -97,13 +97,13 @@ class RailwayDeploymentStrategy(DeploymentStrategy):
97
97
  break
98
98
 
99
99
  return {
100
- "deployment_id": f"railway_{datetime.now().timestamp()}",
100
+ "deployment_id": f"railway_{datetime.now(timezone.utc).timestamp()}",
101
101
  "deployment_url": deployment_url,
102
102
  "deployed_path": deploy_dir,
103
103
  "stdout": result.stdout,
104
104
  }
105
105
  except subprocess.CalledProcessError as e:
106
- raise Exception(f"Railway deployment failed: {e.stderr}")
106
+ raise Exception(f"Railway deployment failed: {e.stderr}") from e
107
107
 
108
108
  def verify(
109
109
  self, context: DeploymentContext, deployment_info: Dict[str, Any]
@@ -150,7 +150,7 @@ class AWSDeploymentStrategy(DeploymentStrategy):
150
150
  # Check AWS CLI
151
151
  try:
152
152
  subprocess.run(["aws", "--version"], capture_output=True, check=True)
153
- except:
153
+ except (subprocess.CalledProcessError, FileNotFoundError, OSError):
154
154
  errors.append("AWS CLI not installed")
155
155
 
156
156
  # Check credentials
@@ -158,7 +158,7 @@ class AWSDeploymentStrategy(DeploymentStrategy):
158
158
  subprocess.run(
159
159
  ["aws", "sts", "get-caller-identity"], capture_output=True, check=True
160
160
  )
161
- except:
161
+ except (subprocess.CalledProcessError, FileNotFoundError, OSError):
162
162
  errors.append("AWS credentials not configured")
163
163
 
164
164
  # Validate service type
@@ -218,7 +218,7 @@ class AWSDeploymentStrategy(DeploymentStrategy):
218
218
  "--zip-file",
219
219
  f"fileb://{artifact}",
220
220
  ]
221
- except:
221
+ except (subprocess.CalledProcessError, FileNotFoundError, OSError):
222
222
  # Create new function
223
223
  cmd = [
224
224
  "aws",
@@ -277,7 +277,7 @@ class AWSDeploymentStrategy(DeploymentStrategy):
277
277
  ]
278
278
  subprocess.run(cmd, capture_output=True, check=True)
279
279
  return True
280
- except:
280
+ except (subprocess.CalledProcessError, FileNotFoundError, OSError):
281
281
  return False
282
282
 
283
283
  return True
@@ -301,7 +301,7 @@ class AWSDeploymentStrategy(DeploymentStrategy):
301
301
  try:
302
302
  subprocess.run(cmd, check=True)
303
303
  return True
304
- except:
304
+ except (subprocess.CalledProcessError, FileNotFoundError, OSError):
305
305
  pass
306
306
  return False
307
307
 
@@ -334,7 +334,7 @@ class DockerDeploymentStrategy(DeploymentStrategy):
334
334
  # Check Docker
335
335
  try:
336
336
  subprocess.run(["docker", "--version"], capture_output=True, check=True)
337
- except:
337
+ except (subprocess.CalledProcessError, FileNotFoundError, OSError):
338
338
  errors.append("Docker not installed or not running")
339
339
 
340
340
  # Check Dockerfile exists
@@ -356,7 +356,7 @@ class DockerDeploymentStrategy(DeploymentStrategy):
356
356
  """Execute Docker deployment."""
357
357
  source_dir = artifacts[0] if artifacts[0].is_dir() else artifacts[0].parent
358
358
  image_name = context.config.get(
359
- "image_name", f"app_{datetime.now().timestamp()}"
359
+ "image_name", f"app_{datetime.now(timezone.utc).timestamp()}"
360
360
  )
361
361
  container_name = context.config.get("container_name", image_name)
362
362
 
@@ -444,7 +444,7 @@ class GitDeploymentStrategy(DeploymentStrategy):
444
444
  # Check Git
445
445
  try:
446
446
  subprocess.run(["git", "--version"], capture_output=True, check=True)
447
- except:
447
+ except (subprocess.CalledProcessError, FileNotFoundError, OSError):
448
448
  errors.append("Git not installed")
449
449
 
450
450
  # Check remote URL
@@ -529,7 +529,7 @@ class GitDeploymentStrategy(DeploymentStrategy):
529
529
  check=True,
530
530
  )
531
531
  return True
532
- except:
532
+ except (subprocess.CalledProcessError, FileNotFoundError, OSError):
533
533
  return False
534
534
 
535
535
  def rollback(self, context: DeploymentContext, result: DeploymentResult) -> bool:
@@ -553,7 +553,7 @@ class GitDeploymentStrategy(DeploymentStrategy):
553
553
  check=True,
554
554
  )
555
555
  return True
556
- except:
556
+ except (subprocess.CalledProcessError, FileNotFoundError, OSError):
557
557
  pass
558
558
  return False
559
559
 
@@ -13,7 +13,7 @@ Consolidates functionality from:
13
13
  import json
14
14
  import shutil
15
15
  import tempfile
16
- from datetime import datetime
16
+ from datetime import datetime, timezone
17
17
  from pathlib import Path
18
18
  from typing import Any, Dict, List, Optional
19
19
 
@@ -183,7 +183,7 @@ class LocalDeploymentStrategy(DeploymentStrategy):
183
183
  "deployed_path": target_path,
184
184
  "deployed_files": deployed_files,
185
185
  "artifacts": [str(a) for a in artifacts],
186
- "timestamp": datetime.now().isoformat(),
186
+ "timestamp": datetime.now(timezone.utc).isoformat(),
187
187
  }
188
188
 
189
189
  def verify(
@@ -300,7 +300,7 @@ class LocalDeploymentStrategy(DeploymentStrategy):
300
300
  def _check_write_permission(self, path: Path) -> bool:
301
301
  """Check if we have write permission to path."""
302
302
  try:
303
- test_file = path / f".write_test_{datetime.now().timestamp()}"
303
+ test_file = path / f".write_test_{datetime.now(timezone.utc).timestamp()}"
304
304
  test_file.touch()
305
305
  test_file.unlink()
306
306
  return True
@@ -309,9 +309,7 @@ class LocalDeploymentStrategy(DeploymentStrategy):
309
309
 
310
310
  def _generate_deployment_id(self) -> str:
311
311
  """Generate unique deployment ID."""
312
- return (
313
- f"local_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{id(self) % 10000:04d}"
314
- )
312
+ return f"local_{datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')}_{id(self) % 10000:04d}"
315
313
 
316
314
  def _create_backup(self, context: DeploymentContext) -> Optional[Path]:
317
315
  """Create backup of target before deployment."""
@@ -324,7 +322,7 @@ class LocalDeploymentStrategy(DeploymentStrategy):
324
322
  backup_dir = Path(tempfile.gettempdir()) / "claude_mpm_backups"
325
323
  backup_dir.mkdir(parents=True, exist_ok=True)
326
324
 
327
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
325
+ timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
328
326
  backup_name = f"{target_path.name}.backup_{timestamp}"
329
327
  backup_path = backup_dir / backup_name
330
328
 
@@ -343,7 +341,9 @@ class LocalDeploymentStrategy(DeploymentStrategy):
343
341
  def _write_version_file(self, target_path: Path, version: str) -> None:
344
342
  """Write version file to deployment."""
345
343
  version_file = target_path / ".version"
346
- version_file.write_text(f"{version}\n{datetime.now().isoformat()}\n")
344
+ version_file.write_text(
345
+ f"{version}\n{datetime.now(timezone.utc).isoformat()}\n"
346
+ )
347
347
 
348
348
  # Agent deployment methods (consolidating agent_deployment.py patterns)
349
349
 
@@ -409,7 +409,7 @@ class LocalDeploymentStrategy(DeploymentStrategy):
409
409
 
410
410
  for yaml_file in yaml_files:
411
411
  try:
412
- with open(yaml_file) as f:
412
+ with yaml_file.open() as f:
413
413
  data = yaml.safe_load(f)
414
414
  # Basic agent structure validation
415
415
  if not isinstance(data, dict):
@@ -425,11 +425,11 @@ class LocalDeploymentStrategy(DeploymentStrategy):
425
425
 
426
426
  def _convert_json_to_yaml(self, json_path: Path) -> Path:
427
427
  """Convert JSON agent to YAML format."""
428
- with open(json_path) as f:
428
+ with json_path.open() as f:
429
429
  data = json.load(f)
430
430
 
431
431
  yaml_path = Path(tempfile.gettempdir()) / f"{json_path.stem}.yaml"
432
- with open(yaml_path, "w") as f:
432
+ with yaml_path.open("w") as f:
433
433
  yaml.dump(data, f, default_flow_style=False, sort_keys=False)
434
434
 
435
435
  return yaml_path
@@ -19,7 +19,7 @@ import json
19
19
  import shutil
20
20
  import subprocess
21
21
  import tempfile
22
- from datetime import datetime
22
+ from datetime import datetime, timezone
23
23
  from pathlib import Path
24
24
  from typing import Any, Dict, List, Optional, Tuple, Union
25
25
 
@@ -162,7 +162,7 @@ def prepare_deployment_artifact(
162
162
  metadata = {
163
163
  "source": str(source_path),
164
164
  "type": artifact_type,
165
- "created_at": datetime.now().isoformat(),
165
+ "created_at": datetime.now(timezone.utc).isoformat(),
166
166
  }
167
167
 
168
168
  # Auto-detect type
@@ -257,7 +257,7 @@ def verify_deployment_health(
257
257
  """
258
258
  health = {
259
259
  "status": "unknown",
260
- "timestamp": datetime.now().isoformat(),
260
+ "timestamp": datetime.now(timezone.utc).isoformat(),
261
261
  "checks": {},
262
262
  "errors": [],
263
263
  }
@@ -464,7 +464,7 @@ def get_version_info(path: Union[str, Path]) -> Dict[str, Any]:
464
464
 
465
465
  if file_path.exists():
466
466
  if version_file == "package.json":
467
- with open(file_path) as f:
467
+ with file_path.open() as f:
468
468
  data = json.load(f)
469
469
  version_info["version"] = data.get("version")
470
470
  version_info["source"] = "package.json"
@@ -512,7 +512,9 @@ def update_version(
512
512
  shutil.copy2(version_file, backup_file)
513
513
 
514
514
  # Write new version
515
- version_file.write_text(f"{new_version}\n{datetime.now().isoformat()}\n")
515
+ version_file.write_text(
516
+ f"{new_version}\n{datetime.now(timezone.utc).isoformat()}\n"
517
+ )
516
518
  return True
517
519
 
518
520
  except Exception as e:
@@ -539,7 +541,7 @@ def calculate_checksum(path: Union[str, Path], algorithm: str = "sha256") -> str
539
541
  hasher = hashlib.new(algorithm)
540
542
 
541
543
  if path.is_file():
542
- with open(path, "rb") as f:
544
+ with path.open("rb") as f:
543
545
  for chunk in iter(lambda: f.read(4096), b""):
544
546
  hasher.update(chunk)
545
547
  elif path.is_dir():
@@ -547,7 +549,7 @@ def calculate_checksum(path: Union[str, Path], algorithm: str = "sha256") -> str
547
549
  for file_path in sorted(path.rglob("*")):
548
550
  if file_path.is_file():
549
551
  hasher.update(str(file_path.relative_to(path)).encode())
550
- with open(file_path, "rb") as f:
552
+ with file_path.open("rb") as f:
551
553
  for chunk in iter(lambda: f.read(4096), b""):
552
554
  hasher.update(chunk)
553
555
 
@@ -616,7 +618,7 @@ def load_env_file(env_file: Union[str, Path]) -> Dict[str, str]:
616
618
  env_path = Path(env_file)
617
619
 
618
620
  if env_path.exists():
619
- with open(env_path) as f:
621
+ with env_path.open() as f:
620
622
  for line in f:
621
623
  line = line.strip()
622
624
  if line and not line.startswith("#") and "=" in line:
@@ -656,7 +658,7 @@ def export_env_to_file(env_vars: Dict[str, str], output_file: Union[str, Path])
656
658
  output_path = Path(output_file)
657
659
  output_path.parent.mkdir(parents=True, exist_ok=True)
658
660
 
659
- with open(output_path, "w") as f:
661
+ with output_path.open("w") as f:
660
662
  for key, value in env_vars.items():
661
663
  # Escape special characters in value
662
664
  if " " in value or '"' in value:
@@ -9,7 +9,7 @@ Consolidates Vercel deployment patterns from multiple services.
9
9
  import json
10
10
  import subprocess
11
11
  import tempfile
12
- from datetime import datetime
12
+ from datetime import datetime, timezone
13
13
  from pathlib import Path
14
14
  from typing import Any, Dict, List, Optional
15
15
 
@@ -203,13 +203,13 @@ class VercelDeploymentStrategy(DeploymentStrategy):
203
203
  "deployed_path": deploy_dir,
204
204
  "production": context.config.get("production", False),
205
205
  "stdout": result.stdout,
206
- "timestamp": datetime.now().isoformat(),
206
+ "timestamp": datetime.now(timezone.utc).isoformat(),
207
207
  }
208
208
  raise Exception("Could not parse deployment URL from Vercel output")
209
209
 
210
210
  except subprocess.CalledProcessError as e:
211
211
  self._logger.error(f"Vercel deployment failed: {e.stderr}")
212
- raise Exception(f"Deployment failed: {e.stderr}")
212
+ raise Exception(f"Deployment failed: {e.stderr}") from e
213
213
 
214
214
  def verify(
215
215
  self, context: DeploymentContext, deployment_info: Dict[str, Any]
@@ -336,7 +336,7 @@ class VercelDeploymentStrategy(DeploymentStrategy):
336
336
  health["checks"][f"function_{func_name}"] = (
337
337
  response.status < 500
338
338
  )
339
- except:
339
+ except (urllib.error.URLError, OSError, TimeoutError):
340
340
  health["checks"][f"function_{func_name}"] = False
341
341
 
342
342
  # Determine overall status
@@ -416,7 +416,7 @@ class VercelDeploymentStrategy(DeploymentStrategy):
416
416
 
417
417
  if vercel_config:
418
418
  config_path = deploy_dir / "vercel.json"
419
- with open(config_path, "w") as f:
419
+ with config_path.open("w") as f:
420
420
  json.dump(vercel_config, f, indent=2)
421
421
  return config_path
422
422
 
@@ -430,7 +430,7 @@ class VercelDeploymentStrategy(DeploymentStrategy):
430
430
 
431
431
  if env_vars:
432
432
  env_file = deploy_dir / ".env"
433
- with open(env_file, "w") as f:
433
+ with env_file.open("w") as f:
434
434
  for key, value in env_vars.items():
435
435
  f.write(f"{key}={value}\n")
436
436
  return env_file
@@ -471,6 +471,4 @@ class VercelDeploymentStrategy(DeploymentStrategy):
471
471
 
472
472
  def _generate_deployment_id(self) -> str:
473
473
  """Generate unique deployment ID."""
474
- return (
475
- f"vercel_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{id(self) % 10000:04d}"
476
- )
474
+ return f"vercel_{datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')}_{id(self) % 10000:04d}"
@@ -335,14 +335,14 @@ class UnifiedConfigManager(IConfigurationService, IUnifiedService):
335
335
 
336
336
  # Save based on file extension
337
337
  if target_path.suffix == ".json":
338
- with open(target_path, "w") as f:
338
+ with target_path.open("w") as f:
339
339
  json.dump(transformed_config, f, indent=2)
340
340
  elif target_path.suffix in [".yaml", ".yml"]:
341
341
  # Would use yaml library here
342
- with open(target_path, "w") as f:
342
+ with target_path.open("w") as f:
343
343
  f.write(str(transformed_config))
344
344
  else:
345
- with open(target_path, "w") as f:
345
+ with target_path.open("w") as f:
346
346
  f.write(str(transformed_config))
347
347
 
348
348
  return ConfigurationResult(
@@ -685,6 +685,6 @@ class UnifiedConfigManager(IConfigurationService, IUnifiedService):
685
685
 
686
686
  def _get_timestamp(self) -> str:
687
687
  """Get current timestamp."""
688
- from datetime import datetime
688
+ from datetime import datetime, timezone
689
689
 
690
- return datetime.now().isoformat()
690
+ return datetime.now(timezone.utc).isoformat()
@@ -460,6 +460,6 @@ class UnifiedDeploymentService(IDeploymentService, IUnifiedService):
460
460
 
461
461
  def _get_timestamp(self) -> str:
462
462
  """Get current timestamp."""
463
- from datetime import datetime
463
+ from datetime import datetime, timezone
464
464
 
465
- return datetime.now().isoformat()
465
+ return datetime.now(timezone.utc).isoformat()
@@ -110,7 +110,7 @@ class UtilityService(BaseService, UtilityServiceInterface):
110
110
  **event_data,
111
111
  }
112
112
 
113
- with open(log_file, "a") as f:
113
+ with log_file.open("a") as f:
114
114
  f.write(json.dumps(log_entry) + "\n")
115
115
 
116
116
  except OSError as e:
@@ -321,7 +321,7 @@ class ConflictResolutionManager:
321
321
 
322
322
  # Check content (simple heuristic)
323
323
  try:
324
- with open(file_path, "rb") as f:
324
+ with file_path.open("rb") as f:
325
325
  chunk = f.read(1024)
326
326
  if b"\0" in chunk:
327
327
  return True
@@ -596,7 +596,7 @@ class ConflictResolutionManager:
596
596
  )
597
597
 
598
598
  # Write resolved content
599
- with open(file_path, "w", encoding="utf-8") as f:
599
+ with file_path.open("w", encoding="utf-8") as f:
600
600
  f.write(resolved_content)
601
601
 
602
602
  return ConflictResolution(
@@ -147,10 +147,10 @@ class GitOperationsManager:
147
147
 
148
148
  return result
149
149
 
150
- except FileNotFoundError:
151
- raise GitOperationError("Git is not installed or not in PATH")
150
+ except FileNotFoundError as e:
151
+ raise GitOperationError("Git is not installed or not in PATH") from e
152
152
  except Exception as e:
153
- raise GitOperationError(f"Error running Git command: {e}")
153
+ raise GitOperationError(f"Error running Git command: {e}") from e
154
154
 
155
155
  def get_current_branch(self) -> str:
156
156
  """Get the current Git branch name."""
@@ -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: # noqa: PLR0911
103
+ def __lt__(self, other: "SemanticVersion") -> bool:
104
104
  """Compare versions for sorting according to semver precedence.
105
105
 
106
106
  Comparison Rules:
@@ -416,7 +416,7 @@ class SemanticVersionManager:
416
416
  return self._parse_toml_version_regex(file_path)
417
417
 
418
418
  try:
419
- with open(file_path, "rb") as f:
419
+ with file_path.open("rb") as f:
420
420
  data = tomllib.load(f)
421
421
 
422
422
  # Try different locations for version
@@ -437,7 +437,7 @@ class SemanticVersionManager:
437
437
  def _parse_toml_version_regex(self, file_path: Path) -> Optional[str]:
438
438
  """Parse version from TOML file using regex."""
439
439
  try:
440
- with open(file_path) as f:
440
+ with file_path.open() as f:
441
441
  content = f.read()
442
442
 
443
443
  # Look for version = "x.y.z" pattern
@@ -463,7 +463,7 @@ class SemanticVersionManager:
463
463
  def _parse_version_file(self, file_path: Path) -> Optional[str]:
464
464
  """Parse version from simple version file."""
465
465
  try:
466
- with open(file_path) as f:
466
+ with file_path.open() as f:
467
467
  return f.read().strip()
468
468
  except Exception:
469
469
  return None
@@ -471,7 +471,7 @@ class SemanticVersionManager:
471
471
  def _parse_pom_xml_version(self, file_path: Path) -> Optional[str]:
472
472
  """Parse version from Maven pom.xml."""
473
473
  try:
474
- with open(file_path) as f:
474
+ with file_path.open() as f:
475
475
  content = f.read()
476
476
 
477
477
  # Simple regex to find version in pom.xml
@@ -673,7 +673,7 @@ class SemanticVersionManager:
673
673
  def _update_toml_version(self, file_path: Path, new_version: str) -> bool:
674
674
  """Update version in TOML file."""
675
675
  try:
676
- with open(file_path) as f:
676
+ with file_path.open() as f:
677
677
  content = f.read()
678
678
 
679
679
  # Replace version field
@@ -691,7 +691,7 @@ class SemanticVersionManager:
691
691
  break
692
692
 
693
693
  if updated:
694
- with open(file_path, "w") as f:
694
+ with file_path.open("w") as f:
695
695
  f.write(content)
696
696
  return True
697
697
 
@@ -703,7 +703,7 @@ class SemanticVersionManager:
703
703
  def _update_simple_version_file(self, file_path: Path, new_version: str) -> bool:
704
704
  """Update version in simple version file."""
705
705
  try:
706
- with open(file_path, "w") as f:
706
+ with file_path.open("w") as f:
707
707
  f.write(new_version + "\n")
708
708
  return True
709
709
  except Exception:
@@ -712,7 +712,7 @@ class SemanticVersionManager:
712
712
  def _update_pom_xml_version(self, file_path: Path, new_version: str) -> bool:
713
713
  """Update version in Maven pom.xml."""
714
714
  try:
715
- with open(file_path) as f:
715
+ with file_path.open() as f:
716
716
  content = f.read()
717
717
 
718
718
  # Replace first version tag (project version)
@@ -722,7 +722,7 @@ class SemanticVersionManager:
722
722
  new_content = re.sub(pattern, replacement, content, count=1)
723
723
 
724
724
  if new_content != content:
725
- with open(file_path, "w") as f:
725
+ with file_path.open("w") as f:
726
726
  f.write(new_content)
727
727
  return True
728
728
 
@@ -841,7 +841,7 @@ class SemanticVersionManager:
841
841
 
842
842
  # Read existing changelog or create new one
843
843
  if changelog_path.exists():
844
- with open(changelog_path) as f:
844
+ with changelog_path.open() as f:
845
845
  existing_content = f.read()
846
846
 
847
847
  # Insert new entry after title
@@ -864,7 +864,7 @@ class SemanticVersionManager:
864
864
  content = f"# Changelog\n\n{new_entry}\n"
865
865
 
866
866
  # Write updated changelog
867
- with open(changelog_path, "w") as f:
867
+ with changelog_path.open("w") as f:
868
868
  f.write(content)
869
869
 
870
870
  self.logger.info(f"Updated {changelog_file} with version {version}")
@@ -945,7 +945,7 @@ class SemanticVersionManager:
945
945
  versions = []
946
946
 
947
947
  try:
948
- with open(changelog_path) as f:
948
+ with changelog_path.open() as f:
949
949
  content = f.read()
950
950
 
951
951
  # Find version entries
@@ -365,7 +365,7 @@ class EnhancedVersionParser:
365
365
  package_file = self.project_root / "package.json"
366
366
  if package_file.exists():
367
367
  try:
368
- with open(package_file) as f:
368
+ with package_file.open() as f:
369
369
  data = json.load(f)
370
370
  version = data.get("version")
371
371
  if version and self._version_pattern.match(version):