claude-mpm 4.14.8__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/agent_loader.py +13 -1
- claude_mpm/agents/templates/project_organizer.json +3 -3
- claude_mpm/cli/commands/auto_configure.py +7 -9
- claude_mpm/cli/commands/local_deploy.py +3 -2
- claude_mpm/cli/commands/mpm_init.py +4 -4
- claude_mpm/cli/commands/mpm_init_handler.py +8 -3
- claude_mpm/core/base_service.py +13 -12
- claude_mpm/core/enums.py +124 -12
- claude_mpm/services/agents/auto_config_manager.py +9 -10
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +6 -4
- claude_mpm/services/agents/registry/modification_tracker.py +5 -2
- claude_mpm/services/command_handler_service.py +11 -5
- claude_mpm/services/core/interfaces/process.py +6 -6
- claude_mpm/services/core/models/__init__.py +0 -2
- claude_mpm/services/core/models/agent_config.py +12 -28
- claude_mpm/services/core/models/process.py +19 -42
- claude_mpm/services/local_ops/__init__.py +3 -3
- claude_mpm/services/local_ops/process_manager.py +12 -12
- claude_mpm/services/local_ops/state_manager.py +6 -5
- claude_mpm/services/local_ops/unified_manager.py +2 -2
- claude_mpm/services/mcp_config_manager.py +7 -2
- claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
- claude_mpm/services/mcp_gateway/core/base.py +18 -31
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +71 -24
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +23 -22
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +2 -2
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +1 -1
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +3 -3
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +3 -3
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +1 -1
- claude_mpm/services/unified/deployment_strategies/local.py +3 -3
- claude_mpm/services/unified/deployment_strategies/utils.py +5 -5
- claude_mpm/services/unified/deployment_strategies/vercel.py +6 -6
- claude_mpm/services/unified/unified_analyzer.py +8 -5
- claude_mpm/services/unified/unified_deployment.py +2 -2
- {claude_mpm-4.14.8.dist-info → claude_mpm-4.15.0.dist-info}/METADATA +1 -1
- {claude_mpm-4.14.8.dist-info → claude_mpm-4.15.0.dist-info}/RECORD +47 -47
- {claude_mpm-4.14.8.dist-info → claude_mpm-4.15.0.dist-info}/WHEEL +0 -0
- {claude_mpm-4.14.8.dist-info → claude_mpm-4.15.0.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.14.8.dist-info → claude_mpm-4.15.0.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.14.8.dist-info → claude_mpm-4.15.0.dist-info}/top_level.txt +0 -0
claude_mpm/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
4.
|
|
1
|
+
4.15.0
|
|
@@ -38,6 +38,8 @@ from enum import Enum
|
|
|
38
38
|
from pathlib import Path
|
|
39
39
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
40
40
|
|
|
41
|
+
from claude_mpm.core.enums import AgentCategory
|
|
42
|
+
|
|
41
43
|
# Module-level logger
|
|
42
44
|
from claude_mpm.core.logging_utils import get_logger
|
|
43
45
|
|
|
@@ -281,11 +283,21 @@ class AgentLoader:
|
|
|
281
283
|
# Check for project memory
|
|
282
284
|
has_memory = capabilities.get("has_project_memory", False)
|
|
283
285
|
|
|
286
|
+
# Get category with enum validation (fallback to GENERAL if invalid)
|
|
287
|
+
category_str = metadata.get("category", "general")
|
|
288
|
+
try:
|
|
289
|
+
category = AgentCategory(category_str)
|
|
290
|
+
except ValueError:
|
|
291
|
+
logger.warning(
|
|
292
|
+
f"Invalid category '{category_str}' for agent {agent_id}, using GENERAL"
|
|
293
|
+
)
|
|
294
|
+
category = AgentCategory.GENERAL
|
|
295
|
+
|
|
284
296
|
result = {
|
|
285
297
|
"agent_id": agent_id,
|
|
286
298
|
"name": metadata.get("name", agent_id),
|
|
287
299
|
"description": metadata.get("description", ""),
|
|
288
|
-
"category":
|
|
300
|
+
"category": category.value, # Store as string for backward compatibility
|
|
289
301
|
"version": metadata.get("version", "1.0.0"),
|
|
290
302
|
"model": agent_data.get("model", "claude-sonnet-4-20250514"),
|
|
291
303
|
"resource_tier": agent_data.get("resource_tier", "standard"),
|
|
@@ -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-
|
|
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 ==
|
|
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 ==
|
|
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 ==
|
|
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 ==
|
|
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 ==
|
|
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
|
-
|
|
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") ==
|
|
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") ==
|
|
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"] ==
|
|
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"] ==
|
|
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 (
|
|
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") ==
|
|
110
|
+
if result.get("status") == OperationResult.SUCCESS:
|
|
106
111
|
return 0
|
|
107
|
-
if result.get("status") ==
|
|
112
|
+
if result.get("status") == OperationResult.CANCELLED:
|
|
108
113
|
return 130 # User cancelled
|
|
109
114
|
return 1 # Error
|
|
110
115
|
|
claude_mpm/core/base_service.py
CHANGED
|
@@ -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:
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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 =
|
|
376
|
+
status = HealthStatus.UNHEALTHY
|
|
376
377
|
message = "Service is not running"
|
|
377
378
|
elif all(checks.values()):
|
|
378
|
-
status =
|
|
379
|
+
status = HealthStatus.HEALTHY
|
|
379
380
|
message = "All health checks passed"
|
|
380
381
|
elif any(checks.values()):
|
|
381
|
-
status =
|
|
382
|
+
status = HealthStatus.DEGRADED
|
|
382
383
|
message = "Some health checks failed"
|
|
383
384
|
else:
|
|
384
|
-
status =
|
|
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=
|
|
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=
|
|
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
|
|
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,12 @@ 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
|
+
|
|
76
|
+
ROLLBACK = "rollback"
|
|
77
|
+
"""Operation rolled back due to failure or cancellation."""
|
|
78
|
+
|
|
73
79
|
UNKNOWN = "unknown"
|
|
74
80
|
"""Operation result is unknown or indeterminate."""
|
|
75
81
|
|
|
@@ -118,12 +124,26 @@ class ServiceState(StrEnum):
|
|
|
118
124
|
Service lifecycle states for all Claude MPM services.
|
|
119
125
|
|
|
120
126
|
Replaces 150+ occurrences of service state strings.
|
|
121
|
-
Used in: Hook services, MCP servers, monitoring, health checks.
|
|
127
|
+
Used in: Hook services, MCP servers, monitoring, health checks, process management.
|
|
122
128
|
|
|
123
129
|
Migration Priority: HIGH (Week 1)
|
|
124
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
|
|
125
136
|
"""
|
|
126
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
|
+
|
|
127
147
|
STOPPED = "stopped"
|
|
128
148
|
"""Service is completely stopped."""
|
|
129
149
|
|
|
@@ -151,6 +171,24 @@ class ServiceState(StrEnum):
|
|
|
151
171
|
IDLE = "idle"
|
|
152
172
|
"""Service is running but not actively processing."""
|
|
153
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
|
+
|
|
154
192
|
|
|
155
193
|
class ValidationSeverity(StrEnum):
|
|
156
194
|
"""
|
|
@@ -179,6 +217,41 @@ class ValidationSeverity(StrEnum):
|
|
|
179
217
|
"""Debug-level information for troubleshooting."""
|
|
180
218
|
|
|
181
219
|
|
|
220
|
+
class HealthStatus(StrEnum):
|
|
221
|
+
"""
|
|
222
|
+
Health check status codes for services and components.
|
|
223
|
+
|
|
224
|
+
Replaces health check status strings throughout monitoring and diagnostics.
|
|
225
|
+
Used in: Health checks, monitoring, service diagnostics, uptime tracking.
|
|
226
|
+
|
|
227
|
+
Migration Priority: MEDIUM (Week 3)
|
|
228
|
+
Coverage: ~2% of all magic strings
|
|
229
|
+
|
|
230
|
+
Notes:
|
|
231
|
+
- Added in Phase 3C for comprehensive service health monitoring
|
|
232
|
+
- Distinct from ServiceState (operational) and OperationResult (transactional)
|
|
233
|
+
- Maps to standard health check patterns (healthy/unhealthy/degraded)
|
|
234
|
+
"""
|
|
235
|
+
|
|
236
|
+
HEALTHY = "healthy"
|
|
237
|
+
"""Component is functioning normally."""
|
|
238
|
+
|
|
239
|
+
UNHEALTHY = "unhealthy"
|
|
240
|
+
"""Component is not functioning correctly."""
|
|
241
|
+
|
|
242
|
+
DEGRADED = "degraded"
|
|
243
|
+
"""Component is functioning with reduced capability."""
|
|
244
|
+
|
|
245
|
+
UNKNOWN = "unknown"
|
|
246
|
+
"""Health status cannot be determined."""
|
|
247
|
+
|
|
248
|
+
CHECKING = "checking"
|
|
249
|
+
"""Health check is currently in progress."""
|
|
250
|
+
|
|
251
|
+
TIMEOUT = "timeout"
|
|
252
|
+
"""Health check exceeded time limit."""
|
|
253
|
+
|
|
254
|
+
|
|
182
255
|
class ModelTier(StrEnum):
|
|
183
256
|
"""
|
|
184
257
|
Claude model tier classifications and identifiers.
|
|
@@ -272,48 +345,87 @@ class AgentCategory(StrEnum):
|
|
|
272
345
|
|
|
273
346
|
Migration Priority: MEDIUM (Week 3)
|
|
274
347
|
Coverage: ~3% of all magic strings
|
|
348
|
+
|
|
349
|
+
Notes:
|
|
350
|
+
- Expanded in Phase 3C to include all template categories
|
|
351
|
+
- Maps to actual usage in agent JSON templates
|
|
352
|
+
- Supports both legacy and new category schemes
|
|
275
353
|
"""
|
|
276
354
|
|
|
355
|
+
# Core Engineering Categories
|
|
356
|
+
ENGINEERING = "engineering"
|
|
357
|
+
"""Software engineering and implementation agents."""
|
|
358
|
+
|
|
359
|
+
# Research and Analysis
|
|
277
360
|
RESEARCH = "research"
|
|
278
361
|
"""Research and analysis agents."""
|
|
279
362
|
|
|
280
|
-
|
|
281
|
-
"""
|
|
363
|
+
ANALYSIS = "analysis"
|
|
364
|
+
"""Code analysis and architectural review agents."""
|
|
365
|
+
|
|
366
|
+
# Quality and Testing
|
|
367
|
+
QUALITY = "quality"
|
|
368
|
+
"""Quality assurance and testing agents (replaces QA)."""
|
|
282
369
|
|
|
283
370
|
QA = "qa"
|
|
284
|
-
"""
|
|
371
|
+
"""Legacy quality assurance category (use QUALITY for new agents)."""
|
|
285
372
|
|
|
286
373
|
SECURITY = "security"
|
|
287
374
|
"""Security analysis and vulnerability assessment agents."""
|
|
288
375
|
|
|
376
|
+
# Operations and Infrastructure
|
|
377
|
+
OPERATIONS = "operations"
|
|
378
|
+
"""DevOps and infrastructure management agents."""
|
|
379
|
+
|
|
380
|
+
INFRASTRUCTURE = "infrastructure"
|
|
381
|
+
"""Infrastructure provisioning and cloud management agents."""
|
|
382
|
+
|
|
383
|
+
# Documentation and Content
|
|
289
384
|
DOCUMENTATION = "documentation"
|
|
290
385
|
"""Documentation and technical writing agents."""
|
|
291
386
|
|
|
292
|
-
|
|
293
|
-
"""
|
|
387
|
+
CONTENT = "content"
|
|
388
|
+
"""Content creation, optimization, and management agents."""
|
|
294
389
|
|
|
390
|
+
# Data and Analytics
|
|
295
391
|
DATA = "data"
|
|
296
392
|
"""Data engineering and analytics agents."""
|
|
297
393
|
|
|
394
|
+
# Specialized Functions
|
|
395
|
+
OPTIMIZATION = "optimization"
|
|
396
|
+
"""Performance and resource optimization agents."""
|
|
397
|
+
|
|
398
|
+
SPECIALIZED = "specialized"
|
|
399
|
+
"""Specialized single-purpose agents."""
|
|
400
|
+
|
|
401
|
+
SYSTEM = "system"
|
|
402
|
+
"""System-level framework agents."""
|
|
403
|
+
|
|
404
|
+
# Management and Coordination
|
|
405
|
+
PROJECT_MANAGEMENT = "project-management"
|
|
406
|
+
"""Project management and coordination agents."""
|
|
407
|
+
|
|
408
|
+
PRODUCT = "product"
|
|
409
|
+
"""Product ownership and strategy agents."""
|
|
410
|
+
|
|
411
|
+
# Legacy and General
|
|
298
412
|
VERSION_CONTROL = "version_control"
|
|
299
413
|
"""Version control and release management agents."""
|
|
300
414
|
|
|
415
|
+
DESIGN = "design"
|
|
416
|
+
"""UI/UX design and frontend agents."""
|
|
417
|
+
|
|
301
418
|
GENERAL = "general"
|
|
302
419
|
"""General-purpose agents without specific specialization."""
|
|
303
420
|
|
|
304
421
|
CUSTOM = "custom"
|
|
305
422
|
"""User-defined custom agent categories."""
|
|
306
423
|
|
|
307
|
-
PROJECT_MANAGEMENT = "project_management"
|
|
308
|
-
"""Project management and coordination agents."""
|
|
309
|
-
|
|
310
|
-
DESIGN = "design"
|
|
311
|
-
"""UI/UX design and frontend agents."""
|
|
312
|
-
|
|
313
424
|
|
|
314
425
|
# Export all enums for convenient access
|
|
315
426
|
__all__ = [
|
|
316
427
|
"AgentCategory",
|
|
428
|
+
"HealthStatus",
|
|
317
429
|
"ModelTier",
|
|
318
430
|
"OperationResult",
|
|
319
431
|
"OutputFormat",
|
|
@@ -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=
|
|
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=
|
|
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=
|
|
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=
|
|
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
|
-
|
|
320
|
+
OperationResult.WARNING
|
|
322
321
|
if deployed_agents
|
|
323
|
-
else
|
|
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=
|
|
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=
|
|
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
|
|
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=
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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=
|
|
131
|
+
status=OperationResult.FAILED,
|
|
131
132
|
message=error_msg,
|
|
132
133
|
error=e,
|
|
133
134
|
execution_time=execution_time,
|