claude-mpm 3.3.2__py3-none-any.whl → 3.4.2__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 (48) hide show
  1. claude_mpm/cli/commands/memory.py +192 -14
  2. claude_mpm/cli/parser.py +13 -1
  3. claude_mpm/constants.py +1 -0
  4. claude_mpm/core/claude_runner.py +61 -0
  5. claude_mpm/core/config.py +161 -1
  6. claude_mpm/core/simple_runner.py +61 -0
  7. claude_mpm/hooks/builtin/mpm_command_hook.py +5 -5
  8. claude_mpm/hooks/claude_hooks/hook_handler.py +211 -4
  9. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +10 -3
  10. claude_mpm/hooks/memory_integration_hook.py +51 -5
  11. claude_mpm/scripts/socketio_daemon.py +49 -9
  12. claude_mpm/scripts/socketio_server_manager.py +370 -45
  13. claude_mpm/services/__init__.py +41 -5
  14. claude_mpm/services/agent_memory_manager.py +541 -51
  15. claude_mpm/services/exceptions.py +677 -0
  16. claude_mpm/services/health_monitor.py +892 -0
  17. claude_mpm/services/memory_builder.py +341 -7
  18. claude_mpm/services/memory_optimizer.py +6 -2
  19. claude_mpm/services/project_analyzer.py +771 -0
  20. claude_mpm/services/recovery_manager.py +670 -0
  21. claude_mpm/services/socketio_server.py +653 -36
  22. claude_mpm/services/standalone_socketio_server.py +703 -34
  23. claude_mpm/services/version_control/git_operations.py +26 -0
  24. {claude_mpm-3.3.2.dist-info → claude_mpm-3.4.2.dist-info}/METADATA +34 -10
  25. {claude_mpm-3.3.2.dist-info → claude_mpm-3.4.2.dist-info}/RECORD +30 -44
  26. claude_mpm/agents/agent-template.yaml +0 -83
  27. claude_mpm/agents/test_fix_deployment/.claude-pm/config/project.json +0 -6
  28. claude_mpm/cli/README.md +0 -109
  29. claude_mpm/cli_module/refactoring_guide.md +0 -253
  30. claude_mpm/core/agent_registry.py.bak +0 -312
  31. claude_mpm/core/base_service.py.bak +0 -406
  32. claude_mpm/hooks/README.md +0 -97
  33. claude_mpm/orchestration/SUBPROCESS_DESIGN.md +0 -66
  34. claude_mpm/schemas/README_SECURITY.md +0 -92
  35. claude_mpm/schemas/agent_schema.json +0 -395
  36. claude_mpm/schemas/agent_schema_documentation.md +0 -181
  37. claude_mpm/schemas/agent_schema_security_notes.md +0 -165
  38. claude_mpm/schemas/examples/standard_workflow.json +0 -505
  39. claude_mpm/schemas/ticket_workflow_documentation.md +0 -482
  40. claude_mpm/schemas/ticket_workflow_schema.json +0 -590
  41. claude_mpm/services/framework_claude_md_generator/README.md +0 -92
  42. claude_mpm/services/parent_directory_manager/README.md +0 -83
  43. claude_mpm/services/version_control/VERSION +0 -1
  44. /claude_mpm/{web → dashboard}/open_dashboard.py +0 -0
  45. {claude_mpm-3.3.2.dist-info → claude_mpm-3.4.2.dist-info}/WHEEL +0 -0
  46. {claude_mpm-3.3.2.dist-info → claude_mpm-3.4.2.dist-info}/entry_points.txt +0 -0
  47. {claude_mpm-3.3.2.dist-info → claude_mpm-3.4.2.dist-info}/licenses/LICENSE +0 -0
  48. {claude_mpm-3.3.2.dist-info → claude_mpm-3.4.2.dist-info}/top_level.txt +0 -0
@@ -1,406 +0,0 @@
1
- """
2
- Base service class for Claude PM Framework services.
3
-
4
- Provides common functionality including:
5
- - Lifecycle management (start, stop, health checks)
6
- - Configuration management
7
- - Logging
8
- - Metrics collection
9
- - Error handling and retry logic
10
- - Service discovery and registration
11
- """
12
-
13
- import asyncio
14
- import logging
15
- import signal
16
- import sys
17
- import os
18
- from abc import ABC, abstractmethod
19
- from dataclasses import dataclass, field
20
- from datetime import datetime
21
- from typing import Any, Dict, List, Optional, Union
22
- from pathlib import Path
23
- import json
24
-
25
- from .config import Config
26
- from .logger import setup_logging
27
- from .mixins import LoggerMixin
28
-
29
-
30
- @dataclass
31
- class ServiceHealth:
32
- """Service health status information."""
33
-
34
- status: str # healthy, degraded, unhealthy, unknown
35
- message: str
36
- timestamp: str
37
- metrics: Dict[str, Any] = field(default_factory=dict)
38
- checks: Dict[str, bool] = field(default_factory=dict)
39
-
40
-
41
- @dataclass
42
- class ServiceMetrics:
43
- """Service metrics collection."""
44
-
45
- requests_total: int = 0
46
- requests_failed: int = 0
47
- response_time_avg: float = 0.0
48
- uptime_seconds: int = 0
49
- memory_usage_mb: float = 0.0
50
- custom_metrics: Dict[str, Any] = field(default_factory=dict)
51
-
52
-
53
- class BaseService(LoggerMixin, ABC):
54
- """
55
- Abstract base class for all Claude PM services.
56
-
57
- Provides common infrastructure for service lifecycle management,
58
- health monitoring, configuration, logging, and error handling.
59
- """
60
-
61
- def __init__(
62
- self, name: str, config: Optional[Dict[str, Any]] = None, config_path: Optional[Path] = None
63
- ):
64
- """
65
- Initialize the base service.
66
-
67
- Args:
68
- name: Service name for identification
69
- config: Optional configuration dictionary
70
- config_path: Optional path to configuration file
71
- """
72
- self.name = name
73
- self.config = Config(config or {}, config_path)
74
-
75
- # Set custom logger name based on service name
76
- self._logger_name = f"{self.__class__.__module__}.{self.__class__.__name__}.{name}"
77
-
78
- # Service state
79
- self._running = False
80
- self._start_time: Optional[datetime] = None
81
- self._stop_event = asyncio.Event()
82
-
83
- # Health and metrics
84
- self._health = ServiceHealth(
85
- status="unknown", message="Service not started", timestamp=datetime.now().isoformat()
86
- )
87
- self._metrics = ServiceMetrics()
88
-
89
- # Background tasks
90
- self._background_tasks: List[asyncio.Task] = []
91
-
92
- # Check for quiet mode environment variable
93
- default_log_level = "INFO"
94
- if os.getenv('CLAUDE_PM_QUIET_MODE') == 'true':
95
- default_log_level = "WARNING"
96
- # Set logger level if needed
97
- self.logger.setLevel(logging.WARNING)
98
-
99
- # Only log if not in quiet mode
100
- if not os.environ.get('CLAUDE_PM_QUIET_MODE', '').lower() == 'true':
101
- self.logger.info(f"Initialized {self.name} service")
102
-
103
- @property
104
- def running(self) -> bool:
105
- """Check if service is currently running."""
106
- return self._running
107
-
108
- @property
109
- def uptime(self) -> Optional[float]:
110
- """Get service uptime in seconds."""
111
- if self._start_time and self._running:
112
- return (datetime.now() - self._start_time).total_seconds()
113
- return None
114
-
115
- @property
116
- def health(self) -> ServiceHealth:
117
- """Get current service health status."""
118
- return self._health
119
-
120
- @property
121
- def metrics(self) -> ServiceMetrics:
122
- """Get current service metrics."""
123
- if self.uptime:
124
- self._metrics.uptime_seconds = int(self.uptime)
125
- return self._metrics
126
-
127
- async def start(self) -> None:
128
- """Start the service."""
129
- if self._running:
130
- self.logger.warning(f"Service {self.name} is already running")
131
- return
132
-
133
- self.logger.info(f"Starting {self.name} service...")
134
-
135
- try:
136
- # Setup signal handlers
137
- self._setup_signal_handlers()
138
-
139
- # Initialize service
140
- await self._initialize()
141
-
142
- # Start background tasks
143
- await self._start_background_tasks()
144
-
145
- # Mark as running
146
- self._running = True
147
- self._start_time = datetime.now()
148
-
149
- # Update health status
150
- self._health = ServiceHealth(
151
- status="healthy",
152
- message="Service started successfully",
153
- timestamp=datetime.now().isoformat(),
154
- checks={"startup": True},
155
- )
156
-
157
- self.logger.info(f"Service {self.name} started successfully")
158
-
159
- except Exception as e:
160
- self.logger.error(f"Failed to start service {self.name}: {e}")
161
- self._health = ServiceHealth(
162
- status="unhealthy",
163
- message=f"Startup failed: {str(e)}",
164
- timestamp=datetime.now().isoformat(),
165
- checks={"startup": False},
166
- )
167
- raise
168
-
169
- async def stop(self) -> None:
170
- """Stop the service gracefully."""
171
- if not self._running:
172
- self.logger.warning(f"Service {self.name} is not running")
173
- return
174
-
175
- self.logger.info(f"Stopping {self.name} service...")
176
-
177
- try:
178
- # Signal stop to background tasks
179
- self._stop_event.set()
180
-
181
- # Cancel background tasks
182
- for task in self._background_tasks:
183
- if not task.done():
184
- task.cancel()
185
-
186
- # Wait for tasks to complete
187
- if self._background_tasks:
188
- await asyncio.gather(*self._background_tasks, return_exceptions=True)
189
-
190
- # Cleanup service
191
- await self._cleanup()
192
-
193
- # Mark as stopped
194
- self._running = False
195
-
196
- # Update health status
197
- self._health = ServiceHealth(
198
- status="unknown",
199
- message="Service stopped",
200
- timestamp=datetime.now().isoformat(),
201
- checks={"running": False},
202
- )
203
-
204
- self.logger.info(f"Service {self.name} stopped successfully")
205
-
206
- except Exception as e:
207
- self.logger.error(f"Error stopping service {self.name}: {e}")
208
- raise
209
-
210
- async def restart(self) -> None:
211
- """Restart the service."""
212
- self.logger.info(f"Restarting {self.name} service...")
213
- await self.stop()
214
- await self.start()
215
-
216
- async def health_check(self) -> ServiceHealth:
217
- """
218
- Perform comprehensive health check.
219
-
220
- Returns:
221
- ServiceHealth object with current status
222
- """
223
- try:
224
- checks = {}
225
-
226
- # Basic running check
227
- checks["running"] = self._running
228
-
229
- # Custom health checks
230
- custom_checks = await self._health_check()
231
- checks.update(custom_checks)
232
-
233
- # Determine overall status
234
- if not checks["running"]:
235
- status = "unhealthy"
236
- message = "Service is not running"
237
- elif all(checks.values()):
238
- status = "healthy"
239
- message = "All health checks passed"
240
- elif any(checks.values()):
241
- status = "degraded"
242
- message = "Some health checks failed"
243
- else:
244
- status = "unhealthy"
245
- message = "Multiple health checks failed"
246
-
247
- # Update health status
248
- self._health = ServiceHealth(
249
- status=status,
250
- message=message,
251
- timestamp=datetime.now().isoformat(),
252
- checks=checks,
253
- metrics={
254
- "uptime": self.uptime,
255
- "requests_total": self._metrics.requests_total,
256
- "requests_failed": self._metrics.requests_failed,
257
- },
258
- )
259
-
260
- return self._health
261
-
262
- except Exception as e:
263
- self.logger.error(f"Health check failed for {self.name}: {e}")
264
- self._health = ServiceHealth(
265
- status="unhealthy",
266
- message=f"Health check error: {str(e)}",
267
- timestamp=datetime.now().isoformat(),
268
- checks={"health_check_error": True},
269
- )
270
- return self._health
271
-
272
- def update_metrics(self, **kwargs) -> None:
273
- """Update service metrics."""
274
- for key, value in kwargs.items():
275
- if hasattr(self._metrics, key):
276
- setattr(self._metrics, key, value)
277
- else:
278
- self._metrics.custom_metrics[key] = value
279
-
280
- def get_config(self, key: str, default: Any = None) -> Any:
281
- """Get configuration value."""
282
- return self.config.get(key, default)
283
-
284
- def _setup_signal_handlers(self) -> None:
285
- """Setup signal handlers for graceful shutdown."""
286
-
287
- def signal_handler(signum, frame):
288
- self.logger.info(f"Received signal {signum}, initiating graceful shutdown...")
289
- asyncio.create_task(self.stop())
290
-
291
- signal.signal(signal.SIGINT, signal_handler)
292
- signal.signal(signal.SIGTERM, signal_handler)
293
-
294
- async def _start_background_tasks(self) -> None:
295
- """Start background tasks."""
296
- # Health check task
297
- if self.get_config("enable_health_monitoring", True):
298
- interval = self.get_config("health_check_interval", 30)
299
- task = asyncio.create_task(self._health_monitor_task(interval))
300
- self._background_tasks.append(task)
301
-
302
- # Metrics collection task
303
- if self.get_config("enable_metrics", True):
304
- interval = self.get_config("metrics_interval", 60)
305
- task = asyncio.create_task(self._metrics_task(interval))
306
- self._background_tasks.append(task)
307
-
308
- # Custom background tasks
309
- custom_tasks = await self._start_custom_tasks()
310
- if custom_tasks:
311
- self._background_tasks.extend(custom_tasks)
312
-
313
- async def _health_monitor_task(self, interval: int) -> None:
314
- """Background task for periodic health monitoring."""
315
- while not self._stop_event.is_set():
316
- try:
317
- await self.health_check()
318
- await asyncio.sleep(interval)
319
- except asyncio.CancelledError:
320
- break
321
- except Exception as e:
322
- self.logger.error(f"Health monitor task error: {e}")
323
- await asyncio.sleep(interval)
324
-
325
- async def _metrics_task(self, interval: int) -> None:
326
- """Background task for metrics collection."""
327
- while not self._stop_event.is_set():
328
- try:
329
- await self._collect_metrics()
330
- await asyncio.sleep(interval)
331
- except asyncio.CancelledError:
332
- break
333
- except Exception as e:
334
- self.logger.error(f"Metrics task error: {e}")
335
- await asyncio.sleep(interval)
336
-
337
- async def _collect_metrics(self) -> None:
338
- """Collect service metrics."""
339
- try:
340
- # Update uptime
341
- if self.uptime:
342
- self._metrics.uptime_seconds = int(self.uptime)
343
-
344
- # Memory usage (basic implementation)
345
- import psutil
346
-
347
- process = psutil.Process()
348
- self._metrics.memory_usage_mb = process.memory_info().rss / 1024 / 1024
349
-
350
- # Custom metrics collection
351
- await self._collect_custom_metrics()
352
-
353
- except Exception as e:
354
- self.logger.warning(f"Failed to collect metrics: {e}")
355
-
356
- # Abstract methods to be implemented by subclasses
357
-
358
- @abstractmethod
359
- async def _initialize(self) -> None:
360
- """Initialize the service. Must be implemented by subclasses."""
361
- pass
362
-
363
- @abstractmethod
364
- async def _cleanup(self) -> None:
365
- """Cleanup service resources. Must be implemented by subclasses."""
366
- pass
367
-
368
- async def _health_check(self) -> Dict[str, bool]:
369
- """
370
- Perform custom health checks. Override in subclasses.
371
-
372
- Returns:
373
- Dictionary of check name -> success boolean
374
- """
375
- return {}
376
-
377
- async def _start_custom_tasks(self) -> Optional[List[asyncio.Task]]:
378
- """
379
- Start custom background tasks. Override in subclasses.
380
-
381
- Returns:
382
- List of asyncio tasks or None
383
- """
384
- return None
385
-
386
- async def _collect_custom_metrics(self) -> None:
387
- """Collect custom metrics. Override in subclasses."""
388
- pass
389
-
390
- # Utility methods
391
-
392
- async def run_forever(self) -> None:
393
- """Run the service until stopped."""
394
- await self.start()
395
- try:
396
- # Wait for stop signal
397
- while self._running:
398
- await asyncio.sleep(1)
399
- except KeyboardInterrupt:
400
- self.logger.info("Received keyboard interrupt")
401
- finally:
402
- await self.stop()
403
-
404
- def __repr__(self) -> str:
405
- """String representation of the service."""
406
- return f"<{self.__class__.__name__}(name='{self.name}', running={self._running})>"
@@ -1,97 +0,0 @@
1
- # Claude Code Hooks System
2
-
3
- This directory contains the Claude Code hook integration for claude-mpm.
4
-
5
- ## Overview
6
-
7
- The hook system allows claude-mpm to intercept and handle commands typed in Claude Code, particularly the `/mpm` commands.
8
-
9
- ## Structure
10
-
11
- ```
12
- hooks/
13
- ├── claude_hooks/ # Claude Code hook implementation
14
- │ ├── hook_handler.py # Main Python handler that processes events
15
- │ └── hook_wrapper.sh # Shell wrapper script (this is what gets installed in ~/.claude/settings.json)
16
- └── builtin/ # Legacy internal hooks (deprecated)
17
- ```
18
-
19
- ## Claude Code Hooks
20
-
21
- The Claude Code hooks are the primary integration point between claude-mpm and Claude Code. They allow:
22
-
23
- - Intercepting `/mpm` commands before they reach the LLM
24
- - Providing custom responses and actions
25
- - Blocking LLM processing when appropriate
26
-
27
- ### Installation
28
-
29
- To install the Claude Code hooks:
30
-
31
- ```bash
32
- python scripts/install_hooks.py
33
- ```
34
-
35
- This will:
36
- 1. Create/update `~/.claude/settings.json` with hook configuration
37
- 2. Point to the `hook_wrapper.sh` script
38
- 3. Copy any custom commands to `~/.claude/commands/`
39
-
40
- ### How It Works
41
-
42
- 1. When you type in Claude Code, it triggers hook events
43
- 2. Claude Code calls `hook_wrapper.sh` (the path in `~/.claude/settings.json`)
44
- 3. The wrapper script:
45
- - Detects if it's running from a local dev environment, npm, or PyPI installation
46
- - Activates the appropriate Python environment
47
- - Runs `hook_handler.py` with the event data
48
- 4. The handler processes various event types:
49
- - **UserPromptSubmit**: Checks if the prompt starts with `/mpm` and handles commands
50
- - **PreToolUse**: Logs tool usage before execution
51
- - **PostToolUse**: Logs tool results after execution
52
- - **Stop**: Logs when a session or task stops
53
- - **SubagentStop**: Logs when a subagent completes with agent type and ID
54
- 5. For `/mpm` commands, it returns exit code 2 to block LLM processing
55
- 6. All events are logged to project-specific log files in `.claude-mpm/logs/`
56
-
57
- ### Available Commands
58
-
59
- - `/mpm` - Show help and available commands
60
- - `/mpm status` - Show claude-mpm status and environment
61
- - `/mpm help` - Show detailed help
62
-
63
- ### Debugging
64
-
65
- To enable debug logging for hooks:
66
-
67
- ```bash
68
- export CLAUDE_MPM_LOG_LEVEL=DEBUG
69
- ```
70
-
71
- Then run Claude Code from that terminal. Hook events will be logged to `~/.claude-mpm/logs/`.
72
-
73
- ## Legacy Hook System (Deprecated)
74
-
75
- The `builtin/` directory contains the old internal hook system that was designed for JSON-RPC based hooks. This system is deprecated and will be removed in a future version. All hook functionality is now handled through the Claude Code hooks.
76
-
77
- ## Development
78
-
79
- To add new `/mpm` commands:
80
-
81
- 1. Edit `hook_handler.py` to handle the new command
82
- 2. Update the help text in the `handle_mpm_help()` function
83
- 3. Test by running Claude Code with the new command
84
-
85
- ## Exit Codes
86
-
87
- The hook system uses specific exit codes:
88
-
89
- - `0` - Success, continue normal processing
90
- - `2` - Block LLM processing (command was handled)
91
- - Other - Error occurred
92
-
93
- ## Environment Variables
94
-
95
- - `CLAUDE_MPM_LOG_LEVEL` - Set to DEBUG for detailed logging
96
- - `HOOK_EVENT_TYPE` - Set by Claude Code (UserPromptSubmit, PreToolUse, PostToolUse)
97
- - `HOOK_DATA` - JSON data from Claude Code with event details
@@ -1,66 +0,0 @@
1
- # Subprocess Orchestration Design
2
-
3
- ## Problem
4
- Claude's `--print` mode times out when generating code or using tools, making subprocess orchestration in non-interactive mode impractical.
5
-
6
- ## Findings
7
-
8
- ### Interactive Mode (Working)
9
- - Claude uses built-in Task tool
10
- - Creates real subprocesses with ~11.4k tokens each
11
- - Runs in parallel with independent timing
12
- - Each subprocess gets framework context
13
-
14
- ### Non-Interactive Mode Issues
15
- - `claude --print` works for simple queries (e.g., "What is 2+2?" in ~4s)
16
- - Times out for any code generation or complex tasks
17
- - Debug shows Claude is working but tool usage adds overhead
18
- - Requires `--dangerously-skip-permissions` flag to run
19
-
20
- ## Alternative Approaches
21
-
22
- ### 1. Use Claude's Conversation API
23
- Instead of `--print`, use conversation management:
24
- ```bash
25
- # Start conversation
26
- claude --model opus -c "conversation_id" < prompt.txt
27
-
28
- # Continue conversation
29
- claude --continue conversation_id < next_prompt.txt
30
- ```
31
-
32
- ### 2. Use Interactive Mode with Expect
33
- Use expect/pexpect to control interactive Claude sessions programmatically.
34
-
35
- ### 3. Mock Subprocess Mode
36
- For testing/development:
37
- - Detect delegations in PM response
38
- - Show subprocess-like output
39
- - But don't actually create subprocesses
40
-
41
- ### 4. Direct API Integration
42
- Skip CLI entirely and use Claude's API directly (if available).
43
-
44
- ## Implementation Status
45
-
46
- ### Completed
47
- 1. ✅ SubprocessOrchestrator class with full functionality
48
- 2. ✅ Delegation detection for multiple formats
49
- 3. ✅ Parallel subprocess execution framework
50
- 4. ✅ Agent-specific prompt generation
51
- 5. ✅ CLI integration via `--subprocess` flag
52
- 6. ✅ Fixed command flags for permissions
53
-
54
- ### Current Status
55
- - Implementation is complete but blocked by Claude CLI limitations
56
- - Use interactive mode for real subprocess orchestration
57
- - Keep implementation for future when Claude print mode improves
58
-
59
- ## Delegation Detection Patterns
60
-
61
- The PM uses these formats:
62
- - `**Engineer Agent**: Create a function...`
63
- - `**QA**: Write tests for...`
64
- - `I'll delegate this to the Engineer agent...`
65
-
66
- We can parse these and show subprocess-style output even without real subprocesses.
@@ -1,92 +0,0 @@
1
- # Agent Schema Security Guide
2
-
3
- ## Critical Security Notice
4
-
5
- **This schema is a SECURITY BOUNDARY.** Any changes to agent_schema.json must be carefully reviewed for security implications.
6
-
7
- ## Security Controls in agent_schema.json
8
-
9
- ### 1. Field Validation
10
- - **agent_id**: Pattern `^[a-z][a-z0-9_]*$` prevents path traversal and command injection
11
- - **version fields**: Semantic versioning pattern prevents version injection
12
- - **enums**: All enums are allowlists preventing arbitrary values
13
-
14
- ### 2. Size Limits
15
- - **instructions**: 8000 char max prevents memory exhaustion
16
- - **name**: 50 char max prevents UI breaking
17
- - **description**: 200 char max prevents storage abuse
18
- - **tags**: max 10 items prevents array bombing
19
-
20
- ### 3. Resource Limits by Tier
21
- ```
22
- intensive: memory: 4096-8192MB, cpu: 60-100%, timeout: 600-3600s
23
- standard: memory: 2048-4096MB, cpu: 30-60%, timeout: 300-1200s
24
- lightweight: memory: 512-2048MB, cpu: 10-30%, timeout: 30-600s
25
- ```
26
-
27
- ### 4. Tool Security Matrix
28
-
29
- | Tool Combination | Risk Level | Security Impact |
30
- |-----------------|------------|-----------------|
31
- | Bash + Write | CRITICAL | Arbitrary code execution |
32
- | docker + kubectl | HIGH | Container escape potential |
33
- | aws + gcloud + azure | HIGH | Multi-cloud attack surface |
34
- | WebFetch + Write | MEDIUM | Data exfiltration risk |
35
- | Read + network_access | MEDIUM | Information disclosure |
36
-
37
- ### 5. Required Security Reviews
38
-
39
- Any PR modifying agent_schema.json MUST include:
40
- 1. Security impact assessment
41
- 2. Validation that no new fields bypass security controls
42
- 3. Test cases for new validation rules
43
- 4. Update to this security guide if needed
44
-
45
- ### 6. Security Checklist for Schema Changes
46
-
47
- - [ ] No new fields allow arbitrary string input without validation
48
- - [ ] All new arrays have maxItems limits
49
- - [ ] All new strings have maxLength limits
50
- - [ ] New enum values are reviewed for security impact
51
- - [ ] Resource limits maintain tier boundaries
52
- - [ ] No new fields can bypass additionalProperties: false
53
- - [ ] Pattern validations prevent injection attacks
54
- - [ ] Default values follow principle of least privilege
55
-
56
- ## Common Security Mistakes to Avoid
57
-
58
- 1. **Never** add fields that accept arbitrary file paths without validation
59
- 2. **Never** increase resource limits without security review
60
- 3. **Never** add tools that bypass the enum list
61
- 4. **Never** remove pattern validation from ID fields
62
- 5. **Never** set additionalProperties to true
63
- 6. **Always** default network_access to false
64
- 7. **Always** validate new tool combinations for security impact
65
-
66
- ## Security Testing
67
-
68
- Run these tests after any schema change:
69
- ```bash
70
- # Validate schema structure
71
- python scripts/validate_agent_schema.py
72
-
73
- # Test security boundaries
74
- python tests/test_agent_security_boundaries.py
75
-
76
- # Check for injection vulnerabilities
77
- python tests/test_agent_validation_security.py
78
- ```
79
-
80
- ## Incident Response
81
-
82
- If a security vulnerability is found in the schema:
83
- 1. Immediately add validation in agent_validator.py as a hotfix
84
- 2. Update schema to prevent the vulnerability
85
- 3. Audit all existing agents for exploitation
86
- 4. Document the vulnerability and fix in security log
87
-
88
- ## Security Contacts
89
-
90
- - Security reviews: security-team@company.com
91
- - Vulnerability reports: security@company.com
92
- - Emergency response: security-oncall@company.com