claude-mpm 4.1.8__py3-none-any.whl → 4.1.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/INSTRUCTIONS.md +26 -1
  3. claude_mpm/agents/agents_metadata.py +57 -0
  4. claude_mpm/agents/templates/.claude-mpm/memories/README.md +17 -0
  5. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +3 -0
  6. claude_mpm/agents/templates/agent-manager.json +263 -17
  7. claude_mpm/agents/templates/agentic_coder_optimizer.json +222 -0
  8. claude_mpm/agents/templates/code_analyzer.json +18 -8
  9. claude_mpm/agents/templates/engineer.json +1 -1
  10. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +39 -0
  11. claude_mpm/agents/templates/qa.json +1 -1
  12. claude_mpm/agents/templates/research.json +1 -1
  13. claude_mpm/cli/__init__.py +15 -0
  14. claude_mpm/cli/commands/__init__.py +6 -0
  15. claude_mpm/cli/commands/analyze.py +548 -0
  16. claude_mpm/cli/commands/analyze_code.py +524 -0
  17. claude_mpm/cli/commands/configure.py +78 -28
  18. claude_mpm/cli/commands/configure_tui.py +62 -60
  19. claude_mpm/cli/commands/dashboard.py +288 -0
  20. claude_mpm/cli/commands/debug.py +1386 -0
  21. claude_mpm/cli/commands/mpm_init.py +427 -0
  22. claude_mpm/cli/commands/mpm_init_handler.py +83 -0
  23. claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
  24. claude_mpm/cli/parsers/analyze_parser.py +135 -0
  25. claude_mpm/cli/parsers/base_parser.py +44 -0
  26. claude_mpm/cli/parsers/dashboard_parser.py +113 -0
  27. claude_mpm/cli/parsers/debug_parser.py +319 -0
  28. claude_mpm/cli/parsers/mpm_init_parser.py +122 -0
  29. claude_mpm/constants.py +13 -1
  30. claude_mpm/core/framework_loader.py +148 -6
  31. claude_mpm/core/log_manager.py +16 -13
  32. claude_mpm/core/logger.py +1 -1
  33. claude_mpm/core/unified_agent_registry.py +1 -1
  34. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +1 -0
  35. claude_mpm/dashboard/analysis_runner.py +455 -0
  36. claude_mpm/dashboard/static/built/components/activity-tree.js +2 -0
  37. claude_mpm/dashboard/static/built/components/agent-inference.js +1 -1
  38. claude_mpm/dashboard/static/built/components/code-tree.js +2 -0
  39. claude_mpm/dashboard/static/built/components/code-viewer.js +2 -0
  40. claude_mpm/dashboard/static/built/components/event-viewer.js +1 -1
  41. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +1 -1
  42. claude_mpm/dashboard/static/built/components/module-viewer.js +1 -1
  43. claude_mpm/dashboard/static/built/components/session-manager.js +1 -1
  44. claude_mpm/dashboard/static/built/components/working-directory.js +1 -1
  45. claude_mpm/dashboard/static/built/dashboard.js +1 -1
  46. claude_mpm/dashboard/static/built/socket-client.js +1 -1
  47. claude_mpm/dashboard/static/css/activity.css +549 -0
  48. claude_mpm/dashboard/static/css/code-tree.css +1175 -0
  49. claude_mpm/dashboard/static/css/dashboard.css +245 -0
  50. claude_mpm/dashboard/static/dist/components/activity-tree.js +2 -0
  51. claude_mpm/dashboard/static/dist/components/code-tree.js +2 -0
  52. claude_mpm/dashboard/static/dist/components/code-viewer.js +2 -0
  53. claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
  54. claude_mpm/dashboard/static/dist/components/session-manager.js +1 -1
  55. claude_mpm/dashboard/static/dist/components/working-directory.js +1 -1
  56. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  57. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  58. claude_mpm/dashboard/static/js/components/activity-tree.js +1338 -0
  59. claude_mpm/dashboard/static/js/components/code-tree.js +2535 -0
  60. claude_mpm/dashboard/static/js/components/code-viewer.js +480 -0
  61. claude_mpm/dashboard/static/js/components/event-viewer.js +59 -9
  62. claude_mpm/dashboard/static/js/components/session-manager.js +40 -4
  63. claude_mpm/dashboard/static/js/components/socket-manager.js +12 -0
  64. claude_mpm/dashboard/static/js/components/ui-state-manager.js +4 -0
  65. claude_mpm/dashboard/static/js/components/working-directory.js +17 -1
  66. claude_mpm/dashboard/static/js/dashboard.js +51 -0
  67. claude_mpm/dashboard/static/js/socket-client.js +465 -29
  68. claude_mpm/dashboard/templates/index.html +182 -4
  69. claude_mpm/hooks/claude_hooks/hook_handler.py +182 -5
  70. claude_mpm/hooks/claude_hooks/installer.py +386 -113
  71. claude_mpm/scripts/claude-hook-handler.sh +161 -0
  72. claude_mpm/scripts/socketio_daemon.py +121 -8
  73. claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +2 -2
  74. claude_mpm/services/agents/deployment/agent_record_service.py +1 -2
  75. claude_mpm/services/agents/memory/memory_format_service.py +1 -3
  76. claude_mpm/services/cli/agent_cleanup_service.py +1 -5
  77. claude_mpm/services/cli/agent_dependency_service.py +1 -1
  78. claude_mpm/services/cli/agent_validation_service.py +3 -4
  79. claude_mpm/services/cli/dashboard_launcher.py +2 -3
  80. claude_mpm/services/cli/startup_checker.py +0 -11
  81. claude_mpm/services/core/cache_manager.py +1 -3
  82. claude_mpm/services/core/path_resolver.py +1 -4
  83. claude_mpm/services/core/service_container.py +2 -2
  84. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  85. claude_mpm/services/infrastructure/monitoring/__init__.py +11 -11
  86. claude_mpm/services/infrastructure/monitoring.py +11 -11
  87. claude_mpm/services/project/architecture_analyzer.py +1 -1
  88. claude_mpm/services/project/dependency_analyzer.py +4 -4
  89. claude_mpm/services/project/language_analyzer.py +3 -3
  90. claude_mpm/services/project/metrics_collector.py +3 -6
  91. claude_mpm/services/socketio/event_normalizer.py +64 -0
  92. claude_mpm/services/socketio/handlers/__init__.py +2 -0
  93. claude_mpm/services/socketio/handlers/code_analysis.py +672 -0
  94. claude_mpm/services/socketio/handlers/registry.py +2 -0
  95. claude_mpm/services/socketio/server/connection_manager.py +6 -4
  96. claude_mpm/services/socketio/server/core.py +100 -11
  97. claude_mpm/services/socketio/server/main.py +8 -2
  98. claude_mpm/services/visualization/__init__.py +19 -0
  99. claude_mpm/services/visualization/mermaid_generator.py +938 -0
  100. claude_mpm/tools/__main__.py +208 -0
  101. claude_mpm/tools/code_tree_analyzer.py +1596 -0
  102. claude_mpm/tools/code_tree_builder.py +631 -0
  103. claude_mpm/tools/code_tree_events.py +416 -0
  104. claude_mpm/tools/socketio_debug.py +671 -0
  105. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.11.dist-info}/METADATA +2 -1
  106. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.11.dist-info}/RECORD +110 -74
  107. claude_mpm/agents/schema/agent_schema.json +0 -314
  108. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.11.dist-info}/WHEEL +0 -0
  109. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.11.dist-info}/entry_points.txt +0 -0
  110. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.11.dist-info}/licenses/LICENSE +0 -0
  111. {claude_mpm-4.1.8.dist-info → claude_mpm-4.1.11.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,161 @@
1
+ #!/bin/bash
2
+ #
3
+ # Claude MPM Hook Handler Entry Point Script
4
+ #
5
+ # OVERVIEW:
6
+ # This script serves as the bridge between Claude Code hook system and the Python-based
7
+ # Claude MPM hook handler. It is executed directly by Claude Code when events occur
8
+ # and ensures proper environment setup before delegating to the Python handler.
9
+ #
10
+ # ARCHITECTURE:
11
+ # Claude Code → This Script → Python Environment → hook_handler.py → Socket.IO/EventBus
12
+ #
13
+ # KEY RESPONSIBILITIES:
14
+ # - Virtual environment detection and activation
15
+ # - Python executable resolution with fallbacks
16
+ # - Error handling and logging for troubleshooting
17
+ # - Path resolution for cross-platform compatibility
18
+ # - Environment variable propagation
19
+ #
20
+ # DEPLOYMENT:
21
+ # This script is deployed to Claude Code's hooks directory during installation.
22
+ # Location: ~/.claude/hooks/claude-mpm/claude-hook-handler.sh
23
+ # Permissions: Must be executable (chmod +x)
24
+ #
25
+ # ENVIRONMENT VARIABLES:
26
+ # - CLAUDE_MPM_HOOK_DEBUG: Enable debug logging to /tmp/claude-mpm-hook.log
27
+ # - CLAUDE_MPM_ROOT: Override project root detection
28
+ # - VIRTUAL_ENV: Standard virtual environment variable
29
+ # - PYTHONPATH: Extended with src/ directory for imports
30
+ #
31
+ # PERFORMANCE CONSIDERATIONS:
32
+ # - Minimal shell operations to reduce latency (~10ms overhead)
33
+ # - Cached virtual environment detection
34
+ # - Early exit on errors to prevent hanging
35
+ # - Lightweight logging for debugging without performance impact
36
+ #
37
+ # SECURITY:
38
+ # - Restricts Python execution to project virtual environments
39
+ # - Validates paths before execution
40
+ # - No external network access or privileged operations
41
+ # - Logs to temporary files only (no persistent sensitive data)
42
+ #
43
+ # TROUBLESHOOTING:
44
+ # Enable debug logging: export CLAUDE_MPM_HOOK_DEBUG=true
45
+ # Check permissions: ls -la ~/.claude/hooks/claude-mpm/claude-hook-handler.sh
46
+ # Test manually: echo '{"test": "data"}' | ./claude-hook-handler.sh
47
+ #
48
+ # GOTCHAS:
49
+ # - Must activate virtual environment in same shell process
50
+ # - Path resolution differs between development and installed environments
51
+ # - Claude Code passes event data via stdin (not command line arguments)
52
+ # - Exit codes must be 0 for success, non-zero indicates failure to Claude Code
53
+ #
54
+ # @author Claude MPM Development Team
55
+ # @version 1.0
56
+ # @since v4.0.25
57
+
58
+ # Exit on any error
59
+ set -e
60
+
61
+ # Get the directory where this script is located
62
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
63
+
64
+ # Determine the claude-mpm root
65
+ # The script is at src/claude_mpm/scripts/, so we go up 3 levels
66
+ CLAUDE_MPM_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
67
+
68
+ # Debug logging (can be enabled via environment variable)
69
+ if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
70
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Claude hook handler starting..." >> /tmp/claude-mpm-hook.log
71
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Script dir: $SCRIPT_DIR" >> /tmp/claude-mpm-hook.log
72
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Claude MPM root: $CLAUDE_MPM_ROOT" >> /tmp/claude-mpm-hook.log
73
+ fi
74
+
75
+ #
76
+ # Find and return the appropriate Python executable for hook processing.
77
+ #
78
+ # STRATEGY:
79
+ # This function implements a fallback chain to find Python with claude-mpm dependencies:
80
+ # 1. Project-specific virtual environments (venv, .venv)
81
+ # 2. Currently active virtual environment ($VIRTUAL_ENV)
82
+ # 3. System python3 (may lack dependencies)
83
+ # 4. System python (last resort)
84
+ #
85
+ # WHY THIS APPROACH:
86
+ # - Claude MPM requires specific packages (socketio, eventlet) not in system Python
87
+ # - Virtual environments ensure dependency isolation and availability
88
+ # - Multiple naming conventions supported (venv vs .venv)
89
+ # - Graceful degradation to system Python if no venv found
90
+ #
91
+ # ACTIVATION STRATEGY:
92
+ # - Sources activate script to set up environment variables
93
+ # - Returns specific Python path for exec (not just 'python')
94
+ # - Maintains environment in same shell process
95
+ #
96
+ # PERFORMANCE:
97
+ # - Fast path detection using file existence checks
98
+ # - Early returns to minimize overhead
99
+ # - Caches result in process environment
100
+ #
101
+ # RETURNS:
102
+ # Absolute path to Python executable with claude-mpm dependencies
103
+ #
104
+ find_python_command() {
105
+ # 1. Check for project-local virtual environment (common in development)
106
+ if [ -f "$CLAUDE_MPM_ROOT/venv/bin/activate" ]; then
107
+ source "$CLAUDE_MPM_ROOT/venv/bin/activate"
108
+ echo "$CLAUDE_MPM_ROOT/venv/bin/python"
109
+ elif [ -f "$CLAUDE_MPM_ROOT/.venv/bin/activate" ]; then
110
+ source "$CLAUDE_MPM_ROOT/.venv/bin/activate"
111
+ echo "$CLAUDE_MPM_ROOT/.venv/bin/python"
112
+ elif [ -n "$VIRTUAL_ENV" ]; then
113
+ # Already in a virtual environment
114
+ echo "$VIRTUAL_ENV/bin/python"
115
+ elif command -v python3 &> /dev/null; then
116
+ echo "python3"
117
+ else
118
+ echo "python"
119
+ fi
120
+ }
121
+
122
+ # Set up Python command
123
+ PYTHON_CMD=$(find_python_command)
124
+
125
+ # Check if we're in a development environment (has src directory)
126
+ if [ -d "$CLAUDE_MPM_ROOT/src" ]; then
127
+ # Development install - add src to PYTHONPATH
128
+ export PYTHONPATH="$CLAUDE_MPM_ROOT/src:$PYTHONPATH"
129
+
130
+ if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
131
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Development environment detected" >> /tmp/claude-mpm-hook.log
132
+ fi
133
+ else
134
+ # Pip install - claude_mpm should be in site-packages
135
+ # No need to modify PYTHONPATH
136
+ if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
137
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Pip installation detected" >> /tmp/claude-mpm-hook.log
138
+ fi
139
+ fi
140
+
141
+ # Debug logging
142
+ if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
143
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] PYTHON_CMD: $PYTHON_CMD" >> /tmp/claude-mpm-hook.log
144
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] PYTHONPATH: $PYTHONPATH" >> /tmp/claude-mpm-hook.log
145
+ fi
146
+
147
+ # Set Socket.IO configuration for hook events
148
+ export CLAUDE_MPM_SOCKETIO_PORT="${CLAUDE_MPM_SOCKETIO_PORT:-8765}"
149
+
150
+ # Run the Python hook handler with all input
151
+ # Use exec to replace the shell process with Python
152
+ if ! exec "$PYTHON_CMD" -m claude_mpm.hooks.claude_hooks.hook_handler "$@" 2>/tmp/claude-mpm-hook-error.log; then
153
+ # If the Python handler fails, always return continue to not block Claude
154
+ if [ "${CLAUDE_MPM_HOOK_DEBUG}" = "true" ]; then
155
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Hook handler failed, see /tmp/claude-mpm-hook-error.log" >> /tmp/claude-mpm-hook.log
156
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)] Error: $(cat /tmp/claude-mpm-hook-error.log 2>/dev/null | head -5)" >> /tmp/claude-mpm-hook.log
157
+ fi
158
+ # Return continue action to prevent blocking Claude Code
159
+ echo '{"action": "continue"}'
160
+ exit 0
161
+ fi
@@ -1,7 +1,45 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- Pure Python daemon management for Socket.IO server.
4
- No external dependencies required.
3
+ Socket.IO Daemon Management for Claude MPM.
4
+
5
+ This module provides pure Python daemon management for the Claude MPM Socket.IO server
6
+ without requiring external process management dependencies. It handles server lifecycle,
7
+ process detection, and virtual environment discovery.
8
+
9
+ Key Features:
10
+ - Pure Python implementation (no external deps)
11
+ - Virtual environment auto-detection
12
+ - Process management with PID tracking
13
+ - Signal handling for clean shutdown
14
+ - Port availability checking
15
+ - Background daemon execution
16
+
17
+ Architecture:
18
+ - Uses subprocess for server execution
19
+ - Implements daemon pattern with double-fork
20
+ - Maintains PID files for process tracking
21
+ - Auto-detects Python environment (venv/conda)
22
+
23
+ Thread Safety:
24
+ - Signal handlers are async-signal-safe
25
+ - PID file operations use atomic writes
26
+ - Process checks use system-level primitives
27
+
28
+ Performance Considerations:
29
+ - Minimal memory footprint for daemon mode
30
+ - Fast process detection using PID files
31
+ - Lazy loading of heavy imports
32
+ - Efficient port scanning
33
+
34
+ Security:
35
+ - Localhost-only binding for server
36
+ - PID file permissions restrict access
37
+ - Process ownership validation
38
+ - Signal handling prevents orphans
39
+
40
+ @author Claude MPM Team
41
+ @version 1.0
42
+ @since v4.0.25
5
43
  """
6
44
 
7
45
  import os
@@ -13,13 +51,45 @@ from pathlib import Path
13
51
 
14
52
 
15
53
  # Detect and use virtual environment Python if available
16
- def get_python_executable():
54
+ def get_python_executable() -> str:
17
55
  """
18
- Get the appropriate Python executable, preferring virtual environment.
19
-
20
- WHY: The daemon must use the same Python environment as the parent process
21
- to ensure all dependencies are available. System Python won't have the
22
- required packages installed.
56
+ Detect and return the appropriate Python executable for Socket.IO daemon.
57
+
58
+ Intelligently detects virtual environments (venv, conda, poetry, pipenv)
59
+ and returns the correct Python path to ensure dependency availability.
60
+
61
+ Detection Strategy:
62
+ 1. Check if already running in virtual environment
63
+ 2. Look for VIRTUAL_ENV environment variable
64
+ 3. Analyze executable path structure
65
+ 4. Search for project-specific virtual environments
66
+ 5. Fall back to system Python
67
+
68
+ WHY this complex detection:
69
+ - Socket.IO server requires specific Python packages (socketio, eventlet)
70
+ - System Python rarely has these packages installed
71
+ - Virtual environments contain isolated dependencies
72
+ - Multiple venv tools have different conventions
73
+
74
+ Thread Safety:
75
+ - Read-only operations on sys and os modules
76
+ - File system checks are atomic
77
+ - No shared state modification
78
+
79
+ Performance:
80
+ - Early returns for common cases
81
+ - Minimal file system operations
82
+ - Cached in practice by Python import system
83
+
84
+ Returns:
85
+ str: Path to Python executable with required dependencies
86
+
87
+ Raises:
88
+ FileNotFoundError: If no suitable Python executable found
89
+
90
+ Examples:
91
+ >>> python_path = get_python_executable()
92
+ >>> # Returns: '/path/to/venv/bin/python' or '/usr/bin/python3'
23
93
  """
24
94
  # First, check if we're already in a virtual environment
25
95
  if hasattr(sys, "real_prefix") or (
@@ -274,6 +344,49 @@ def start_server():
274
344
  # Start server using synchronous method
275
345
  server.start_sync()
276
346
 
347
+ # Debug: Check if handlers are registered (write to file for daemon)
348
+ with open(LOG_FILE, "a") as f:
349
+ f.write(
350
+ f"\n[{time.strftime('%Y-%m-%d %H:%M:%S')}] Server started, checking handlers...\n"
351
+ )
352
+ if server.event_registry:
353
+ f.write(
354
+ f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Event registry exists with {len(server.event_registry.handlers)} handlers\n"
355
+ )
356
+ for handler in server.event_registry.handlers:
357
+ f.write(
358
+ f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] - {handler.__class__.__name__}\n"
359
+ )
360
+ else:
361
+ f.write(
362
+ f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] WARNING: No event registry found!\n"
363
+ )
364
+
365
+ # Check Socket.IO events
366
+ if server.core and server.core.sio:
367
+ handlers = getattr(server.core.sio, "handlers", {})
368
+ f.write(
369
+ f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Socket.IO has {len(handlers)} namespaces\n"
370
+ )
371
+ for namespace, events in handlers.items():
372
+ f.write(
373
+ f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Namespace '{namespace}': {len(events)} events\n"
374
+ )
375
+ # List all events to debug
376
+ event_list = list(events.keys())
377
+ f.write(
378
+ f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Events: {event_list}\n"
379
+ )
380
+ if "code:analyze:request" in events:
381
+ f.write(
382
+ f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] ✅ code:analyze:request is registered!\n"
383
+ )
384
+ else:
385
+ f.write(
386
+ f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] ❌ code:analyze:request NOT found\n"
387
+ )
388
+ f.flush()
389
+
277
390
  # Keep running
278
391
  try:
279
392
  while True:
@@ -141,7 +141,7 @@ class AgentLifecycleManager(BaseService):
141
141
  records = await self.record_service.load_records()
142
142
  self.state_service.agent_records = records
143
143
 
144
- history = await self.record_service.load_history()
144
+ await self.record_service.load_history()
145
145
  # Convert history back to operation results if needed
146
146
  # For now, we'll start with empty history
147
147
 
@@ -299,7 +299,7 @@ class AgentLifecycleManager(BaseService):
299
299
  # Update state if successful
300
300
  if result.success:
301
301
  # Create state record
302
- record = self.state_service.create_record(
302
+ self.state_service.create_record(
303
303
  agent_name=agent_name,
304
304
  tier=tier,
305
305
  file_path=result.metadata.get("file_path", ""),
@@ -217,7 +217,7 @@ class AgentRecordService(BaseService):
217
217
  Returns:
218
218
  Deserialized AgentLifecycleRecord
219
219
  """
220
- record = AgentLifecycleRecord(
220
+ return AgentLifecycleRecord(
221
221
  agent_name=data["agent_name"],
222
222
  current_state=LifecycleState(data["current_state"]),
223
223
  tier=ModificationTier(data["tier"]),
@@ -232,7 +232,6 @@ class AgentRecordService(BaseService):
232
232
  validation_errors=data.get("validation_errors", []),
233
233
  metadata=data.get("metadata", {}),
234
234
  )
235
- return record
236
235
 
237
236
  async def export_records(self, output_path: Path, format: str = "json") -> bool:
238
237
  """
@@ -63,9 +63,7 @@ class MemoryFormatService:
63
63
  # Skip headers, empty lines, and metadata
64
64
  if (
65
65
  not line
66
- or line.startswith("#")
67
- or line.startswith("Last Updated:")
68
- or line.startswith("**")
66
+ or line.startswith(("#", "Last Updated:", "**"))
69
67
  or line == "---"
70
68
  ):
71
69
  continue
@@ -233,11 +233,7 @@ class AgentCleanupService(IAgentCleanupService):
233
233
  all_agents = multi_source_service.discover_agents_from_all_sources()
234
234
 
235
235
  # Detect orphaned agents
236
- orphaned = multi_source_service.detect_orphaned_agents(
237
- agents_dir, all_agents
238
- )
239
-
240
- return orphaned
236
+ return multi_source_service.detect_orphaned_agents(agents_dir, all_agents)
241
237
 
242
238
  except Exception as e:
243
239
  self.logger.error(f"Error finding orphaned agents: {e}", exc_info=True)
@@ -225,7 +225,7 @@ class AgentDependencyService(IAgentDependencyService):
225
225
  all_python_deps = set()
226
226
  all_system_deps = set()
227
227
 
228
- for agent_id, deps in loader.agent_dependencies.items():
228
+ for _agent_id, deps in loader.agent_dependencies.items():
229
229
  if "python" in deps:
230
230
  all_python_deps.update(deps["python"])
231
231
  if "system" in deps:
@@ -324,10 +324,9 @@ class AgentValidationService(IAgentValidationService):
324
324
  if fix_result.warnings:
325
325
  total_issues += len(fix_result.warnings)
326
326
 
327
- if fix_result.corrections:
328
- if not dry_run:
329
- total_fixed += len(fix_result.corrections)
330
- agents_fixed.append(agent_id)
327
+ if fix_result.corrections and not dry_run:
328
+ total_fixed += len(fix_result.corrections)
329
+ agents_fixed.append(agent_id)
331
330
 
332
331
  return {
333
332
  "success": True,
@@ -134,9 +134,8 @@ class DashboardLauncher(IDashboardLauncher):
134
134
  """
135
135
  try:
136
136
  # Verify dependencies for Socket.IO dashboard
137
- if monitor_mode:
138
- if not self._verify_socketio_dependencies():
139
- return False, False
137
+ if monitor_mode and not self._verify_socketio_dependencies():
138
+ return False, False
140
139
 
141
140
  self.logger.info(
142
141
  f"Launching dashboard (port: {port}, monitor: {monitor_mode})"
@@ -176,17 +176,6 @@ class StartupCheckerService(IStartupChecker):
176
176
 
177
177
  try:
178
178
  # Check Python version
179
- import sys
180
-
181
- if sys.version_info < (3, 8):
182
- warnings.append(
183
- StartupWarning(
184
- category="environment",
185
- message=f"Python {sys.version_info.major}.{sys.version_info.minor} detected",
186
- suggestion="Python 3.8+ is recommended for optimal performance",
187
- severity="info",
188
- )
189
- )
190
179
 
191
180
  # Check for common missing directories
192
181
  warnings.extend(self._check_required_directories())
@@ -253,7 +253,7 @@ class CacheManager(ICacheManager):
253
253
  with self._lock:
254
254
  current_time = time.time()
255
255
 
256
- stats = {
256
+ return {
257
257
  "capabilities": {
258
258
  "cached": self._capabilities_cache is not None,
259
259
  "age": (
@@ -307,5 +307,3 @@ class CacheManager(ICacheManager):
307
307
  },
308
308
  "fs_cache": self._fs_cache.get_stats() if self._fs_cache else {},
309
309
  }
310
-
311
- return stats
@@ -91,10 +91,7 @@ class PathResolver(IPathResolver):
91
91
  resolved = path.resolve()
92
92
 
93
93
  # Check if path exists if required
94
- if must_exist and not resolved.exists():
95
- return False
96
-
97
- return True
94
+ return not (must_exist and not resolved.exists())
98
95
  except (OSError, ValueError):
99
96
  return False
100
97
 
@@ -244,7 +244,7 @@ class ServiceContainer:
244
244
 
245
245
  # Check for circular dependencies
246
246
  if service_type in self._resolution_stack.stack:
247
- raise CircularDependencyError(self._resolution_stack.stack + [service_type])
247
+ raise CircularDependencyError([*self._resolution_stack.stack, service_type])
248
248
 
249
249
  try:
250
250
  # Add to resolution stack
@@ -287,7 +287,7 @@ class ServiceContainer:
287
287
  results = []
288
288
 
289
289
  with self._lock:
290
- for registered_type, descriptor in self._services.items():
290
+ for registered_type, _descriptor in self._services.items():
291
291
  # Check if registered type is subclass of requested type
292
292
  if self._is_assignable(registered_type, service_type):
293
293
  try:
@@ -197,7 +197,6 @@ class InstructionsCheck(BaseDiagnosticCheck):
197
197
  )
198
198
 
199
199
  # Calculate content hashes
200
- content_hashes = {}
201
200
  content_snippets = defaultdict(list)
202
201
 
203
202
  for path in files:
@@ -265,7 +264,7 @@ class InstructionsCheck(BaseDiagnosticCheck):
265
264
  for description, occurrences in pattern_occurrences.items():
266
265
  if len(occurrences) > 1:
267
266
  files_info = []
268
- for path, count, snippet in occurrences:
267
+ for path, count, _snippet in occurrences:
269
268
  rel_path = (
270
269
  path.relative_to(Path.cwd())
271
270
  if Path.cwd() in path.parents or path.parent == Path.cwd()
@@ -24,20 +24,20 @@ from .resources import ResourceMonitorService
24
24
  from .service import ServiceHealthService
25
25
 
26
26
  __all__ = [
27
- # New service-based API
28
- "ResourceMonitorService",
29
- "ProcessHealthService",
30
- "ServiceHealthService",
31
- "NetworkHealthService",
32
- "MonitoringAggregatorService",
33
- # Base components
34
- "HealthStatus",
35
- "HealthMetric",
27
+ "AdvancedHealthMonitor",
36
28
  "HealthCheckResult",
37
29
  "HealthChecker",
30
+ "HealthMetric",
31
+ # Base components
32
+ "HealthStatus",
33
+ "MonitoringAggregatorService",
34
+ "NetworkConnectivityChecker",
35
+ "NetworkHealthService",
36
+ "ProcessHealthService",
38
37
  # Legacy compatibility
39
38
  "ProcessResourceChecker",
40
- "NetworkConnectivityChecker",
39
+ # New service-based API
40
+ "ResourceMonitorService",
41
41
  "ServiceHealthChecker",
42
- "AdvancedHealthMonitor",
42
+ "ServiceHealthService",
43
43
  ]
@@ -47,22 +47,22 @@ from .monitoring import ( # noqa: F401; New service-based API; Base components;
47
47
  )
48
48
 
49
49
  __all__ = [
50
- # New service-based API
51
- "ResourceMonitorService",
52
- "ProcessHealthService",
53
- "ServiceHealthService",
54
- "NetworkHealthService",
55
- "MonitoringAggregatorService",
56
- # Base components
57
- "HealthStatus",
58
- "HealthMetric",
50
+ "AdvancedHealthMonitor",
59
51
  "HealthCheckResult",
60
52
  "HealthChecker",
53
+ "HealthMetric",
54
+ # Base components
55
+ "HealthStatus",
56
+ "MonitoringAggregatorService",
57
+ "NetworkConnectivityChecker",
58
+ "NetworkHealthService",
59
+ "ProcessHealthService",
61
60
  # Legacy compatibility
62
61
  "ProcessResourceChecker",
63
- "NetworkConnectivityChecker",
62
+ # New service-based API
63
+ "ResourceMonitorService",
64
64
  "ServiceHealthChecker",
65
- "AdvancedHealthMonitor",
65
+ "ServiceHealthService",
66
66
  ]
67
67
 
68
68
  # Module metadata
@@ -224,7 +224,7 @@ class ArchitectureAnalyzerService:
224
224
  existing_dirs = set()
225
225
 
226
226
  # Collect all directory names
227
- for dirpath, dirnames, _ in self.working_directory.walk():
227
+ for _dirpath, dirnames, _ in self.working_directory.walk():
228
228
  for dirname in dirnames:
229
229
  if not dirname.startswith("."):
230
230
  existing_dirs.add(dirname.lower())
@@ -171,7 +171,7 @@ class DependencyAnalyzerService:
171
171
  if any(pkg in dep_lower for pkg in db_packages):
172
172
  databases.add(db_name)
173
173
 
174
- return sorted(list(databases))
174
+ return sorted(databases)
175
175
 
176
176
  def detect_testing_frameworks(
177
177
  self, dependencies: Optional[List[str]] = None
@@ -201,7 +201,7 @@ class DependencyAnalyzerService:
201
201
  testing_frameworks.add(dep)
202
202
  break
203
203
 
204
- return sorted(list(testing_frameworks))
204
+ return sorted(testing_frameworks)
205
205
 
206
206
  def detect_web_frameworks(self, dependencies: List[str]) -> List[str]:
207
207
  """Detect web frameworks from dependencies.
@@ -343,7 +343,7 @@ class DependencyAnalyzerService:
343
343
  for dep in all_deps:
344
344
  dep_lower = dep.lower()
345
345
  # Check for database packages
346
- for db_name, db_packages in self.DATABASE_PACKAGES.items():
346
+ for _db_name, db_packages in self.DATABASE_PACKAGES.items():
347
347
  if any(pkg in dep_lower for pkg in db_packages):
348
348
  dependencies["databases"].append(dep)
349
349
 
@@ -407,7 +407,7 @@ class DependencyAnalyzerService:
407
407
  dep_lower = dep.lower()
408
408
 
409
409
  # Check databases
410
- for db_name, db_packages in self.DATABASE_PACKAGES.items():
410
+ for _db_name, db_packages in self.DATABASE_PACKAGES.items():
411
411
  if any(pkg in dep_lower for pkg in db_packages):
412
412
  dependencies["databases"].append(dep)
413
413
 
@@ -109,7 +109,7 @@ class LanguageAnalyzerService:
109
109
  if files:
110
110
  languages.add(lang)
111
111
 
112
- return sorted(list(languages))
112
+ return sorted(languages)
113
113
 
114
114
  def detect_primary_language(
115
115
  self, file_counts: Optional[Dict[str, int]] = None
@@ -229,7 +229,7 @@ class LanguageAnalyzerService:
229
229
  """Count files by extension in the project."""
230
230
  counts = Counter()
231
231
 
232
- for ext in self.FILE_EXTENSIONS.keys():
232
+ for ext in self.FILE_EXTENSIONS:
233
233
  files = list(self.working_directory.rglob(f"*{ext}"))
234
234
  # Filter out vendor directories
235
235
  files = [
@@ -249,7 +249,7 @@ class LanguageAnalyzerService:
249
249
  """Get a sample of source files for analysis."""
250
250
  source_files = []
251
251
 
252
- for ext in self.FILE_EXTENSIONS.keys():
252
+ for ext in self.FILE_EXTENSIONS:
253
253
  files = list(self.working_directory.rglob(f"*{ext}"))
254
254
  # Filter out vendor directories
255
255
  files = [
@@ -166,7 +166,7 @@ class MetricsCollectorService:
166
166
 
167
167
  for file_path in self._iter_code_files():
168
168
  try:
169
- size = file_path.stat().st_size
169
+ file_path.stat().st_size
170
170
  lines = len(
171
171
  file_path.read_text(encoding="utf-8", errors="ignore").splitlines()
172
172
  )
@@ -377,7 +377,7 @@ class MetricsCollectorService:
377
377
 
378
378
  # Count directories
379
379
  dir_count = 0
380
- for dirpath, dirnames, _ in self.working_directory.walk():
380
+ for _dirpath, dirnames, _ in self.working_directory.walk():
381
381
  dirnames[:] = [d for d in dirnames if d not in self.EXCLUDE_DIRS]
382
382
  dir_count += len(dirnames)
383
383
 
@@ -404,7 +404,4 @@ class MetricsCollectorService:
404
404
  def _should_analyze_file(self, file_path: Path) -> bool:
405
405
  """Check if a file should be analyzed."""
406
406
  # Skip files in excluded directories
407
- for part in file_path.parts:
408
- if part in self.EXCLUDE_DIRS:
409
- return False
410
- return True
407
+ return all(part not in self.EXCLUDE_DIRS for part in file_path.parts)