claude-mpm 4.0.32__py3-none-any.whl → 4.1.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.
Files changed (82) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/INSTRUCTIONS.md +70 -2
  3. claude_mpm/agents/OUTPUT_STYLE.md +0 -11
  4. claude_mpm/agents/WORKFLOW.md +14 -2
  5. claude_mpm/agents/templates/documentation.json +51 -34
  6. claude_mpm/agents/templates/research.json +0 -11
  7. claude_mpm/cli/__init__.py +111 -33
  8. claude_mpm/cli/commands/agent_manager.py +10 -8
  9. claude_mpm/cli/commands/agents.py +82 -0
  10. claude_mpm/cli/commands/cleanup_orphaned_agents.py +150 -0
  11. claude_mpm/cli/commands/mcp_pipx_config.py +199 -0
  12. claude_mpm/cli/parsers/agents_parser.py +27 -0
  13. claude_mpm/cli/parsers/base_parser.py +6 -0
  14. claude_mpm/cli/startup_logging.py +75 -0
  15. claude_mpm/core/framework_loader.py +173 -84
  16. claude_mpm/dashboard/static/css/dashboard.css +449 -0
  17. claude_mpm/dashboard/static/dist/components/agent-inference.js +1 -1
  18. claude_mpm/dashboard/static/dist/components/event-viewer.js +1 -1
  19. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +1 -1
  20. claude_mpm/dashboard/static/dist/components/module-viewer.js +1 -1
  21. claude_mpm/dashboard/static/dist/components/session-manager.js +1 -1
  22. claude_mpm/dashboard/static/dist/dashboard.js +1 -1
  23. claude_mpm/dashboard/static/dist/socket-client.js +1 -1
  24. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +774 -0
  25. claude_mpm/dashboard/static/js/components/agent-inference.js +257 -3
  26. claude_mpm/dashboard/static/js/components/build-tracker.js +323 -0
  27. claude_mpm/dashboard/static/js/components/event-viewer.js +168 -39
  28. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +17 -0
  29. claude_mpm/dashboard/static/js/components/session-manager.js +23 -3
  30. claude_mpm/dashboard/static/js/components/socket-manager.js +2 -0
  31. claude_mpm/dashboard/static/js/dashboard.js +207 -31
  32. claude_mpm/dashboard/static/js/socket-client.js +92 -11
  33. claude_mpm/dashboard/templates/index.html +1 -0
  34. claude_mpm/hooks/claude_hooks/connection_pool.py +25 -4
  35. claude_mpm/hooks/claude_hooks/event_handlers.py +81 -19
  36. claude_mpm/hooks/claude_hooks/hook_handler.py +125 -163
  37. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +398 -0
  38. claude_mpm/hooks/claude_hooks/response_tracking.py +10 -0
  39. claude_mpm/services/agents/deployment/agent_deployment.py +34 -48
  40. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -1
  41. claude_mpm/services/agents/deployment/agent_template_builder.py +20 -11
  42. claude_mpm/services/agents/deployment/agent_version_manager.py +4 -1
  43. claude_mpm/services/agents/deployment/agents_directory_resolver.py +10 -25
  44. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +396 -13
  45. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +3 -2
  46. claude_mpm/services/agents/deployment/strategies/system_strategy.py +10 -3
  47. claude_mpm/services/agents/deployment/strategies/user_strategy.py +10 -14
  48. claude_mpm/services/agents/deployment/system_instructions_deployer.py +8 -85
  49. claude_mpm/services/agents/memory/content_manager.py +98 -105
  50. claude_mpm/services/event_bus/__init__.py +18 -0
  51. claude_mpm/services/event_bus/config.py +165 -0
  52. claude_mpm/services/event_bus/event_bus.py +349 -0
  53. claude_mpm/services/event_bus/relay.py +297 -0
  54. claude_mpm/services/events/__init__.py +44 -0
  55. claude_mpm/services/events/consumers/__init__.py +18 -0
  56. claude_mpm/services/events/consumers/dead_letter.py +296 -0
  57. claude_mpm/services/events/consumers/logging.py +183 -0
  58. claude_mpm/services/events/consumers/metrics.py +242 -0
  59. claude_mpm/services/events/consumers/socketio.py +376 -0
  60. claude_mpm/services/events/core.py +470 -0
  61. claude_mpm/services/events/interfaces.py +230 -0
  62. claude_mpm/services/events/producers/__init__.py +14 -0
  63. claude_mpm/services/events/producers/hook.py +269 -0
  64. claude_mpm/services/events/producers/system.py +327 -0
  65. claude_mpm/services/mcp_gateway/auto_configure.py +372 -0
  66. claude_mpm/services/mcp_gateway/core/process_pool.py +411 -0
  67. claude_mpm/services/mcp_gateway/server/stdio_server.py +13 -0
  68. claude_mpm/services/monitor_build_service.py +345 -0
  69. claude_mpm/services/socketio/event_normalizer.py +667 -0
  70. claude_mpm/services/socketio/handlers/connection.py +81 -23
  71. claude_mpm/services/socketio/handlers/hook.py +14 -5
  72. claude_mpm/services/socketio/migration_utils.py +329 -0
  73. claude_mpm/services/socketio/server/broadcaster.py +26 -33
  74. claude_mpm/services/socketio/server/core.py +29 -5
  75. claude_mpm/services/socketio/server/eventbus_integration.py +189 -0
  76. claude_mpm/services/socketio/server/main.py +25 -0
  77. {claude_mpm-4.0.32.dist-info → claude_mpm-4.1.0.dist-info}/METADATA +28 -9
  78. {claude_mpm-4.0.32.dist-info → claude_mpm-4.1.0.dist-info}/RECORD +82 -56
  79. {claude_mpm-4.0.32.dist-info → claude_mpm-4.1.0.dist-info}/WHEEL +0 -0
  80. {claude_mpm-4.0.32.dist-info → claude_mpm-4.1.0.dist-info}/entry_points.txt +0 -0
  81. {claude_mpm-4.0.32.dist-info → claude_mpm-4.1.0.dist-info}/licenses/LICENSE +0 -0
  82. {claude_mpm-4.0.32.dist-info → claude_mpm-4.1.0.dist-info}/top_level.txt +0 -0
@@ -31,6 +31,9 @@ except ImportError:
31
31
  aiohttp = None
32
32
  web = None
33
33
 
34
+ # Import VersionService for dynamic version retrieval
35
+ from claude_mpm.services.version_service import VersionService
36
+
34
37
  from ....core.constants import (
35
38
  NetworkConfig,
36
39
  PerformanceConfig,
@@ -158,11 +161,14 @@ class SocketIOServerCore:
158
161
  async def _start_server(self):
159
162
  """Start the Socket.IO server with aiohttp."""
160
163
  try:
161
- # Create Socket.IO server
164
+ # Create Socket.IO server with proper ping/pong configuration
162
165
  self.sio = socketio.AsyncServer(
163
166
  cors_allowed_origins="*",
164
167
  logger=False, # Disable Socket.IO's own logging
165
168
  engineio_logger=False,
169
+ ping_interval=25, # Send ping every 25 seconds
170
+ ping_timeout=60, # Wait 60 seconds for pong response
171
+ max_http_buffer_size=1e8, # 100MB max buffer
166
172
  )
167
173
 
168
174
  # Create aiohttp application
@@ -255,6 +261,23 @@ class SocketIOServerCore:
255
261
  return web.Response(text="Dashboard not available", status=404)
256
262
 
257
263
  self.app.router.add_get("/", index_handler)
264
+
265
+ # Serve version.json from dashboard directory
266
+ async def version_handler(request):
267
+ version_file = self.dashboard_path / "version.json"
268
+ if version_file.exists():
269
+ self.logger.debug(f"Serving version.json from: {version_file}")
270
+ return web.FileResponse(version_file)
271
+ else:
272
+ # Return default version info if file doesn't exist
273
+ return web.json_response({
274
+ "version": "1.0.0",
275
+ "build": 1,
276
+ "formatted_build": "0001",
277
+ "full_version": "v1.0.0-0001"
278
+ })
279
+
280
+ self.app.router.add_get("/version.json", version_handler)
258
281
 
259
282
  # Serve static assets (CSS, JS) from the dashboard static directory
260
283
  dashboard_static_path = (
@@ -414,18 +437,19 @@ class SocketIOServerCore:
414
437
  except Exception as e:
415
438
  self.logger.debug(f"Could not get active sessions: {e}")
416
439
 
417
- # Prepare heartbeat data
440
+ # Prepare heartbeat data (using new schema)
418
441
  heartbeat_data = {
419
442
  "type": "system",
420
- "event": "heartbeat",
443
+ "subtype": "heartbeat",
421
444
  "timestamp": datetime.now().isoformat(),
445
+ "source": "server",
422
446
  "data": {
423
447
  "uptime_seconds": uptime_seconds,
424
448
  "connected_clients": len(self.connected_clients),
425
449
  "total_events": self.stats.get("events_sent", 0),
426
450
  "active_sessions": active_sessions,
427
451
  "server_info": {
428
- "version": "4.0.2",
452
+ "version": VersionService().get_version(),
429
453
  "port": self.port,
430
454
  },
431
455
  },
@@ -435,7 +459,7 @@ class SocketIOServerCore:
435
459
  if self.main_server and hasattr(self.main_server, 'event_history'):
436
460
  self.main_server.event_history.append(heartbeat_data)
437
461
 
438
- # Emit heartbeat to all connected clients
462
+ # Emit heartbeat to all connected clients (already using new schema)
439
463
  await self.sio.emit("system_event", heartbeat_data)
440
464
 
441
465
  self.logger.info(
@@ -0,0 +1,189 @@
1
+ """EventBus integration for Socket.IO server.
2
+
3
+ WHY this integration module:
4
+ - Adds EventBus relay to Socket.IO server without modifying core
5
+ - Maintains backward compatibility with existing server
6
+ - Easy to enable/disable via configuration
7
+ - Provides clean separation of concerns
8
+ """
9
+
10
+ import asyncio
11
+ import logging
12
+ from typing import Optional
13
+
14
+ from claude_mpm.services.event_bus import EventBus, SocketIORelay
15
+ from claude_mpm.services.event_bus.config import get_config
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class EventBusIntegration:
21
+ """Integrates EventBus relay with Socket.IO server.
22
+
23
+ WHY integration class:
24
+ - Encapsulates EventBus setup and teardown
25
+ - Provides lifecycle management for relay
26
+ - Handles configuration and error cases
27
+ - Can be easily added to existing server
28
+ """
29
+
30
+ def __init__(self, server_instance=None):
31
+ """Initialize EventBus integration.
32
+
33
+ Args:
34
+ server_instance: Optional Socket.IO server instance
35
+ """
36
+ self.server = server_instance
37
+ self.relay: Optional[SocketIORelay] = None
38
+ self.event_bus: Optional[EventBus] = None
39
+ self.config = get_config()
40
+ self.enabled = self.config.enabled and self.config.relay_enabled
41
+
42
+ def setup(self, port: Optional[int] = None) -> bool:
43
+ """Set up EventBus and relay.
44
+
45
+ Args:
46
+ port: Optional Socket.IO server port
47
+
48
+ Returns:
49
+ bool: True if setup successful
50
+ """
51
+ if not self.enabled:
52
+ logger.info("EventBus integration disabled by configuration")
53
+ return False
54
+
55
+ try:
56
+ # Get EventBus instance
57
+ self.event_bus = EventBus.get_instance()
58
+
59
+ # Apply configuration
60
+ self.config.apply_to_eventbus(self.event_bus)
61
+
62
+ # Create and configure relay
63
+ relay_port = port or self.config.relay_port
64
+ self.relay = SocketIORelay(relay_port)
65
+ self.config.apply_to_relay(self.relay)
66
+
67
+ # Start the relay
68
+ self.relay.start()
69
+
70
+ logger.info(f"EventBus integration setup complete (port: {relay_port})")
71
+ return True
72
+
73
+ except Exception as e:
74
+ logger.error(f"Failed to setup EventBus integration: {e}")
75
+ self.enabled = False
76
+ return False
77
+
78
+ def teardown(self) -> None:
79
+ """Tear down EventBus integration."""
80
+ if self.relay:
81
+ try:
82
+ self.relay.stop()
83
+ logger.info("EventBus relay stopped")
84
+ except Exception as e:
85
+ logger.error(f"Error stopping relay: {e}")
86
+ finally:
87
+ self.relay = None
88
+
89
+ def is_active(self) -> bool:
90
+ """Check if integration is active.
91
+
92
+ Returns:
93
+ bool: True if relay is active and connected
94
+ """
95
+ return (
96
+ self.enabled and
97
+ self.relay is not None and
98
+ self.relay.enabled
99
+ )
100
+
101
+ def get_stats(self) -> dict:
102
+ """Get integration statistics.
103
+
104
+ Returns:
105
+ dict: Combined stats from EventBus and relay
106
+ """
107
+ stats = {
108
+ "enabled": self.enabled,
109
+ "active": self.is_active()
110
+ }
111
+
112
+ if self.event_bus:
113
+ stats["eventbus"] = self.event_bus.get_stats()
114
+
115
+ if self.relay:
116
+ stats["relay"] = self.relay.get_stats()
117
+
118
+ return stats
119
+
120
+
121
+ def integrate_with_server(server_instance, port: Optional[int] = None) -> EventBusIntegration:
122
+ """Helper function to integrate EventBus with a Socket.IO server.
123
+
124
+ Args:
125
+ server_instance: Socket.IO server instance
126
+ port: Optional server port
127
+
128
+ Returns:
129
+ EventBusIntegration: The integration instance
130
+ """
131
+ integration = EventBusIntegration(server_instance)
132
+ integration.setup(port or getattr(server_instance, 'port', 8765))
133
+ return integration
134
+
135
+
136
+ # Monkey-patch helper for existing server
137
+ def patch_socketio_server(server_class):
138
+ """Monkey-patch an existing Socket.IO server class to add EventBus.
139
+
140
+ WHY monkey-patching:
141
+ - Allows integration without modifying existing code
142
+ - Can be applied selectively based on configuration
143
+ - Easy to remove or disable
144
+
145
+ Args:
146
+ server_class: The server class to patch
147
+ """
148
+ original_init = server_class.__init__
149
+ original_start = getattr(server_class, 'start_sync', None) or getattr(server_class, 'start', None)
150
+ original_stop = getattr(server_class, 'stop_sync', None) or getattr(server_class, 'stop', None)
151
+
152
+ def patched_init(self, *args, **kwargs):
153
+ """Patched __init__ that adds EventBus integration."""
154
+ original_init(self, *args, **kwargs)
155
+ self._eventbus_integration = EventBusIntegration(self)
156
+
157
+ def patched_start(self, *args, **kwargs):
158
+ """Patched start method that sets up EventBus."""
159
+ # Call original start
160
+ if original_start:
161
+ result = original_start(self, *args, **kwargs)
162
+ else:
163
+ result = None
164
+
165
+ # Setup EventBus integration
166
+ if hasattr(self, '_eventbus_integration'):
167
+ port = getattr(self, 'port', 8765)
168
+ self._eventbus_integration.setup(port)
169
+
170
+ return result
171
+
172
+ def patched_stop(self, *args, **kwargs):
173
+ """Patched stop method that tears down EventBus."""
174
+ # Teardown EventBus first
175
+ if hasattr(self, '_eventbus_integration'):
176
+ self._eventbus_integration.teardown()
177
+
178
+ # Call original stop
179
+ if original_stop:
180
+ return original_stop(self, *args, **kwargs)
181
+
182
+ # Apply patches
183
+ server_class.__init__ = patched_init
184
+ if original_start:
185
+ setattr(server_class, 'start_sync' if hasattr(server_class, 'start_sync') else 'start', patched_start)
186
+ if original_stop:
187
+ setattr(server_class, 'stop_sync' if hasattr(server_class, 'stop_sync') else 'stop', patched_stop)
188
+
189
+ logger.info(f"Patched {server_class.__name__} with EventBus integration")
@@ -43,6 +43,7 @@ from ...exceptions import SocketIOServerError as MPMConnectionError
43
43
  from ..handlers import EventHandlerRegistry, FileEventHandler, GitEventHandler
44
44
  from .broadcaster import SocketIOEventBroadcaster
45
45
  from .core import SocketIOServerCore
46
+ from .eventbus_integration import EventBusIntegration
46
47
 
47
48
 
48
49
  class SocketIOServer(SocketIOServiceInterface):
@@ -93,6 +94,9 @@ class SocketIOServer(SocketIOServiceInterface):
93
94
 
94
95
  # Active session tracking for heartbeat
95
96
  self.active_sessions: Dict[str, Dict[str, Any]] = {}
97
+
98
+ # EventBus integration
99
+ self.eventbus_integration = None
96
100
 
97
101
  def start_sync(self):
98
102
  """Start the Socket.IO server in a background thread (synchronous version)."""
@@ -144,6 +148,19 @@ class SocketIOServer(SocketIOServiceInterface):
144
148
 
145
149
  # Register events
146
150
  self._register_events()
151
+
152
+ # Setup EventBus integration
153
+ # WHY: This connects the EventBus to the Socket.IO server, allowing
154
+ # events from other parts of the system to be broadcast to dashboard
155
+ try:
156
+ self.eventbus_integration = EventBusIntegration(self)
157
+ if self.eventbus_integration.setup(self.port):
158
+ self.logger.info("EventBus integration setup successful")
159
+ else:
160
+ self.logger.warning("EventBus integration setup failed or disabled")
161
+ except Exception as e:
162
+ self.logger.error(f"Failed to setup EventBus integration: {e}")
163
+ self.eventbus_integration = None
147
164
 
148
165
  # Update running state
149
166
  self.running = self.core.running
@@ -159,6 +176,14 @@ class SocketIOServer(SocketIOServiceInterface):
159
176
  if self.broadcaster:
160
177
  self.broadcaster.stop_retry_processor()
161
178
 
179
+ # Teardown EventBus integration
180
+ if self.eventbus_integration:
181
+ try:
182
+ self.eventbus_integration.teardown()
183
+ self.logger.info("EventBus integration teardown complete")
184
+ except Exception as e:
185
+ self.logger.error(f"Error during EventBus teardown: {e}")
186
+
162
187
  # Stop health monitoring in connection handler
163
188
  if self.event_registry:
164
189
  from ..handlers import ConnectionEventHandler
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-mpm
3
- Version: 4.0.32
3
+ Version: 4.1.0
4
4
  Summary: Claude Multi-Agent Project Manager - Orchestrate Claude with agent delegation and ticket tracking
5
5
  Author-email: Bob Matsuoka <bob@matsuoka.com>
6
6
  Maintainer: Claude MPM Team
@@ -46,6 +46,7 @@ Requires-Dist: toml>=0.10.2
46
46
  Requires-Dist: packaging>=21.0
47
47
  Requires-Dist: pydantic>=2.0.0
48
48
  Requires-Dist: pydantic-settings>=2.0.0
49
+ Requires-Dist: pyee>=13.0.0
49
50
  Requires-Dist: importlib-resources>=5.0; python_version < "3.9"
50
51
  Provides-Extra: dev
51
52
  Requires-Dist: pytest>=7.0; extra == "dev"
@@ -53,6 +54,11 @@ Requires-Dist: pytest-asyncio; extra == "dev"
53
54
  Requires-Dist: pytest-cov; extra == "dev"
54
55
  Requires-Dist: black; extra == "dev"
55
56
  Requires-Dist: flake8; extra == "dev"
57
+ Requires-Dist: flake8-import-order; extra == "dev"
58
+ Requires-Dist: flake8-tidy-imports; extra == "dev"
59
+ Requires-Dist: flake8-bugbear; extra == "dev"
60
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
61
+ Requires-Dist: pylint>=3.0.0; extra == "dev"
56
62
  Requires-Dist: pre-commit; extra == "dev"
57
63
  Requires-Dist: mypy>=1.0.0; extra == "dev"
58
64
  Requires-Dist: types-PyYAML>=6.0.0; extra == "dev"
@@ -116,7 +122,7 @@ A powerful orchestration framework for Claude Code that enables multi-agent work
116
122
  ## Features
117
123
 
118
124
  - 🤖 **Multi-Agent System**: 15 specialized agents for comprehensive project management
119
- - 🧠 **Agent Memory System**: Persistent learning with project-specific knowledge retention
125
+ - 🧠 **Agent Memory System**: Simple list-based persistent learning with JSON response field updates
120
126
  - 🔄 **Session Management**: Resume previous sessions with `--resume`
121
127
  - 📊 **Real-Time Monitoring**: Live dashboard with `--monitor` flag
122
128
  - 🔌 **MCP Gateway**: Model Context Protocol integration for extensible tool capabilities
@@ -132,6 +138,13 @@ A powerful orchestration framework for Claude Code that enables multi-agent work
132
138
  pip install claude-mpm
133
139
  ```
134
140
 
141
+ Or with pipx (recommended for isolated installation):
142
+ ```bash
143
+ pipx install claude-mpm
144
+ # Configure MCP for pipx users:
145
+ claude-mpm mcp-pipx-config
146
+ ```
147
+
135
148
  **That's it!** See [QUICKSTART.md](QUICKSTART.md) for immediate usage or [docs/user/installation.md](docs/user/installation.md) for advanced options.
136
149
 
137
150
  ## Quick Usage
@@ -156,15 +169,17 @@ claude-mpm cleanup-memory
156
169
  See [QUICKSTART.md](QUICKSTART.md) for complete usage examples.
157
170
 
158
171
 
159
- ## Architecture (v3.8.2+)
172
+ ## Architecture (v4.1.0+)
160
173
 
161
- Following the TSK-0053 refactoring, Claude MPM features:
174
+ Following continuous improvements through v4.1.0, Claude MPM features:
162
175
 
163
- - **Service-Oriented Architecture**: Five specialized service domains
176
+ - **Service-Oriented Architecture**: Five specialized service domains with Socket.IO stability improvements
164
177
  - **Interface-Based Contracts**: All services implement explicit interfaces
165
178
  - **Dependency Injection**: Service container with automatic resolution
166
179
  - **50-80% Performance Improvement**: Through lazy loading and intelligent caching
167
180
  - **Enhanced Security**: Comprehensive input validation and sanitization framework
181
+ - **Improved Monitoring**: Enhanced dashboard with hierarchical agent display
182
+ - **Socket.IO Stability**: Major reliability improvements for real-time communication
168
183
 
169
184
  See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for detailed architecture information.
170
185
 
@@ -200,7 +215,7 @@ Claude MPM includes 15 specialized agents:
200
215
  - **Code Analyzer** - Static code analysis with AST and tree-sitter
201
216
 
202
217
  ### Agent Memory System
203
- Agents learn project-specific patterns and remember insights across sessions. Initialize with `claude-mpm memory init`.
218
+ Agents learn project-specific patterns using a simple list format and can update memories via JSON response fields (`remember` for incremental updates, `MEMORIES` for complete replacement). Initialize with `claude-mpm memory init`.
204
219
 
205
220
  ### MCP Gateway (Model Context Protocol)
206
221
 
@@ -253,11 +268,15 @@ See [docs/MEMORY.md](docs/MEMORY.md) and [docs/developer/11-dashboard/README.md]
253
268
  ### API Documentation
254
269
  Comprehensive API documentation is available at [docs/api/](docs/api/) - build with `make html` in that directory.
255
270
 
256
- ## Recent Updates (v3.8.2)
271
+ ## Recent Updates (v4.1.0)
272
+
273
+ **Socket.IO Stability Improvements**: Major reliability enhancements for real-time communication with improved error handling and connection management.
274
+
275
+ **Project Organization**: Comprehensive cleanup and reorganization with structured script directories for better maintainability.
257
276
 
258
- **Major Architecture Refactoring (TSK-0053)**: Complete service-oriented redesign with 50-80% performance improvements, enhanced security, and interface-based design.
277
+ **Documentation Consolidation**: Streamlined documentation structure with consolidated guides and improved navigation.
259
278
 
260
- **Process Management Improvements**: Enhanced hook system reliability with automatic process cleanup, timeout protection, and orphan process monitoring to prevent resource leaks.
279
+ **Agent Hierarchy Display**: Enhanced dashboard with hierarchical agent display showing PM at top level with visual distinction for implied vs explicit nodes.
261
280
 
262
281
  See [CHANGELOG.md](CHANGELOG.md) for full history and [docs/MIGRATION.md](docs/MIGRATION.md) for upgrade instructions.
263
282