claude-mpm 4.14.9__py3-none-any.whl → 4.15.0__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (43) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/templates/project_organizer.json +3 -3
  3. claude_mpm/cli/commands/auto_configure.py +7 -9
  4. claude_mpm/cli/commands/local_deploy.py +3 -2
  5. claude_mpm/cli/commands/mpm_init.py +4 -4
  6. claude_mpm/cli/commands/mpm_init_handler.py +8 -3
  7. claude_mpm/core/base_service.py +13 -12
  8. claude_mpm/core/enums.py +36 -1
  9. claude_mpm/services/agents/auto_config_manager.py +9 -10
  10. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
  11. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
  12. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
  13. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
  14. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
  15. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +6 -4
  16. claude_mpm/services/agents/registry/modification_tracker.py +5 -2
  17. claude_mpm/services/command_handler_service.py +11 -5
  18. claude_mpm/services/core/interfaces/process.py +6 -6
  19. claude_mpm/services/core/models/__init__.py +0 -2
  20. claude_mpm/services/core/models/agent_config.py +12 -28
  21. claude_mpm/services/core/models/process.py +19 -42
  22. claude_mpm/services/local_ops/__init__.py +3 -3
  23. claude_mpm/services/local_ops/process_manager.py +12 -12
  24. claude_mpm/services/local_ops/state_manager.py +6 -5
  25. claude_mpm/services/local_ops/unified_manager.py +2 -2
  26. claude_mpm/services/mcp_config_manager.py +7 -2
  27. claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
  28. claude_mpm/services/mcp_gateway/core/base.py +18 -31
  29. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +71 -24
  30. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +23 -22
  31. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +2 -2
  32. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +2 -2
  33. claude_mpm/services/unified/deployment_strategies/local.py +3 -3
  34. claude_mpm/services/unified/deployment_strategies/utils.py +5 -5
  35. claude_mpm/services/unified/deployment_strategies/vercel.py +6 -6
  36. claude_mpm/services/unified/unified_analyzer.py +8 -5
  37. claude_mpm/services/unified/unified_deployment.py +2 -2
  38. {claude_mpm-4.14.9.dist-info → claude_mpm-4.15.0.dist-info}/METADATA +1 -1
  39. {claude_mpm-4.14.9.dist-info → claude_mpm-4.15.0.dist-info}/RECORD +43 -43
  40. {claude_mpm-4.14.9.dist-info → claude_mpm-4.15.0.dist-info}/WHEEL +0 -0
  41. {claude_mpm-4.14.9.dist-info → claude_mpm-4.15.0.dist-info}/entry_points.txt +0 -0
  42. {claude_mpm-4.14.9.dist-info → claude_mpm-4.15.0.dist-info}/licenses/LICENSE +0 -0
  43. {claude_mpm-4.14.9.dist-info → claude_mpm-4.15.0.dist-info}/top_level.txt +0 -0
claude_mpm/VERSION CHANGED
@@ -1 +1 @@
1
- 4.14.9
1
+ 4.15.0
@@ -15,7 +15,7 @@
15
15
  ],
16
16
  "author": "Claude MPM Team",
17
17
  "created_at": "2025-08-15T00:00:00.000000Z",
18
- "updated_at": "2025-10-08T00:00:00.000000Z",
18
+ "updated_at": "2025-10-26T00:00:00.000000Z",
19
19
  "color": "purple"
20
20
  },
21
21
  "capabilities": {
@@ -47,7 +47,7 @@
47
47
  ]
48
48
  }
49
49
  },
50
- "instructions": "# Project Organizer Agent\n\n**Inherits from**: BASE_OPS_AGENT.md\n**Focus**: Intelligent project structure management and organization\n\n## Core Expertise\n\nLearn existing patterns, enforce consistent structure, suggest optimal file placement, and maintain organization documentation.\n\n## Organization Standard Management\n\n**CRITICAL**: Always ensure organization standards are documented and accessible.\n\n### Standard Documentation Protocol\n\n1. **Verify Organization Standard Exists**\n - Check if `docs/reference/PROJECT_ORGANIZATION.md` exists\n - If missing, create it with current organization rules\n - If exists, verify it's up to date with current patterns\n\n2. **Update CLAUDE.md Linking**\n - Verify CLAUDE.md links to PROJECT_ORGANIZATION.md\n - Add link in \"Project Structure Requirements\" section if missing\n - Format: `See [docs/reference/PROJECT_ORGANIZATION.md](docs/reference/PROJECT_ORGANIZATION.md)`\n\n3. **Keep Standard Current**\n - Update standard when new patterns are established\n - Document framework-specific rules as discovered\n - Add version and timestamp to changes\n\n### Organization Standard Location\n- **Primary**: `docs/reference/PROJECT_ORGANIZATION.md`\n- **Reference from**: CLAUDE.md, /mpm-organize command docs\n- **Format**: Markdown with comprehensive rules, examples, and tables\n\n## Pattern Detection Protocol\n\n### 1. Structure Analysis\n- Scan directory hierarchy and patterns\n- Identify naming conventions (camelCase, kebab-case, snake_case)\n- Map file type locations\n- Detect framework-specific conventions\n- Identify organization type (feature/type/domain-based)\n\n### 2. Pattern Categories\n- **By Feature**: `/features/auth/`, `/features/dashboard/`\n- **By Type**: `/controllers/`, `/models/`, `/views/`\n- **By Domain**: `/user/`, `/product/`, `/order/`\n- **Mixed**: Combination approaches\n- **Test Organization**: Colocated vs separate\n\n## File Placement Logic\n\n### Decision Process\n1. Consult PROJECT_ORGANIZATION.md for official rules\n2. Analyze file purpose and type\n3. Apply learned project patterns\n4. Consider framework requirements\n5. Provide clear reasoning\n\n### Framework Handling\n- **Next.js**: Respect pages/app, public, API routes\n- **Django**: Maintain app structure, migrations, templates\n- **Rails**: Follow MVC, assets pipeline, migrations\n- **React**: Component organization, hooks, utils\n\n## Organization Enforcement\n\n### Validation Steps\n1. Check files against PROJECT_ORGANIZATION.md rules\n2. Flag convention violations\n3. Generate safe move operations\n4. Use `git mv` for version control\n5. Update import paths\n6. Update organization standard if needed\n\n### Batch Reorganization\n```bash\n# Analyze violations\nfind . -type f | while read file; do\n expected=$(determine_location \"$file\")\n [ \"$file\" != \"$expected\" ] && echo \"Move: $file -> $expected\"\ndone\n\n# Execute with backup\ntar -czf backup_$(date +%Y%m%d).tar.gz .\n# Run moves with git mv\n```\n\n## Documentation Maintenance\n\n### PROJECT_ORGANIZATION.md Requirements\n- Comprehensive directory structure\n- File placement rules by type and purpose\n- Naming conventions for all file types\n- Framework-specific organization rules\n- Migration procedures\n- Version history\n\n### CLAUDE.md Updates\n- Keep organization quick reference current\n- Link to PROJECT_ORGANIZATION.md prominently\n- Update when major structure changes occur\n\n## Organizer-Specific Todo Patterns\n\n**Analysis**:\n- `[Organizer] Detect project organization patterns`\n- `[Organizer] Identify framework conventions`\n- `[Organizer] Verify organization standard exists`\n\n**Placement**:\n- `[Organizer] Suggest location for API service`\n- `[Organizer] Plan feature module structure`\n\n**Enforcement**:\n- `[Organizer] Validate file organization`\n- `[Organizer] Generate reorganization plan`\n\n**Documentation**:\n- `[Organizer] Update PROJECT_ORGANIZATION.md`\n- `[Organizer] Update CLAUDE.md organization links`\n- `[Organizer] Document naming conventions`\n\n## Safety Measures\n\n- Create backups before reorganization\n- Preserve git history with git mv\n- Update imports after moves\n- Test build after changes\n- Respect .gitignore patterns\n- Document all organization changes\n\n## Success Criteria\n\n- Accurately detect patterns (90%+)\n- Correctly suggest locations\n- Maintain up-to-date documentation (PROJECT_ORGANIZATION.md)\n- Ensure CLAUDE.md links are current\n- Adapt to user corrections\n- Provide clear reasoning",
50
+ "instructions": "# Project Organizer Agent\n\n**Inherits from**: BASE_OPS_AGENT.md\n**Focus**: Intelligent project structure management and organization\n\n## Core Expertise\n\nLearn existing patterns, enforce consistent structure, suggest optimal file placement, and maintain organization documentation.\n\n## Organization Standard Management\n\n**CRITICAL**: Always ensure organization standards are documented and accessible.\n\n### Standard Documentation Protocol\n\n1. **Verify Organization Standard Exists**\n - Check if `docs/reference/PROJECT_ORGANIZATION.md` exists\n - If missing, create it with current organization rules\n - If exists, verify it's up to date with current patterns\n\n2. **Update CLAUDE.md Linking**\n - Verify CLAUDE.md links to PROJECT_ORGANIZATION.md\n - Add link in \"Project Structure Requirements\" section if missing\n - Format: `See [docs/reference/PROJECT_ORGANIZATION.md](docs/reference/PROJECT_ORGANIZATION.md)`\n\n3. **Keep Standard Current**\n - Update standard when new patterns are established\n - Document framework-specific rules as discovered\n - Add version and timestamp to changes\n\n### Organization Standard Location\n- **Primary**: `docs/reference/PROJECT_ORGANIZATION.md`\n- **Reference from**: CLAUDE.md, /mpm-organize command docs\n- **Format**: Markdown with comprehensive rules, examples, and tables\n\n## Project-Specific Organization Standards\n\n**PRIORITY**: Always check for project-specific organization standards before applying defaults.\n\n### Standard Detection and Application Protocol\n\n1. **Check for PROJECT_ORGANIZATION.md** (in order of precedence):\n - First: Project root (`./PROJECT_ORGANIZATION.md`)\n - Second: Documentation directory (`docs/reference/PROJECT_ORGANIZATION.md`)\n - Third: Docs root (`docs/PROJECT_ORGANIZATION.md`)\n\n2. **If PROJECT_ORGANIZATION.md exists**:\n - Read and parse the organizational standards defined within\n - Apply project-specific conventions for:\n * Directory structure and naming patterns\n * File organization principles (feature/type/domain-based)\n * Documentation placement rules\n * Code organization guidelines\n * Framework-specific organizational rules\n * Naming conventions (camelCase, kebab-case, snake_case, etc.)\n * Test organization (colocated vs separate)\n * Any custom organizational policies\n - Use these standards as the PRIMARY guide for all organization decisions\n - Project-specific standards ALWAYS take precedence over default patterns\n - When making organization decisions, explicitly reference which rule from PROJECT_ORGANIZATION.md is being applied\n\n3. **If PROJECT_ORGANIZATION.md does not exist**:\n - Fall back to pattern detection and framework defaults (see below)\n - Suggest creating PROJECT_ORGANIZATION.md to document discovered patterns\n - Use detected patterns for current organization decisions\n\n## Pattern Detection Protocol\n\n### 1. Structure Analysis\n- Scan directory hierarchy and patterns\n- Identify naming conventions (camelCase, kebab-case, snake_case)\n- Map file type locations\n- Detect framework-specific conventions\n- Identify organization type (feature/type/domain-based)\n\n### 2. Pattern Categories\n- **By Feature**: `/features/auth/`, `/features/dashboard/`\n- **By Type**: `/controllers/`, `/models/`, `/views/`\n- **By Domain**: `/user/`, `/product/`, `/order/`\n- **Mixed**: Combination approaches\n- **Test Organization**: Colocated vs separate\n\n## File Placement Logic\n\n### Decision Process\n1. Consult PROJECT_ORGANIZATION.md for official rules\n2. Analyze file purpose and type\n3. Apply learned project patterns\n4. Consider framework requirements\n5. Provide clear reasoning\n\n### Framework Handling\n- **Next.js**: Respect pages/app, public, API routes\n- **Django**: Maintain app structure, migrations, templates\n- **Rails**: Follow MVC, assets pipeline, migrations\n- **React**: Component organization, hooks, utils\n\n## Organization Enforcement\n\n### Validation Steps\n1. Check files against PROJECT_ORGANIZATION.md rules\n2. Flag convention violations\n3. Generate safe move operations\n4. Use `git mv` for version control\n5. Update import paths\n6. Update organization standard if needed\n\n### Batch Reorganization\n```bash\n# Analyze violations\nfind . -type f | while read file; do\n expected=$(determine_location \"$file\")\n [ \"$file\" != \"$expected\" ] && echo \"Move: $file -> $expected\"\ndone\n\n# Execute with backup\ntar -czf backup_$(date +%Y%m%d).tar.gz .\n# Run moves with git mv\n```\n\n## Documentation Maintenance\n\n### PROJECT_ORGANIZATION.md Requirements\n- Comprehensive directory structure\n- File placement rules by type and purpose\n- Naming conventions for all file types\n- Framework-specific organization rules\n- Migration procedures\n- Version history\n\n### CLAUDE.md Updates\n- Keep organization quick reference current\n- Link to PROJECT_ORGANIZATION.md prominently\n- Update when major structure changes occur\n\n## Organizer-Specific Todo Patterns\n\n**Analysis**:\n- `[Organizer] Detect project organization patterns`\n- `[Organizer] Identify framework conventions`\n- `[Organizer] Verify organization standard exists`\n\n**Placement**:\n- `[Organizer] Suggest location for API service`\n- `[Organizer] Plan feature module structure`\n\n**Enforcement**:\n- `[Organizer] Validate file organization`\n- `[Organizer] Generate reorganization plan`\n\n**Documentation**:\n- `[Organizer] Update PROJECT_ORGANIZATION.md`\n- `[Organizer] Update CLAUDE.md organization links`\n- `[Organizer] Document naming conventions`\n\n## Safety Measures\n\n- Create backups before reorganization\n- Preserve git history with git mv\n- Update imports after moves\n- Test build after changes\n- Respect .gitignore patterns\n- Document all organization changes\n\n## Success Criteria\n\n- Accurately detect patterns (90%+)\n- Correctly suggest locations\n- Maintain up-to-date documentation (PROJECT_ORGANIZATION.md)\n- Ensure CLAUDE.md links are current\n- Adapt to user corrections\n- Provide clear reasoning",
51
51
  "knowledge": {
52
52
  "domain_expertise": [
53
53
  "Project structure patterns",
@@ -130,4 +130,4 @@
130
130
  "success_rate": 0.9
131
131
  }
132
132
  }
133
- }
133
+ }
@@ -26,12 +26,10 @@ try:
26
26
  except ImportError:
27
27
  RICH_AVAILABLE = False
28
28
 
29
+ from ...core.enums import OperationResult
29
30
  from ...services.agents.auto_config_manager import AutoConfigManagerService
30
31
  from ...services.agents.observers import NullObserver
31
- from ...services.core.models.agent_config import (
32
- ConfigurationResult,
33
- ConfigurationStatus,
34
- )
32
+ from ...services.core.models.agent_config import ConfigurationResult
35
33
  from ..shared import BaseCommand, CommandResult
36
34
 
37
35
 
@@ -419,7 +417,7 @@ class AutoConfigureCommand(BaseCommand):
419
417
  return self._display_result_plain(result)
420
418
 
421
419
  # Display summary
422
- if result.status == ConfigurationStatus.SUCCESS:
420
+ if result.status == OperationResult.SUCCESS:
423
421
  panel = Panel(
424
422
  f"✅ Auto-configuration completed successfully!\n\n"
425
423
  f"Deployed {len(result.deployed_agents)} agent(s)",
@@ -436,7 +434,7 @@ class AutoConfigureCommand(BaseCommand):
436
434
 
437
435
  return CommandResult.success_result()
438
436
 
439
- if result.status == ConfigurationStatus.PARTIAL_SUCCESS:
437
+ if result.status == OperationResult.WARNING:
440
438
  panel = Panel(
441
439
  f"⚠️ Auto-configuration partially completed\n\n"
442
440
  f"Deployed: {len(result.deployed_agents)}\n"
@@ -465,7 +463,7 @@ class AutoConfigureCommand(BaseCommand):
465
463
 
466
464
  def _display_result_plain(self, result: ConfigurationResult) -> CommandResult:
467
465
  """Display result in plain text (fallback)."""
468
- if result.status == ConfigurationStatus.SUCCESS:
466
+ if result.status == OperationResult.SUCCESS:
469
467
  print("\n✅ Auto-configuration completed successfully!")
470
468
  print(f"Deployed {len(result.deployed_agents)} agent(s)")
471
469
 
@@ -476,7 +474,7 @@ class AutoConfigureCommand(BaseCommand):
476
474
 
477
475
  return CommandResult.success_result()
478
476
 
479
- if result.status == ConfigurationStatus.PARTIAL_SUCCESS:
477
+ if result.status == OperationResult.WARNING:
480
478
  print("\n⚠️ Auto-configuration partially completed")
481
479
  print(f"Deployed: {len(result.deployed_agents)}")
482
480
  print(f"Failed: {len(result.failed_agents)}")
@@ -565,7 +563,7 @@ class AutoConfigureCommand(BaseCommand):
565
563
 
566
564
  print(json.dumps(output, indent=2))
567
565
 
568
- if result.status == ConfigurationStatus.SUCCESS:
566
+ if result.status == OperationResult.SUCCESS:
569
567
  return CommandResult.success_result(data=output)
570
568
  return CommandResult.error_result(
571
569
  "Configuration failed or partial", exit_code=1, data=output
@@ -23,8 +23,9 @@ from rich.panel import Panel
23
23
  from rich.table import Table
24
24
  from rich.text import Text
25
25
 
26
+ from claude_mpm.core.enums import ServiceState
27
+
26
28
  from ...services.local_ops import (
27
- ProcessStatus,
28
29
  StartConfig,
29
30
  UnifiedLocalOpsManager,
30
31
  )
@@ -298,7 +299,7 @@ class LocalDeployCommand(BaseCommand):
298
299
  try:
299
300
  status_filter_str = getattr(args, "status", None)
300
301
  status_filter = (
301
- ProcessStatus(status_filter_str) if status_filter_str else None
302
+ ServiceState(status_filter_str) if status_filter_str else None
302
303
  )
303
304
 
304
305
  deployments = self.manager.list_deployments(status_filter=status_filter)
@@ -157,7 +157,7 @@ class MPMInitCommand:
157
157
  pre_check_result = self._run_pre_initialization_checks(
158
158
  organize_files, skip_archive, has_existing
159
159
  )
160
- if pre_check_result.get("status") == "error":
160
+ if pre_check_result.get("status") == OperationResult.ERROR:
161
161
  return pre_check_result
162
162
 
163
163
  # Build the delegation prompt
@@ -200,7 +200,7 @@ class MPMInitCommand:
200
200
  progress.update(task, description=complete_desc)
201
201
 
202
202
  # Post-processing for update mode
203
- if update_mode and result.get("status") == "success":
203
+ if update_mode and result.get("status") == OperationResult.SUCCESS:
204
204
  self._handle_update_post_processing()
205
205
 
206
206
  return result
@@ -1685,7 +1685,7 @@ Keep it concise (<1000 words) but actionable.
1685
1685
 
1686
1686
  def _display_results(self, result: Dict, verbose: bool):
1687
1687
  """Display initialization results."""
1688
- if result["status"] == "success":
1688
+ if result["status"] == OperationResult.SUCCESS:
1689
1689
  console.print("\n[green]✅ Project Initialization Complete![/green]\n")
1690
1690
 
1691
1691
  # Display files created
@@ -1885,7 +1885,7 @@ def mpm_init(
1885
1885
  )
1886
1886
 
1887
1887
  # Exit with appropriate code
1888
- if result["status"] == "success":
1888
+ if result["status"] == OperationResult.SUCCESS:
1889
1889
  sys.exit(0)
1890
1890
  else:
1891
1891
  sys.exit(1)
@@ -8,6 +8,8 @@ from pathlib import Path
8
8
 
9
9
  from rich.console import Console
10
10
 
11
+ from claude_mpm.core.enums import OperationResult
12
+
11
13
  console = Console()
12
14
 
13
15
 
@@ -51,7 +53,10 @@ def manage_mpm_init(args):
51
53
  )
52
54
 
53
55
  # Return appropriate exit code
54
- if result.get("status") in ("success", "context_ready"):
56
+ if result.get("status") in (
57
+ OperationResult.SUCCESS,
58
+ OperationResult.CONTEXT_READY,
59
+ ):
55
60
  return 0
56
61
  return 1
57
62
 
@@ -102,9 +107,9 @@ def manage_mpm_init(args):
102
107
  result = command.initialize_project(**init_params)
103
108
 
104
109
  # Return appropriate exit code
105
- if result.get("status") == "success":
110
+ if result.get("status") == OperationResult.SUCCESS:
106
111
  return 0
107
- if result.get("status") == "cancelled":
112
+ if result.get("status") == OperationResult.CANCELLED:
108
113
  return 130 # User cancelled
109
114
  return 1 # Error
110
115
 
@@ -31,6 +31,7 @@ from pathlib import Path
31
31
  from typing import Any, Dict, List, Optional
32
32
 
33
33
  from .config import Config
34
+ from .enums import HealthStatus
34
35
  from .mixins import LoggerMixin
35
36
 
36
37
 
@@ -38,7 +39,7 @@ from .mixins import LoggerMixin
38
39
  class ServiceHealth:
39
40
  """Service health status information."""
40
41
 
41
- status: str # healthy, degraded, unhealthy, unknown
42
+ status: HealthStatus # Type-safe health status using enum
42
43
  message: str
43
44
  timestamp: str
44
45
  metrics: Dict[str, Any] = field(default_factory=dict)
@@ -142,7 +143,7 @@ class BaseService(LoggerMixin, ABC):
142
143
 
143
144
  # Health and metrics
144
145
  self._health = ServiceHealth(
145
- status="unknown",
146
+ status=HealthStatus.UNKNOWN,
146
147
  message="Service not started",
147
148
  timestamp=datetime.now(timezone.utc).isoformat(),
148
149
  )
@@ -235,7 +236,7 @@ class BaseService(LoggerMixin, ABC):
235
236
  except Exception as e:
236
237
  self.logger.error(f"Failed to start service {self.name}: {e}")
237
238
  self._health = ServiceHealth(
238
- status="unhealthy",
239
+ status=HealthStatus.UNHEALTHY,
239
240
  message=f"Startup failed: {e!s}",
240
241
  timestamp=datetime.now(timezone.utc).isoformat(),
241
242
  checks={"startup": False},
@@ -272,7 +273,7 @@ class BaseService(LoggerMixin, ABC):
272
273
 
273
274
  # Update health status
274
275
  self._health = ServiceHealth(
275
- status="healthy",
276
+ status=HealthStatus.HEALTHY,
276
277
  message="Service started successfully",
277
278
  timestamp=datetime.now(timezone.utc).isoformat(),
278
279
  checks={"startup": True},
@@ -336,7 +337,7 @@ class BaseService(LoggerMixin, ABC):
336
337
 
337
338
  # Update health status
338
339
  self._health = ServiceHealth(
339
- status="unknown",
340
+ status=HealthStatus.UNKNOWN,
340
341
  message="Service stopped",
341
342
  timestamp=datetime.now(timezone.utc).isoformat(),
342
343
  checks={"running": False},
@@ -372,16 +373,16 @@ class BaseService(LoggerMixin, ABC):
372
373
 
373
374
  # Determine overall status
374
375
  if not checks["running"]:
375
- status = "unhealthy"
376
+ status = HealthStatus.UNHEALTHY
376
377
  message = "Service is not running"
377
378
  elif all(checks.values()):
378
- status = "healthy"
379
+ status = HealthStatus.HEALTHY
379
380
  message = "All health checks passed"
380
381
  elif any(checks.values()):
381
- status = "degraded"
382
+ status = HealthStatus.DEGRADED
382
383
  message = "Some health checks failed"
383
384
  else:
384
- status = "unhealthy"
385
+ status = HealthStatus.UNHEALTHY
385
386
  message = "Multiple health checks failed"
386
387
 
387
388
  # Update health status
@@ -402,7 +403,7 @@ class BaseService(LoggerMixin, ABC):
402
403
  except Exception as e:
403
404
  self.logger.error(f"Health check failed for {self.name}: {e}")
404
405
  self._health = ServiceHealth(
405
- status="unhealthy",
406
+ status=HealthStatus.UNHEALTHY,
406
407
  message=f"Health check error: {e!s}",
407
408
  timestamp=datetime.now(timezone.utc).isoformat(),
408
409
  checks={"health_check_error": True},
@@ -593,7 +594,7 @@ class BaseService(LoggerMixin, ABC):
593
594
  )
594
595
  else:
595
596
  return ServiceHealth(
596
- status="degraded",
597
+ status=HealthStatus.DEGRADED,
597
598
  message="Service circuit breaker is open",
598
599
  timestamp=datetime.now(timezone.utc).isoformat(),
599
600
  checks={"circuit_breaker": False},
@@ -604,7 +605,7 @@ class BaseService(LoggerMixin, ABC):
604
605
  health = await self.health_check()
605
606
 
606
607
  # Update circuit breaker
607
- if health.status in ["healthy", "degraded"]:
608
+ if health.status in (HealthStatus.HEALTHY, HealthStatus.DEGRADED):
608
609
  self._record_circuit_success()
609
610
  else:
610
611
  self._record_circuit_failure()
claude_mpm/core/enums.py CHANGED
@@ -70,6 +70,9 @@ class OperationResult(StrEnum):
70
70
  PARTIAL = "partial"
71
71
  """Operation completed partially."""
72
72
 
73
+ WARNING = "warning"
74
+ """Operation completed with warnings (partial success with issues)."""
75
+
73
76
  ROLLBACK = "rollback"
74
77
  """Operation rolled back due to failure or cancellation."""
75
78
 
@@ -121,12 +124,26 @@ class ServiceState(StrEnum):
121
124
  Service lifecycle states for all Claude MPM services.
122
125
 
123
126
  Replaces 150+ occurrences of service state strings.
124
- Used in: Hook services, MCP servers, monitoring, health checks.
127
+ Used in: Hook services, MCP servers, monitoring, health checks, process management.
125
128
 
126
129
  Migration Priority: HIGH (Week 1)
127
130
  Coverage: ~7% of all magic strings
131
+
132
+ Notes:
133
+ - Consolidated with ProcessStatus enum (Phase 3A Batch 24)
134
+ - Process states are semantically equivalent to service states
135
+ - CRASHED processes map to ERROR state
128
136
  """
129
137
 
138
+ UNINITIALIZED = "uninitialized"
139
+ """Service has not been initialized yet."""
140
+
141
+ INITIALIZING = "initializing"
142
+ """Service is in the process of initializing."""
143
+
144
+ INITIALIZED = "initialized"
145
+ """Service has been initialized but not started."""
146
+
130
147
  STOPPED = "stopped"
131
148
  """Service is completely stopped."""
132
149
 
@@ -154,6 +171,24 @@ class ServiceState(StrEnum):
154
171
  IDLE = "idle"
155
172
  """Service is running but not actively processing."""
156
173
 
174
+ def is_active(self) -> bool:
175
+ """
176
+ Check if state represents an active service/process.
177
+
178
+ Returns:
179
+ True if state is STARTING or RUNNING
180
+ """
181
+ return self in (ServiceState.STARTING, ServiceState.RUNNING)
182
+
183
+ def is_terminal(self) -> bool:
184
+ """
185
+ Check if state represents a terminal/stopped state.
186
+
187
+ Returns:
188
+ True if state is STOPPED or ERROR
189
+ """
190
+ return self in (ServiceState.STOPPED, ServiceState.ERROR)
191
+
157
192
 
158
193
  class ValidationSeverity(StrEnum):
159
194
  """
@@ -23,15 +23,14 @@ from typing import Any, Dict, List, Optional
23
23
  import yaml
24
24
 
25
25
  from ...core.base_service import BaseService
26
+ from ...core.enums import OperationResult, ValidationSeverity
26
27
  from ..core.interfaces.agent import IAgentRegistry, IAutoConfigManager
27
28
  from ..core.models.agent_config import (
28
29
  AgentRecommendation,
29
30
  ConfigurationPreview,
30
31
  ConfigurationResult,
31
- ConfigurationStatus,
32
32
  ValidationIssue,
33
33
  ValidationResult,
34
- ValidationSeverity,
35
34
  )
36
35
  from ..core.models.toolchain import ToolchainAnalysis
37
36
  from .observers import IDeploymentObserver, NullObserver
@@ -216,7 +215,7 @@ class AutoConfigManagerService(BaseService, IAutoConfigManager):
216
215
 
217
216
  if not recommendations:
218
217
  return ConfigurationResult(
219
- status=ConfigurationStatus.SUCCESS,
218
+ status=OperationResult.SUCCESS,
220
219
  message="No agents recommended for this project configuration",
221
220
  recommendations=recommendations,
222
221
  metadata={
@@ -241,7 +240,7 @@ class AutoConfigManagerService(BaseService, IAutoConfigManager):
241
240
  f"Validation failed with {validation_result.error_count} errors"
242
241
  )
243
242
  return ConfigurationResult(
244
- status=ConfigurationStatus.VALIDATION_ERROR,
243
+ status=OperationResult.ERROR,
245
244
  validation_errors=[
246
245
  issue.message for issue in validation_result.errors
247
246
  ],
@@ -260,7 +259,7 @@ class AutoConfigManagerService(BaseService, IAutoConfigManager):
260
259
  if dry_run:
261
260
  self.logger.info("Dry-run mode: skipping deployment")
262
261
  return ConfigurationResult(
263
- status=ConfigurationStatus.SUCCESS,
262
+ status=OperationResult.SUCCESS,
264
263
  validation_warnings=[
265
264
  issue.message for issue in validation_result.warnings
266
265
  ],
@@ -280,7 +279,7 @@ class AutoConfigManagerService(BaseService, IAutoConfigManager):
280
279
  if not confirmed:
281
280
  self.logger.info("User cancelled auto-configuration")
282
281
  return ConfigurationResult(
283
- status=ConfigurationStatus.USER_CANCELLED,
282
+ status=OperationResult.CANCELLED,
284
283
  recommendations=recommendations,
285
284
  message="Auto-configuration cancelled by user",
286
285
  metadata={
@@ -318,9 +317,9 @@ class AutoConfigManagerService(BaseService, IAutoConfigManager):
318
317
 
319
318
  return ConfigurationResult(
320
319
  status=(
321
- ConfigurationStatus.PARTIAL_SUCCESS
320
+ OperationResult.WARNING
322
321
  if deployed_agents
323
- else ConfigurationStatus.FAILURE
322
+ else OperationResult.FAILED
324
323
  ),
325
324
  deployed_agents=deployed_agents,
326
325
  failed_agents=failed_agents,
@@ -347,7 +346,7 @@ class AutoConfigManagerService(BaseService, IAutoConfigManager):
347
346
  )
348
347
 
349
348
  return ConfigurationResult(
350
- status=ConfigurationStatus.SUCCESS,
349
+ status=OperationResult.SUCCESS,
351
350
  deployed_agents=deployed_agents,
352
351
  validation_warnings=[
353
352
  issue.message for issue in validation_result.warnings
@@ -365,7 +364,7 @@ class AutoConfigManagerService(BaseService, IAutoConfigManager):
365
364
  observer.on_error("auto-configuration", str(e), e)
366
365
 
367
366
  return ConfigurationResult(
368
- status=ConfigurationStatus.FAILURE,
367
+ status=OperationResult.FAILED,
369
368
  message=f"Auto-configuration failed: {e}",
370
369
  metadata={
371
370
  "duration_ms": (time.time() - start_time) * 1000,
@@ -3,13 +3,14 @@
3
3
  import time
4
4
  from pathlib import Path
5
5
 
6
+ from claude_mpm.core.enums import OperationResult
6
7
  from claude_mpm.services.agents.deployment.processors import (
7
8
  AgentDeploymentContext,
8
9
  AgentDeploymentResult,
9
10
  AgentProcessor,
10
11
  )
11
12
 
12
- from .base_step import BaseDeploymentStep, StepResult, StepStatus
13
+ from .base_step import BaseDeploymentStep, StepResult
13
14
 
14
15
 
15
16
  class AgentProcessingStep(BaseDeploymentStep):
@@ -37,7 +38,7 @@ class AgentProcessingStep(BaseDeploymentStep):
37
38
  if not context.template_files:
38
39
  self.logger.warning("No template files to process")
39
40
  return StepResult(
40
- status=StepStatus.SKIPPED,
41
+ status=OperationResult.SKIPPED,
41
42
  message="No template files found to process",
42
43
  execution_time=time.time() - start_time,
43
44
  )
@@ -103,13 +104,13 @@ class AgentProcessingStep(BaseDeploymentStep):
103
104
 
104
105
  # Determine step status
105
106
  if failed_count == 0:
106
- status = StepStatus.SUCCESS
107
+ status = OperationResult.SUCCESS
107
108
  message = f"Successfully processed {processed_count} agents in {execution_time:.3f}s"
108
109
  elif processed_count > 0:
109
- status = StepStatus.WARNING
110
+ status = OperationResult.WARNING
110
111
  message = f"Processed {processed_count} agents with {failed_count} failures in {execution_time:.3f}s"
111
112
  else:
112
- status = StepStatus.FAILURE
113
+ status = OperationResult.FAILED
113
114
  message = f"Failed to process any agents ({failed_count} failures) in {execution_time:.3f}s"
114
115
 
115
116
  self.logger.info(message)
@@ -127,7 +128,7 @@ class AgentProcessingStep(BaseDeploymentStep):
127
128
  context.add_error(error_msg)
128
129
 
129
130
  return StepResult(
130
- status=StepStatus.FAILURE,
131
+ status=OperationResult.FAILED,
131
132
  message=error_msg,
132
133
  error=e,
133
134
  execution_time=execution_time,
@@ -2,26 +2,17 @@
2
2
 
3
3
  from abc import ABC, abstractmethod
4
4
  from dataclasses import dataclass
5
- from enum import Enum
6
5
  from typing import Optional
7
6
 
7
+ from claude_mpm.core.enums import OperationResult
8
8
  from claude_mpm.core.logger import get_logger
9
9
 
10
10
 
11
- class StepStatus(Enum):
12
- """Status of a pipeline step execution."""
13
-
14
- SUCCESS = "success"
15
- FAILURE = "failure"
16
- SKIPPED = "skipped"
17
- WARNING = "warning"
18
-
19
-
20
11
  @dataclass
21
12
  class StepResult:
22
13
  """Result of executing a pipeline step."""
23
14
 
24
- status: StepStatus
15
+ status: OperationResult
25
16
  message: Optional[str] = None
26
17
  error: Optional[Exception] = None
27
18
  execution_time: Optional[float] = None
@@ -29,22 +20,22 @@ class StepResult:
29
20
  @property
30
21
  def is_success(self) -> bool:
31
22
  """Check if the step was successful."""
32
- return self.status == StepStatus.SUCCESS
23
+ return self.status == OperationResult.SUCCESS
33
24
 
34
25
  @property
35
26
  def is_failure(self) -> bool:
36
27
  """Check if the step failed."""
37
- return self.status == StepStatus.FAILURE
28
+ return self.status == OperationResult.FAILED
38
29
 
39
30
  @property
40
31
  def is_skipped(self) -> bool:
41
32
  """Check if the step was skipped."""
42
- return self.status == StepStatus.SKIPPED
33
+ return self.status == OperationResult.SKIPPED
43
34
 
44
35
  @property
45
36
  def is_warning(self) -> bool:
46
37
  """Check if the step completed with warnings."""
47
- return self.status == StepStatus.WARNING
38
+ return self.status == OperationResult.WARNING
48
39
 
49
40
 
50
41
  class BaseDeploymentStep(ABC):
@@ -67,7 +58,7 @@ class BaseDeploymentStep(ABC):
67
58
  self.logger = get_logger(f"{__name__}.{self.__class__.__name__}")
68
59
 
69
60
  @abstractmethod
70
- def execute(self, context) -> StepResult:
61
+ def execute(self, context) -> "StepResult":
71
62
  """Execute this deployment step.
72
63
 
73
64
  Args:
@@ -3,8 +3,9 @@
3
3
  import time
4
4
 
5
5
  from claude_mpm.core.config import Config
6
+ from claude_mpm.core.enums import OperationResult
6
7
 
7
- from .base_step import BaseDeploymentStep, StepResult, StepStatus
8
+ from .base_step import BaseDeploymentStep, StepResult
8
9
 
9
10
 
10
11
  class ConfigurationLoadStep(BaseDeploymentStep):
@@ -54,7 +55,7 @@ class ConfigurationLoadStep(BaseDeploymentStep):
54
55
  context.step_timings[self.name] = execution_time
55
56
 
56
57
  return StepResult(
57
- status=StepStatus.SUCCESS,
58
+ status=OperationResult.SUCCESS,
58
59
  message=f"Configuration loaded successfully in {execution_time:.3f}s",
59
60
  execution_time=execution_time,
60
61
  )
@@ -68,7 +69,7 @@ class ConfigurationLoadStep(BaseDeploymentStep):
68
69
  context.add_error(error_msg)
69
70
 
70
71
  return StepResult(
71
- status=StepStatus.FAILURE,
72
+ status=OperationResult.FAILED,
72
73
  message=error_msg,
73
74
  error=e,
74
75
  execution_time=execution_time,
@@ -3,7 +3,9 @@
3
3
  import time
4
4
  from pathlib import Path
5
5
 
6
- from .base_step import BaseDeploymentStep, StepResult, StepStatus
6
+ from claude_mpm.core.enums import OperationResult
7
+
8
+ from .base_step import BaseDeploymentStep, StepResult
7
9
 
8
10
 
9
11
  class TargetDirectorySetupStep(BaseDeploymentStep):
@@ -59,7 +61,7 @@ class TargetDirectorySetupStep(BaseDeploymentStep):
59
61
  context.step_timings[self.name] = execution_time
60
62
 
61
63
  return StepResult(
62
- status=StepStatus.SUCCESS,
64
+ status=OperationResult.SUCCESS,
63
65
  message=f"Target directory set up at {context.actual_target_dir} in {execution_time:.3f}s",
64
66
  execution_time=execution_time,
65
67
  )
@@ -73,7 +75,7 @@ class TargetDirectorySetupStep(BaseDeploymentStep):
73
75
  context.add_error(error_msg)
74
76
 
75
77
  return StepResult(
76
- status=StepStatus.FAILURE,
78
+ status=OperationResult.FAILED,
77
79
  message=error_msg,
78
80
  error=e,
79
81
  execution_time=execution_time,
@@ -2,9 +2,10 @@
2
2
 
3
3
  import time
4
4
 
5
+ from claude_mpm.core.enums import OperationResult
5
6
  from claude_mpm.services.agents.deployment.validation import DeploymentValidator
6
7
 
7
- from .base_step import BaseDeploymentStep, StepResult, StepStatus
8
+ from .base_step import BaseDeploymentStep, StepResult
8
9
 
9
10
 
10
11
  class ValidationStep(BaseDeploymentStep):
@@ -49,13 +50,13 @@ class ValidationStep(BaseDeploymentStep):
49
50
 
50
51
  # Determine step status
51
52
  if not validation_result.is_valid:
52
- status = StepStatus.FAILURE
53
+ status = OperationResult.FAILED
53
54
  message = f"Validation failed with {validation_result.error_count} errors in {execution_time:.3f}s"
54
55
  elif validation_result.has_warnings:
55
- status = StepStatus.WARNING
56
+ status = OperationResult.WARNING
56
57
  message = f"Validation completed with {validation_result.warning_count} warnings in {execution_time:.3f}s"
57
58
  else:
58
- status = StepStatus.SUCCESS
59
+ status = OperationResult.SUCCESS
59
60
  message = f"Validation passed successfully in {execution_time:.3f}s"
60
61
 
61
62
  self.logger.info(message)
@@ -73,7 +74,7 @@ class ValidationStep(BaseDeploymentStep):
73
74
  context.add_error(error_msg)
74
75
 
75
76
  return StepResult(
76
- status=StepStatus.FAILURE,
77
+ status=OperationResult.FAILED,
77
78
  message=error_msg,
78
79
  error=e,
79
80
  execution_time=execution_time,