claude-mpm 3.7.4__py3-none-any.whl → 3.8.1__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_PM.md +0 -106
- claude_mpm/agents/INSTRUCTIONS.md +0 -78
- claude_mpm/agents/MEMORY.md +88 -0
- claude_mpm/agents/WORKFLOW.md +86 -0
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/templates/code_analyzer.json +26 -11
- claude_mpm/agents/templates/data_engineer.json +4 -7
- claude_mpm/agents/templates/documentation.json +2 -2
- claude_mpm/agents/templates/engineer.json +2 -2
- claude_mpm/agents/templates/ops.json +3 -8
- claude_mpm/agents/templates/qa.json +2 -3
- claude_mpm/agents/templates/research.json +2 -3
- claude_mpm/agents/templates/security.json +3 -6
- claude_mpm/agents/templates/ticketing.json +4 -9
- claude_mpm/agents/templates/version_control.json +3 -3
- claude_mpm/agents/templates/web_qa.json +4 -4
- claude_mpm/agents/templates/web_ui.json +4 -4
- claude_mpm/cli/__init__.py +2 -2
- claude_mpm/cli/commands/__init__.py +2 -1
- claude_mpm/cli/commands/agents.py +118 -1
- claude_mpm/cli/commands/tickets.py +596 -19
- claude_mpm/cli/parser.py +228 -5
- claude_mpm/config/__init__.py +30 -39
- claude_mpm/config/socketio_config.py +8 -5
- claude_mpm/constants.py +13 -0
- claude_mpm/core/__init__.py +8 -18
- claude_mpm/core/cache.py +596 -0
- claude_mpm/core/claude_runner.py +166 -622
- claude_mpm/core/config.py +5 -1
- claude_mpm/core/constants.py +339 -0
- claude_mpm/core/container.py +461 -22
- claude_mpm/core/exceptions.py +392 -0
- claude_mpm/core/framework_loader.py +208 -93
- claude_mpm/core/interactive_session.py +432 -0
- claude_mpm/core/interfaces.py +424 -0
- claude_mpm/core/lazy.py +467 -0
- claude_mpm/core/logging_config.py +444 -0
- claude_mpm/core/oneshot_session.py +465 -0
- claude_mpm/core/optimized_agent_loader.py +485 -0
- claude_mpm/core/optimized_startup.py +490 -0
- claude_mpm/core/service_registry.py +52 -26
- claude_mpm/core/socketio_pool.py +162 -5
- claude_mpm/core/types.py +292 -0
- claude_mpm/core/typing_utils.py +477 -0
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +46 -2
- claude_mpm/dashboard/templates/index.html +5 -5
- claude_mpm/hooks/claude_hooks/hook_handler.py +213 -99
- claude_mpm/init.py +2 -1
- claude_mpm/services/__init__.py +78 -14
- claude_mpm/services/agent/__init__.py +24 -0
- claude_mpm/services/agent/deployment.py +2548 -0
- claude_mpm/services/agent/management.py +598 -0
- claude_mpm/services/agent/registry.py +813 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +592 -269
- claude_mpm/services/agents/deployment/async_agent_deployment.py +5 -1
- claude_mpm/services/agents/management/agent_capabilities_generator.py +21 -11
- claude_mpm/services/agents/memory/agent_memory_manager.py +156 -1
- claude_mpm/services/async_session_logger.py +8 -3
- claude_mpm/services/communication/__init__.py +21 -0
- claude_mpm/services/communication/socketio.py +1933 -0
- claude_mpm/services/communication/websocket.py +479 -0
- claude_mpm/services/core/__init__.py +123 -0
- claude_mpm/services/core/base.py +247 -0
- claude_mpm/services/core/interfaces.py +951 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +23 -23
- claude_mpm/services/framework_claude_md_generator.py +3 -2
- claude_mpm/services/health_monitor.py +4 -3
- claude_mpm/services/hook_service.py +64 -4
- claude_mpm/services/infrastructure/__init__.py +21 -0
- claude_mpm/services/infrastructure/logging.py +202 -0
- claude_mpm/services/infrastructure/monitoring.py +893 -0
- claude_mpm/services/memory/indexed_memory.py +648 -0
- claude_mpm/services/project/__init__.py +21 -0
- claude_mpm/services/project/analyzer.py +864 -0
- claude_mpm/services/project/registry.py +608 -0
- claude_mpm/services/project_analyzer.py +95 -2
- claude_mpm/services/recovery_manager.py +15 -9
- claude_mpm/services/socketio/__init__.py +25 -0
- claude_mpm/services/socketio/handlers/__init__.py +25 -0
- claude_mpm/services/socketio/handlers/base.py +121 -0
- claude_mpm/services/socketio/handlers/connection.py +198 -0
- claude_mpm/services/socketio/handlers/file.py +213 -0
- claude_mpm/services/socketio/handlers/git.py +723 -0
- claude_mpm/services/socketio/handlers/memory.py +27 -0
- claude_mpm/services/socketio/handlers/project.py +25 -0
- claude_mpm/services/socketio/handlers/registry.py +145 -0
- claude_mpm/services/socketio_client_manager.py +12 -7
- claude_mpm/services/socketio_server.py +156 -30
- claude_mpm/services/ticket_manager.py +377 -51
- claude_mpm/utils/agent_dependency_loader.py +66 -15
- claude_mpm/utils/error_handler.py +1 -1
- claude_mpm/utils/robust_installer.py +587 -0
- claude_mpm/validation/agent_validator.py +27 -14
- claude_mpm/validation/frontmatter_validator.py +231 -0
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/METADATA +74 -41
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/RECORD +101 -76
- claude_mpm/.claude-mpm/logs/hooks_20250728.log +0 -10
- claude_mpm/agents/agent-template.yaml +0 -83
- claude_mpm/cli/README.md +0 -108
- claude_mpm/cli_module/refactoring_guide.md +0 -253
- claude_mpm/config/async_logging_config.yaml +0 -145
- claude_mpm/core/.claude-mpm/logs/hooks_20250730.log +0 -34
- claude_mpm/dashboard/.claude-mpm/memories/README.md +0 -36
- claude_mpm/dashboard/README.md +0 -121
- claude_mpm/dashboard/static/js/dashboard.js.backup +0 -1973
- claude_mpm/dashboard/templates/.claude-mpm/memories/README.md +0 -36
- claude_mpm/dashboard/templates/.claude-mpm/memories/engineer_agent.md +0 -39
- claude_mpm/dashboard/templates/.claude-mpm/memories/version_control_agent.md +0 -38
- claude_mpm/hooks/README.md +0 -96
- claude_mpm/schemas/agent_schema.json +0 -435
- claude_mpm/services/framework_claude_md_generator/README.md +0 -92
- claude_mpm/services/version_control/VERSION +0 -1
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/WHEEL +0 -0
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/entry_points.txt +0 -0
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-3.7.4.dist-info → claude_mpm-3.8.1.dist-info}/top_level.txt +0 -0
| @@ -45,31 +45,31 @@ Task(description="[task description]", subagent_type="[agent-type]") | |
| 45 45 |  | 
| 46 46 | 
             
            **Valid subagent_type values (use lowercase format for Claude Code compatibility):**
         | 
| 47 47 |  | 
| 48 | 
            -
            **Required  | 
| 49 | 
            -
            - `subagent_type="research"` - For investigation and analysis
         | 
| 48 | 
            +
            **Required format (Claude Code expects these exact values from deployed agent YAML names):**
         | 
| 49 | 
            +
            - `subagent_type="research-agent"` - For investigation and analysis
         | 
| 50 50 | 
             
            - `subagent_type="engineer"` - For coding and implementation
         | 
| 51 | 
            -
            - `subagent_type="qa"` - For testing and quality assurance
         | 
| 52 | 
            -
            - `subagent_type="documentation"` - For docs and guides
         | 
| 53 | 
            -
            - `subagent_type="security"` - For security assessments
         | 
| 54 | 
            -
            - `subagent_type="ops"` - For deployment and infrastructure
         | 
| 55 | 
            -
            - `subagent_type=" | 
| 56 | 
            -
            - `subagent_type=" | 
| 51 | 
            +
            - `subagent_type="qa-agent"` - For testing and quality assurance
         | 
| 52 | 
            +
            - `subagent_type="documentation-agent"` - For docs and guides
         | 
| 53 | 
            +
            - `subagent_type="security-agent"` - For security assessments
         | 
| 54 | 
            +
            - `subagent_type="ops-agent"` - For deployment and infrastructure
         | 
| 55 | 
            +
            - `subagent_type="version-control"` - For git and version management
         | 
| 56 | 
            +
            - `subagent_type="data-engineer"` - For data processing and APIs
         | 
| 57 57 | 
             
            - `subagent_type="pm"` - For project management coordination
         | 
| 58 58 | 
             
            - `subagent_type="test_integration"` - For integration testing
         | 
| 59 59 |  | 
| 60 | 
            -
            **Note:** Claude Code's Task tool requires exact  | 
| 60 | 
            +
            **Note:** Claude Code's Task tool requires exact agent names as defined in the deployed agent YAML frontmatter. The names must match exactly - including hyphens where specified.
         | 
| 61 61 |  | 
| 62 | 
            -
            **Examples of Proper Task Tool Usage ( | 
| 63 | 
            -
            - ✅ `Task(description="Update framework documentation", subagent_type="documentation")`
         | 
| 64 | 
            -
            - ✅ `Task(description="Execute test suite validation", subagent_type="qa")`
         | 
| 65 | 
            -
            - ✅ `Task(description="Create feature branch and sync", subagent_type=" | 
| 66 | 
            -
            - ✅ `Task(description="Investigate performance patterns", subagent_type="research")`
         | 
| 62 | 
            +
            **Examples of Proper Task Tool Usage (must match deployed agent YAML names):**
         | 
| 63 | 
            +
            - ✅ `Task(description="Update framework documentation", subagent_type="documentation-agent")`
         | 
| 64 | 
            +
            - ✅ `Task(description="Execute test suite validation", subagent_type="qa-agent")`
         | 
| 65 | 
            +
            - ✅ `Task(description="Create feature branch and sync", subagent_type="version-control")`
         | 
| 66 | 
            +
            - ✅ `Task(description="Investigate performance patterns", subagent_type="research-agent")`
         | 
| 67 67 | 
             
            - ✅ `Task(description="Implement authentication system", subagent_type="engineer")`
         | 
| 68 | 
            -
            - ✅ `Task(description="Configure database and optimize queries", subagent_type=" | 
| 68 | 
            +
            - ✅ `Task(description="Configure database and optimize queries", subagent_type="data-engineer")`
         | 
| 69 69 | 
             
            - ✅ `Task(description="Coordinate project tasks", subagent_type="pm")`
         | 
| 70 | 
            -
            - ❌ `Task(description="Analyze code patterns", subagent_type=" | 
| 71 | 
            -
            - ❌ `Task(description="Update API docs", subagent_type=" | 
| 72 | 
            -
            - ❌ `Task(description="Create release tags", subagent_type=" | 
| 70 | 
            +
            - ❌ `Task(description="Analyze code patterns", subagent_type="research")` (WRONG - missing '-agent' suffix)
         | 
| 71 | 
            +
            - ❌ `Task(description="Update API docs", subagent_type="documentation")` (WRONG - missing '-agent' suffix)
         | 
| 72 | 
            +
            - ❌ `Task(description="Create release tags", subagent_type="version_control")` (WRONG - should be 'version-control')
         | 
| 73 73 |  | 
| 74 74 | 
             
            ### 🚨 MANDATORY: THREE SHORTCUT COMMANDS
         | 
| 75 75 |  | 
| @@ -98,11 +98,11 @@ Task(description="[task description]", subagent_type="[agent-type]") | |
| 98 98 | 
             
            - ☐ [Data Engineer] Validate data integrity and verify API connectivity
         | 
| 99 99 | 
             
            - ☐ [Version Control] Apply semantic version bump and create release tags
         | 
| 100 100 |  | 
| 101 | 
            -
            # Corresponding Task Tool delegations ( | 
| 102 | 
            -
            Task(description="Generate changelog and analyze version impact", subagent_type="documentation")
         | 
| 103 | 
            -
            Task(description="Execute full test suite and quality validation", subagent_type="qa")
         | 
| 104 | 
            -
            Task(description="Validate data integrity and verify API connectivity", subagent_type=" | 
| 105 | 
            -
            Task(description="Apply semantic version bump and create release tags", subagent_type=" | 
| 101 | 
            +
            # Corresponding Task Tool delegations (must match deployed agent names):
         | 
| 102 | 
            +
            Task(description="Generate changelog and analyze version impact", subagent_type="documentation-agent")
         | 
| 103 | 
            +
            Task(description="Execute full test suite and quality validation", subagent_type="qa-agent")
         | 
| 104 | 
            +
            Task(description="Validate data integrity and verify API connectivity", subagent_type="data-engineer")
         | 
| 105 | 
            +
            Task(description="Apply semantic version bump and create release tags", subagent_type="version-control")
         | 
| 106 106 |  | 
| 107 107 | 
             
            # Update TodoWrite status based on agent completions
         | 
| 108 108 | 
             
            ```
         | 
| @@ -19,6 +19,7 @@ from typing import Dict, Optional, Any, List, Tuple, Callable | |
| 19 19 | 
             
            from dataclasses import dataclass, field
         | 
| 20 20 |  | 
| 21 21 | 
             
            from claude_mpm.core.config_paths import ConfigPaths
         | 
| 22 | 
            +
            from claude_mpm.core.constants import SystemLimits
         | 
| 22 23 |  | 
| 23 24 | 
             
            logger = logging.getLogger(__name__)
         | 
| 24 25 |  | 
| @@ -450,8 +451,8 @@ class FrameworkClaudeMdGenerator: | |
| 450 451 | 
             
                    suggestions = []
         | 
| 451 452 |  | 
| 452 453 | 
             
                    # Check minimum length
         | 
| 453 | 
            -
                    if len(content) <  | 
| 454 | 
            -
                        errors.append("Content seems too short")
         | 
| 454 | 
            +
                    if len(content) < SystemLimits.MIN_CONTENT_LENGTH:
         | 
| 455 | 
            +
                        errors.append(f"Content seems too short (minimum {SystemLimits.MIN_CONTENT_LENGTH} characters)")
         | 
| 455 456 |  | 
| 456 457 | 
             
                    # Check for required sections
         | 
| 457 458 | 
             
                    required_sections = [
         | 
| @@ -27,6 +27,7 @@ from pathlib import Path | |
| 27 27 | 
             
            from typing import Any, Dict, List, Optional, Callable, Union
         | 
| 28 28 | 
             
            import json
         | 
| 29 29 | 
             
            import socket
         | 
| 30 | 
            +
            from claude_mpm.core.constants import ResourceLimits, TimeoutConfig
         | 
| 30 31 |  | 
| 31 32 | 
             
            try:
         | 
| 32 33 | 
             
                import psutil
         | 
| @@ -196,7 +197,7 @@ class ProcessResourceChecker(HealthChecker): | |
| 196 197 |  | 
| 197 198 | 
             
                        # CPU usage
         | 
| 198 199 | 
             
                        try:
         | 
| 199 | 
            -
                            cpu_percent = self.process.cpu_percent(interval= | 
| 200 | 
            +
                            cpu_percent = self.process.cpu_percent(interval=TimeoutConfig.CPU_SAMPLE_INTERVAL)
         | 
| 200 201 | 
             
                            cpu_status = HealthStatus.HEALTHY
         | 
| 201 202 | 
             
                            if cpu_percent > self.cpu_threshold:
         | 
| 202 203 | 
             
                                cpu_status = HealthStatus.WARNING if cpu_percent < self.cpu_threshold * 1.2 else HealthStatus.CRITICAL
         | 
| @@ -219,7 +220,7 @@ class ProcessResourceChecker(HealthChecker): | |
| 219 220 | 
             
                        # Memory usage
         | 
| 220 221 | 
             
                        try:
         | 
| 221 222 | 
             
                            memory_info = self.process.memory_info()
         | 
| 222 | 
            -
                            memory_mb = memory_info.rss /  | 
| 223 | 
            +
                            memory_mb = memory_info.rss / ResourceLimits.BYTES_TO_MB
         | 
| 223 224 | 
             
                            memory_status = HealthStatus.HEALTHY
         | 
| 224 225 | 
             
                            if memory_mb > self.memory_threshold_mb:
         | 
| 225 226 | 
             
                                memory_status = HealthStatus.WARNING if memory_mb < self.memory_threshold_mb * 1.2 else HealthStatus.CRITICAL
         | 
| @@ -234,7 +235,7 @@ class ProcessResourceChecker(HealthChecker): | |
| 234 235 |  | 
| 235 236 | 
             
                            metrics.append(HealthMetric(
         | 
| 236 237 | 
             
                                name="memory_vms_mb",
         | 
| 237 | 
            -
                                value=round(memory_info.vms /  | 
| 238 | 
            +
                                value=round(memory_info.vms / ResourceLimits.BYTES_TO_MB, 2),
         | 
| 238 239 | 
             
                                status=HealthStatus.HEALTHY,
         | 
| 239 240 | 
             
                                unit="MB"
         | 
| 240 241 | 
             
                            ))
         | 
| @@ -16,7 +16,7 @@ import time | |
| 16 16 | 
             
            from datetime import datetime
         | 
| 17 17 |  | 
| 18 18 | 
             
            from claude_mpm.core.config import Config
         | 
| 19 | 
            -
            from claude_mpm.core. | 
| 19 | 
            +
            from claude_mpm.core.logging_config import get_logger, log_operation
         | 
| 20 20 | 
             
            from claude_mpm.hooks.base_hook import (
         | 
| 21 21 | 
             
                BaseHook,
         | 
| 22 22 | 
             
                PreDelegationHook,
         | 
| @@ -25,9 +25,10 @@ from claude_mpm.hooks.base_hook import ( | |
| 25 25 | 
             
                HookResult,
         | 
| 26 26 | 
             
                HookType
         | 
| 27 27 | 
             
            )
         | 
| 28 | 
            +
            from claude_mpm.core.interfaces import HookServiceInterface
         | 
| 28 29 |  | 
| 29 30 |  | 
| 30 | 
            -
            class HookService:
         | 
| 31 | 
            +
            class HookService(HookServiceInterface):
         | 
| 31 32 | 
             
                """Service for managing and executing hooks in the delegation workflow.
         | 
| 32 33 |  | 
| 33 34 | 
             
                WHY: Provides a centralized place to register and execute hooks, ensuring
         | 
| @@ -47,7 +48,7 @@ class HookService: | |
| 47 48 | 
             
                        config: Optional configuration object for controlling hook behavior
         | 
| 48 49 | 
             
                    """
         | 
| 49 50 | 
             
                    self.config = config or Config()
         | 
| 50 | 
            -
                    self.logger = get_logger( | 
| 51 | 
            +
                    self.logger = get_logger(__name__)
         | 
| 51 52 |  | 
| 52 53 | 
             
                    # Separate lists for different hook types for performance
         | 
| 53 54 | 
             
                    self.pre_delegation_hooks: List[PreDelegationHook] = []
         | 
| @@ -359,4 +360,63 @@ class HookService: | |
| 359 360 | 
             
                            return True
         | 
| 360 361 |  | 
| 361 362 | 
             
                    self.logger.warning(f"Hook not found: {hook_name}")
         | 
| 362 | 
            -
                    return False
         | 
| 363 | 
            +
                    return False
         | 
| 364 | 
            +
                
         | 
| 365 | 
            +
                # ================================================================================
         | 
| 366 | 
            +
                # Interface Adapter Methods
         | 
| 367 | 
            +
                # ================================================================================
         | 
| 368 | 
            +
                # These methods are added to comply with HookServiceInterface
         | 
| 369 | 
            +
                
         | 
| 370 | 
            +
                def get_registered_hooks(self) -> Dict[str, List[Any]]:
         | 
| 371 | 
            +
                    """Get all registered hooks by type.
         | 
| 372 | 
            +
                    
         | 
| 373 | 
            +
                    WHY: This method provides interface compliance by exposing the
         | 
| 374 | 
            +
                    registered hooks for inspection and debugging purposes.
         | 
| 375 | 
            +
                    
         | 
| 376 | 
            +
                    Returns:
         | 
| 377 | 
            +
                        Dictionary mapping hook types to lists of hooks
         | 
| 378 | 
            +
                    """
         | 
| 379 | 
            +
                    return {
         | 
| 380 | 
            +
                        "pre_delegation": [
         | 
| 381 | 
            +
                            {
         | 
| 382 | 
            +
                                "name": hook.name,
         | 
| 383 | 
            +
                                "priority": hook.priority,
         | 
| 384 | 
            +
                                "enabled": hook.enabled,
         | 
| 385 | 
            +
                                "type": "pre_delegation"
         | 
| 386 | 
            +
                            }
         | 
| 387 | 
            +
                            for hook in self.pre_delegation_hooks
         | 
| 388 | 
            +
                        ],
         | 
| 389 | 
            +
                        "post_delegation": [
         | 
| 390 | 
            +
                            {
         | 
| 391 | 
            +
                                "name": hook.name,
         | 
| 392 | 
            +
                                "priority": hook.priority,
         | 
| 393 | 
            +
                                "enabled": hook.enabled,
         | 
| 394 | 
            +
                                "type": "post_delegation"
         | 
| 395 | 
            +
                            }
         | 
| 396 | 
            +
                            for hook in self.post_delegation_hooks
         | 
| 397 | 
            +
                        ]
         | 
| 398 | 
            +
                    }
         | 
| 399 | 
            +
                
         | 
| 400 | 
            +
                def clear_hooks(self, hook_type: Optional[str] = None) -> None:
         | 
| 401 | 
            +
                    """Clear registered hooks.
         | 
| 402 | 
            +
                    
         | 
| 403 | 
            +
                    WHY: This method provides interface compliance by allowing bulk
         | 
| 404 | 
            +
                    removal of hooks, useful for testing and cleanup scenarios.
         | 
| 405 | 
            +
                    
         | 
| 406 | 
            +
                    Args:
         | 
| 407 | 
            +
                        hook_type: Optional specific hook type to clear, or None for all
         | 
| 408 | 
            +
                    """
         | 
| 409 | 
            +
                    if hook_type is None or hook_type == "pre_delegation":
         | 
| 410 | 
            +
                        count = len(self.pre_delegation_hooks)
         | 
| 411 | 
            +
                        self.pre_delegation_hooks.clear()
         | 
| 412 | 
            +
                        if count > 0:
         | 
| 413 | 
            +
                            self.logger.info(f"Cleared {count} pre-delegation hooks")
         | 
| 414 | 
            +
                    
         | 
| 415 | 
            +
                    if hook_type is None or hook_type == "post_delegation":
         | 
| 416 | 
            +
                        count = len(self.post_delegation_hooks)
         | 
| 417 | 
            +
                        self.post_delegation_hooks.clear()
         | 
| 418 | 
            +
                        if count > 0:
         | 
| 419 | 
            +
                            self.logger.info(f"Cleared {count} post-delegation hooks")
         | 
| 420 | 
            +
                    
         | 
| 421 | 
            +
                    if hook_type and hook_type not in ["pre_delegation", "post_delegation"]:
         | 
| 422 | 
            +
                        self.logger.warning(f"Unknown hook type: {hook_type}")
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            """
         | 
| 2 | 
            +
            Infrastructure Services Module
         | 
| 3 | 
            +
            =============================
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            This module contains infrastructure-related services including
         | 
| 6 | 
            +
            logging, monitoring, and system health management.
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            Part of TSK-0046: Service Layer Architecture Reorganization
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            Services:
         | 
| 11 | 
            +
            - LoggingService: Centralized logging with structured output
         | 
| 12 | 
            +
            - HealthMonitor: System health monitoring and alerting
         | 
| 13 | 
            +
            """
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            from .logging import LoggingService
         | 
| 16 | 
            +
            from .monitoring import HealthMonitor
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            __all__ = [
         | 
| 19 | 
            +
                'LoggingService',
         | 
| 20 | 
            +
                'HealthMonitor',
         | 
| 21 | 
            +
            ]
         | 
| @@ -0,0 +1,202 @@ | |
| 1 | 
            +
            """
         | 
| 2 | 
            +
            Logging Service for Claude MPM Framework
         | 
| 3 | 
            +
            ========================================
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            This module provides centralized logging services and utilities.
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            Part of TSK-0046: Service Layer Architecture Reorganization
         | 
| 8 | 
            +
            """
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            from typing import Any, Dict, Optional, List
         | 
| 11 | 
            +
            from pathlib import Path
         | 
| 12 | 
            +
            import logging
         | 
| 13 | 
            +
            import json
         | 
| 14 | 
            +
            from datetime import datetime
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            from claude_mpm.services.core import SyncBaseService, ILoggingService
         | 
| 17 | 
            +
            from claude_mpm.utils.logger import get_logger
         | 
| 18 | 
            +
             | 
| 19 | 
            +
             | 
| 20 | 
            +
            class LoggingService(SyncBaseService, ILoggingService):
         | 
| 21 | 
            +
                """
         | 
| 22 | 
            +
                Centralized logging service for the Claude MPM framework.
         | 
| 23 | 
            +
                
         | 
| 24 | 
            +
                This service provides:
         | 
| 25 | 
            +
                - Structured logging with JSON output
         | 
| 26 | 
            +
                - Log rotation and archival
         | 
| 27 | 
            +
                - Performance metrics logging
         | 
| 28 | 
            +
                - Audit trail capabilities
         | 
| 29 | 
            +
                """
         | 
| 30 | 
            +
                
         | 
| 31 | 
            +
                def __init__(self, config: Optional[Dict[str, Any]] = None):
         | 
| 32 | 
            +
                    """
         | 
| 33 | 
            +
                    Initialize logging service.
         | 
| 34 | 
            +
                    
         | 
| 35 | 
            +
                    Args:
         | 
| 36 | 
            +
                        config: Logging configuration
         | 
| 37 | 
            +
                    """
         | 
| 38 | 
            +
                    super().__init__("LoggingService", config)
         | 
| 39 | 
            +
                    self.log_dir = Path(self.get_config('log_dir', '.claude-mpm/logs'))
         | 
| 40 | 
            +
                    self.log_level = self.get_config('log_level', 'INFO')
         | 
| 41 | 
            +
                    self.structured_logging = self.get_config('structured_logging', True)
         | 
| 42 | 
            +
                    self._log_handlers = []
         | 
| 43 | 
            +
                
         | 
| 44 | 
            +
                def initialize(self) -> bool:
         | 
| 45 | 
            +
                    """Initialize the logging service."""
         | 
| 46 | 
            +
                    try:
         | 
| 47 | 
            +
                        # Create log directory if it doesn't exist
         | 
| 48 | 
            +
                        self.log_dir.mkdir(parents=True, exist_ok=True)
         | 
| 49 | 
            +
                        
         | 
| 50 | 
            +
                        # Set up log rotation if configured
         | 
| 51 | 
            +
                        if self.get_config('enable_rotation', True):
         | 
| 52 | 
            +
                            self._setup_rotation()
         | 
| 53 | 
            +
                        
         | 
| 54 | 
            +
                        # Set up structured logging if enabled
         | 
| 55 | 
            +
                        if self.structured_logging:
         | 
| 56 | 
            +
                            self._setup_structured_logging()
         | 
| 57 | 
            +
                        
         | 
| 58 | 
            +
                        self._initialized = True
         | 
| 59 | 
            +
                        self.log_info("Logging service initialized successfully")
         | 
| 60 | 
            +
                        return True
         | 
| 61 | 
            +
                        
         | 
| 62 | 
            +
                    except Exception as e:
         | 
| 63 | 
            +
                        self.log_error(f"Failed to initialize logging service: {e}")
         | 
| 64 | 
            +
                        return False
         | 
| 65 | 
            +
                
         | 
| 66 | 
            +
                def shutdown(self) -> None:
         | 
| 67 | 
            +
                    """Shutdown the logging service."""
         | 
| 68 | 
            +
                    try:
         | 
| 69 | 
            +
                        # Flush all handlers
         | 
| 70 | 
            +
                        for handler in self._log_handlers:
         | 
| 71 | 
            +
                            handler.flush()
         | 
| 72 | 
            +
                            handler.close()
         | 
| 73 | 
            +
                        
         | 
| 74 | 
            +
                        self._log_handlers.clear()
         | 
| 75 | 
            +
                        self._shutdown = True
         | 
| 76 | 
            +
                        self.log_info("Logging service shutdown successfully")
         | 
| 77 | 
            +
                        
         | 
| 78 | 
            +
                    except Exception as e:
         | 
| 79 | 
            +
                        self.log_error(f"Error during logging service shutdown: {e}")
         | 
| 80 | 
            +
                
         | 
| 81 | 
            +
                def log(self, level: str, message: str, **context) -> None:
         | 
| 82 | 
            +
                    """
         | 
| 83 | 
            +
                    Log a message with context.
         | 
| 84 | 
            +
                    
         | 
| 85 | 
            +
                    Args:
         | 
| 86 | 
            +
                        level: Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
         | 
| 87 | 
            +
                        message: Log message
         | 
| 88 | 
            +
                        **context: Additional context to include
         | 
| 89 | 
            +
                    """
         | 
| 90 | 
            +
                    logger = get_logger(context.get('component', 'default'))
         | 
| 91 | 
            +
                    
         | 
| 92 | 
            +
                    if self.structured_logging:
         | 
| 93 | 
            +
                        log_entry = {
         | 
| 94 | 
            +
                            'timestamp': datetime.utcnow().isoformat(),
         | 
| 95 | 
            +
                            'level': level,
         | 
| 96 | 
            +
                            'message': message,
         | 
| 97 | 
            +
                            'context': context
         | 
| 98 | 
            +
                        }
         | 
| 99 | 
            +
                        message = json.dumps(log_entry)
         | 
| 100 | 
            +
                    
         | 
| 101 | 
            +
                    log_method = getattr(logger, level.lower(), logger.info)
         | 
| 102 | 
            +
                    log_method(message)
         | 
| 103 | 
            +
                
         | 
| 104 | 
            +
                def log_performance(self, operation: str, duration: float, **metrics) -> None:
         | 
| 105 | 
            +
                    """
         | 
| 106 | 
            +
                    Log performance metrics.
         | 
| 107 | 
            +
                    
         | 
| 108 | 
            +
                    Args:
         | 
| 109 | 
            +
                        operation: Name of the operation
         | 
| 110 | 
            +
                        duration: Duration in seconds
         | 
| 111 | 
            +
                        **metrics: Additional performance metrics
         | 
| 112 | 
            +
                    """
         | 
| 113 | 
            +
                    self.log('INFO', f"Performance: {operation}", 
         | 
| 114 | 
            +
                            operation=operation, 
         | 
| 115 | 
            +
                            duration_ms=duration * 1000,
         | 
| 116 | 
            +
                            **metrics)
         | 
| 117 | 
            +
                
         | 
| 118 | 
            +
                def log_audit(self, action: str, user: str, **details) -> None:
         | 
| 119 | 
            +
                    """
         | 
| 120 | 
            +
                    Log an audit event.
         | 
| 121 | 
            +
                    
         | 
| 122 | 
            +
                    Args:
         | 
| 123 | 
            +
                        action: Action performed
         | 
| 124 | 
            +
                        user: User who performed the action
         | 
| 125 | 
            +
                        **details: Additional audit details
         | 
| 126 | 
            +
                    """
         | 
| 127 | 
            +
                    self.log('INFO', f"Audit: {action} by {user}",
         | 
| 128 | 
            +
                            audit=True,
         | 
| 129 | 
            +
                            action=action,
         | 
| 130 | 
            +
                            user=user,
         | 
| 131 | 
            +
                            **details)
         | 
| 132 | 
            +
                
         | 
| 133 | 
            +
                def get_logs(self, level: Optional[str] = None, 
         | 
| 134 | 
            +
                             component: Optional[str] = None,
         | 
| 135 | 
            +
                             limit: int = 100) -> List[Dict[str, Any]]:
         | 
| 136 | 
            +
                    """
         | 
| 137 | 
            +
                    Retrieve recent logs.
         | 
| 138 | 
            +
                    
         | 
| 139 | 
            +
                    Args:
         | 
| 140 | 
            +
                        level: Filter by log level
         | 
| 141 | 
            +
                        component: Filter by component
         | 
| 142 | 
            +
                        limit: Maximum number of logs to return
         | 
| 143 | 
            +
                        
         | 
| 144 | 
            +
                    Returns:
         | 
| 145 | 
            +
                        List of log entries
         | 
| 146 | 
            +
                    """
         | 
| 147 | 
            +
                    # This would typically read from log files or a log aggregation service
         | 
| 148 | 
            +
                    # For now, return empty list as placeholder
         | 
| 149 | 
            +
                    return []
         | 
| 150 | 
            +
                
         | 
| 151 | 
            +
                def _setup_rotation(self) -> None:
         | 
| 152 | 
            +
                    """Set up log rotation."""
         | 
| 153 | 
            +
                    from logging.handlers import RotatingFileHandler
         | 
| 154 | 
            +
                    
         | 
| 155 | 
            +
                    max_bytes = self.get_config('max_bytes', 10 * 1024 * 1024)  # 10MB
         | 
| 156 | 
            +
                    backup_count = self.get_config('backup_count', 5)
         | 
| 157 | 
            +
                    
         | 
| 158 | 
            +
                    handler = RotatingFileHandler(
         | 
| 159 | 
            +
                        self.log_dir / 'claude_mpm.log',
         | 
| 160 | 
            +
                        maxBytes=max_bytes,
         | 
| 161 | 
            +
                        backupCount=backup_count
         | 
| 162 | 
            +
                    )
         | 
| 163 | 
            +
                    
         | 
| 164 | 
            +
                    formatter = logging.Formatter(
         | 
| 165 | 
            +
                        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
         | 
| 166 | 
            +
                    )
         | 
| 167 | 
            +
                    handler.setFormatter(formatter)
         | 
| 168 | 
            +
                    
         | 
| 169 | 
            +
                    self._log_handlers.append(handler)
         | 
| 170 | 
            +
                    logging.getLogger().addHandler(handler)
         | 
| 171 | 
            +
                
         | 
| 172 | 
            +
                def _setup_structured_logging(self) -> None:
         | 
| 173 | 
            +
                    """Set up structured JSON logging."""
         | 
| 174 | 
            +
                    import logging.config
         | 
| 175 | 
            +
                    
         | 
| 176 | 
            +
                    config = {
         | 
| 177 | 
            +
                        'version': 1,
         | 
| 178 | 
            +
                        'disable_existing_loggers': False,
         | 
| 179 | 
            +
                        'formatters': {
         | 
| 180 | 
            +
                            'json': {
         | 
| 181 | 
            +
                                'class': 'pythonjsonlogger.jsonlogger.JsonFormatter',
         | 
| 182 | 
            +
                                'format': '%(asctime)s %(name)s %(levelname)s %(message)s'
         | 
| 183 | 
            +
                            }
         | 
| 184 | 
            +
                        },
         | 
| 185 | 
            +
                        'handlers': {
         | 
| 186 | 
            +
                            'json_file': {
         | 
| 187 | 
            +
                                'class': 'logging.FileHandler',
         | 
| 188 | 
            +
                                'filename': str(self.log_dir / 'structured.json'),
         | 
| 189 | 
            +
                                'formatter': 'json'
         | 
| 190 | 
            +
                            }
         | 
| 191 | 
            +
                        },
         | 
| 192 | 
            +
                        'root': {
         | 
| 193 | 
            +
                            'handlers': ['json_file'],
         | 
| 194 | 
            +
                            'level': self.log_level
         | 
| 195 | 
            +
                        }
         | 
| 196 | 
            +
                    }
         | 
| 197 | 
            +
                    
         | 
| 198 | 
            +
                    try:
         | 
| 199 | 
            +
                        logging.config.dictConfig(config)
         | 
| 200 | 
            +
                    except ImportError:
         | 
| 201 | 
            +
                        # If pythonjsonlogger is not available, fall back to regular logging
         | 
| 202 | 
            +
                        self.log_warning("pythonjsonlogger not available, using standard logging")
         |