devsquad 3.6.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.
- devsquad-3.6.0.dist-info/METADATA +944 -0
- devsquad-3.6.0.dist-info/RECORD +95 -0
- devsquad-3.6.0.dist-info/WHEEL +5 -0
- devsquad-3.6.0.dist-info/entry_points.txt +2 -0
- devsquad-3.6.0.dist-info/licenses/LICENSE +21 -0
- devsquad-3.6.0.dist-info/top_level.txt +2 -0
- scripts/__init__.py +0 -0
- scripts/ai_semantic_matcher.py +512 -0
- scripts/alert_manager.py +505 -0
- scripts/api/__init__.py +43 -0
- scripts/api/models.py +386 -0
- scripts/api/routes/__init__.py +20 -0
- scripts/api/routes/dispatch.py +348 -0
- scripts/api/routes/lifecycle.py +330 -0
- scripts/api/routes/metrics_gates.py +347 -0
- scripts/api_server.py +318 -0
- scripts/auth.py +451 -0
- scripts/cli/__init__.py +1 -0
- scripts/cli/cli_visual.py +642 -0
- scripts/cli.py +1094 -0
- scripts/collaboration/__init__.py +212 -0
- scripts/collaboration/_version.py +1 -0
- scripts/collaboration/agent_briefing.py +656 -0
- scripts/collaboration/ai_semantic_matcher.py +260 -0
- scripts/collaboration/anchor_checker.py +281 -0
- scripts/collaboration/anti_rationalization.py +470 -0
- scripts/collaboration/async_integration_example.py +255 -0
- scripts/collaboration/batch_scheduler.py +149 -0
- scripts/collaboration/checkpoint_manager.py +561 -0
- scripts/collaboration/ci_feedback_adapter.py +351 -0
- scripts/collaboration/code_map_generator.py +247 -0
- scripts/collaboration/concern_pack_loader.py +352 -0
- scripts/collaboration/confidence_score.py +496 -0
- scripts/collaboration/config_loader.py +188 -0
- scripts/collaboration/consensus.py +244 -0
- scripts/collaboration/context_compressor.py +533 -0
- scripts/collaboration/coordinator.py +668 -0
- scripts/collaboration/dispatcher.py +1636 -0
- scripts/collaboration/dual_layer_context.py +128 -0
- scripts/collaboration/enhanced_worker.py +539 -0
- scripts/collaboration/feature_usage_tracker.py +206 -0
- scripts/collaboration/five_axis_consensus.py +334 -0
- scripts/collaboration/input_validator.py +401 -0
- scripts/collaboration/integration_example.py +287 -0
- scripts/collaboration/intent_workflow_mapper.py +350 -0
- scripts/collaboration/language_parsers.py +269 -0
- scripts/collaboration/lifecycle_protocol.py +1446 -0
- scripts/collaboration/llm_backend.py +453 -0
- scripts/collaboration/llm_cache.py +448 -0
- scripts/collaboration/llm_cache_async.py +347 -0
- scripts/collaboration/llm_retry.py +387 -0
- scripts/collaboration/llm_retry_async.py +389 -0
- scripts/collaboration/mce_adapter.py +597 -0
- scripts/collaboration/memory_bridge.py +1607 -0
- scripts/collaboration/models.py +537 -0
- scripts/collaboration/null_providers.py +297 -0
- scripts/collaboration/operation_classifier.py +289 -0
- scripts/collaboration/output_slicer.py +225 -0
- scripts/collaboration/performance_monitor.py +462 -0
- scripts/collaboration/permission_guard.py +865 -0
- scripts/collaboration/prompt_assembler.py +756 -0
- scripts/collaboration/prompt_variant_generator.py +483 -0
- scripts/collaboration/protocols.py +267 -0
- scripts/collaboration/report_formatter.py +352 -0
- scripts/collaboration/retrospective.py +279 -0
- scripts/collaboration/role_matcher.py +92 -0
- scripts/collaboration/role_template_market.py +352 -0
- scripts/collaboration/rule_collector.py +678 -0
- scripts/collaboration/scratchpad.py +346 -0
- scripts/collaboration/skill_registry.py +151 -0
- scripts/collaboration/skillifier.py +878 -0
- scripts/collaboration/standardized_role_template.py +317 -0
- scripts/collaboration/task_completion_checker.py +237 -0
- scripts/collaboration/test_quality_guard.py +695 -0
- scripts/collaboration/unified_gate_engine.py +598 -0
- scripts/collaboration/usage_tracker.py +309 -0
- scripts/collaboration/user_friendly_error.py +176 -0
- scripts/collaboration/verification_gate.py +312 -0
- scripts/collaboration/warmup_manager.py +635 -0
- scripts/collaboration/worker.py +513 -0
- scripts/collaboration/workflow_engine.py +684 -0
- scripts/dashboard.py +1088 -0
- scripts/generate_benchmark_report.py +786 -0
- scripts/history_manager.py +604 -0
- scripts/mcp_server.py +289 -0
- skills/__init__.py +32 -0
- skills/dispatch/handler.py +52 -0
- skills/intent/handler.py +59 -0
- skills/registry.py +67 -0
- skills/retrospective/__init__.py +0 -0
- skills/retrospective/handler.py +125 -0
- skills/review/handler.py +356 -0
- skills/security/handler.py +454 -0
- skills/test/__init__.py +0 -0
- skills/test/handler.py +78 -0
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
"""Security Audit Skill - V3.6.0
|
|
2
|
+
|
|
3
|
+
Encapsulates security components for comprehensive task auditing:
|
|
4
|
+
- InputValidator: 21 pattern injection detection
|
|
5
|
+
- OperationClassifier: Three-tier operation classification
|
|
6
|
+
- PermissionGuard: Four-level permission control
|
|
7
|
+
|
|
8
|
+
Provides unified audit interface for secure multi-agent collaboration.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
12
|
+
|
|
13
|
+
from skills.registry import BaseSkill
|
|
14
|
+
|
|
15
|
+
from scripts.collaboration.input_validator import InputValidator
|
|
16
|
+
from scripts.collaboration.operation_classifier import (
|
|
17
|
+
OperationClassifier,
|
|
18
|
+
OperationCategory,
|
|
19
|
+
)
|
|
20
|
+
from scripts.collaboration.permission_guard import (
|
|
21
|
+
PermissionGuard,
|
|
22
|
+
PermissionLevel,
|
|
23
|
+
ActionType,
|
|
24
|
+
ProposedAction,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class SecuritySkill(BaseSkill):
|
|
29
|
+
"""Security audit skill combining injection detection, operation classification, and permission control."""
|
|
30
|
+
|
|
31
|
+
name = "security"
|
|
32
|
+
description = "Security auditing: injection detection, operation classification, permission control (V3.6.0)"
|
|
33
|
+
version = "3.6.0"
|
|
34
|
+
|
|
35
|
+
INJECTION_PATTERNS_COUNT = 21
|
|
36
|
+
INJECTION_CATEGORIES = {
|
|
37
|
+
"instruction_override": [
|
|
38
|
+
"ignore previous instructions",
|
|
39
|
+
"forget previous context",
|
|
40
|
+
"disregard above",
|
|
41
|
+
],
|
|
42
|
+
"role_jacking": [
|
|
43
|
+
"you are now a different role",
|
|
44
|
+
"new instructions",
|
|
45
|
+
"override settings",
|
|
46
|
+
],
|
|
47
|
+
"system_prompt_leak": [
|
|
48
|
+
"reveal your instructions",
|
|
49
|
+
"show system prompt",
|
|
50
|
+
"what are your instructions",
|
|
51
|
+
],
|
|
52
|
+
"persona_adoption": [
|
|
53
|
+
"pretend you are",
|
|
54
|
+
"act as if you are",
|
|
55
|
+
"jailbreak",
|
|
56
|
+
],
|
|
57
|
+
"privilege_escalation": [
|
|
58
|
+
"developer mode",
|
|
59
|
+
"sudo mode",
|
|
60
|
+
"DAN mode",
|
|
61
|
+
],
|
|
62
|
+
"multilingual_injection": [
|
|
63
|
+
"Chinese injection patterns",
|
|
64
|
+
"Japanese injection patterns",
|
|
65
|
+
],
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
OPERATION_LEVELS = {
|
|
69
|
+
OperationCategory.ALWAYS_SAFE: {
|
|
70
|
+
"label": "ALWAYS_SAFE",
|
|
71
|
+
"description": "Read-only operations auto-approved at most levels",
|
|
72
|
+
"examples": ["read_config", "read_file", "query_status"],
|
|
73
|
+
"default_action": "Auto-approve",
|
|
74
|
+
},
|
|
75
|
+
OperationCategory.NEEDS_REVIEW: {
|
|
76
|
+
"label": "NEEDS_REVIEW",
|
|
77
|
+
"description": "Write operations requiring confirmation or AI risk assessment",
|
|
78
|
+
"examples": ["write_file", "call_llm", "git_operation"],
|
|
79
|
+
"default_action": "Request confirmation",
|
|
80
|
+
},
|
|
81
|
+
OperationCategory.FORBIDDEN: {
|
|
82
|
+
"label": "FORBIDDEN",
|
|
83
|
+
"description": "Dangerous operations blocked unless BYPASS level override",
|
|
84
|
+
"examples": ["delete_file", "execute_shell", "access_secrets"],
|
|
85
|
+
"default_action": "Block or escalate",
|
|
86
|
+
},
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
PERMISSION_LEVELS = {
|
|
90
|
+
PermissionLevel.PLAN: {
|
|
91
|
+
"order": 0,
|
|
92
|
+
"label": "PLAN",
|
|
93
|
+
"description": "Read-only mode - all write operations denied",
|
|
94
|
+
"use_case": "Analysis, research, design tasks",
|
|
95
|
+
"risk_tolerance": "Zero write risk",
|
|
96
|
+
},
|
|
97
|
+
PermissionLevel.DEFAULT: {
|
|
98
|
+
"order": 1,
|
|
99
|
+
"label": "DEFAULT",
|
|
100
|
+
"description": "Standard mode - dangerous operations require user confirmation",
|
|
101
|
+
"use_case": "Standard coding tasks",
|
|
102
|
+
"risk_tolerance": "Medium - confirmation required",
|
|
103
|
+
},
|
|
104
|
+
PermissionLevel.AUTO: {
|
|
105
|
+
"order": 2,
|
|
106
|
+
"label": "AUTO",
|
|
107
|
+
"description": "AI-judged safe operations with guardrails and whitelist",
|
|
108
|
+
"use_case": "Trusted contexts with automated safeguards",
|
|
109
|
+
"risk_tolerance": "Medium-high - AI assessment",
|
|
110
|
+
},
|
|
111
|
+
PermissionLevel.BYPASS: {
|
|
112
|
+
"order": 3,
|
|
113
|
+
"label": "BYPASS",
|
|
114
|
+
"description": "Skip all checks - highest trust level for controlled environments only",
|
|
115
|
+
"use_case": "Sensitive operations requiring manual auth",
|
|
116
|
+
"risk_tolerance": "Full trust - manual oversight",
|
|
117
|
+
},
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
def __init__(self):
|
|
121
|
+
self._validator = InputValidator(strict_mode=False)
|
|
122
|
+
self._classifier = OperationClassifier()
|
|
123
|
+
self._guard = PermissionGuard(current_level=PermissionLevel.DEFAULT)
|
|
124
|
+
|
|
125
|
+
def scan_input(self, text: str) -> Dict[str, Any]:
|
|
126
|
+
"""
|
|
127
|
+
Scan input for prompt injection patterns using InputValidator.
|
|
128
|
+
|
|
129
|
+
Detects 21 injection patterns across categories:
|
|
130
|
+
- Instruction override attempts
|
|
131
|
+
- Role/persona jacking
|
|
132
|
+
- System prompt extraction
|
|
133
|
+
- Privilege escalation
|
|
134
|
+
- Multilingual injection vectors
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
text: Input text to scan for injection patterns
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
Dict with detection results:
|
|
141
|
+
- is_safe: Boolean indicating if input passed validation
|
|
142
|
+
- injection_patterns: List of detected injection patterns
|
|
143
|
+
- suspicious_patterns: List of suspicious but non-blocking patterns
|
|
144
|
+
- risk_level: low/medium/high/critical
|
|
145
|
+
- details: Full validation result from InputValidator
|
|
146
|
+
"""
|
|
147
|
+
if not text or not isinstance(text, str):
|
|
148
|
+
return {
|
|
149
|
+
"is_safe": False,
|
|
150
|
+
"injection_patterns": [],
|
|
151
|
+
"suspicious_patterns": [],
|
|
152
|
+
"risk_level": "critical",
|
|
153
|
+
"details": {"reason": "Invalid input type or empty text"},
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
injection_detected = self._validator.check_prompt_injection(text)
|
|
157
|
+
suspicious_detected = self._validator.check_suspicious_patterns(text)
|
|
158
|
+
|
|
159
|
+
full_validation = self._validator.validate_task(text)
|
|
160
|
+
|
|
161
|
+
pattern_count = len(injection_detected) + len(suspicious_detected)
|
|
162
|
+
|
|
163
|
+
if pattern_count == 0:
|
|
164
|
+
risk_level = "low"
|
|
165
|
+
elif len(injection_detected) == 0 and len(suspicious_detected) <= 2:
|
|
166
|
+
risk_level = "medium"
|
|
167
|
+
elif len(injection_detected) <= 3:
|
|
168
|
+
risk_level = "high"
|
|
169
|
+
else:
|
|
170
|
+
risk_level = "critical"
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
"is_safe": full_validation.valid,
|
|
174
|
+
"injection_patterns": injection_detected,
|
|
175
|
+
"suspicious_patterns": suspicious_detected,
|
|
176
|
+
"pattern_count": pattern_count,
|
|
177
|
+
"total_patterns_available": self.INJECTION_PATTERNS_COUNT,
|
|
178
|
+
"risk_level": risk_level,
|
|
179
|
+
"sanitized_input": full_validation.sanitized_input,
|
|
180
|
+
"details": {
|
|
181
|
+
"valid": full_validation.valid,
|
|
182
|
+
"reason": full_validation.reason,
|
|
183
|
+
},
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
def classify_operation(
|
|
187
|
+
self,
|
|
188
|
+
operation: str,
|
|
189
|
+
target: Optional[str] = None,
|
|
190
|
+
context: Optional[Dict[str, Any]] = None,
|
|
191
|
+
) -> Dict[str, Any]:
|
|
192
|
+
"""
|
|
193
|
+
Classify an operation into three-tier category using OperationClassifier.
|
|
194
|
+
|
|
195
|
+
Categories:
|
|
196
|
+
- ALWAYS_SAFE: Auto-approved read-only ops
|
|
197
|
+
- NEEDS_REVIEW: Write ops needing confirmation
|
|
198
|
+
- FORBIDDEN: Dangerous blocked ops
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
operation: Operation identifier (e.g., "write_file", "delete_file")
|
|
202
|
+
target: Optional target path/URL for context
|
|
203
|
+
context: Additional context (source_role, etc.)
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
Dict with classification result:
|
|
207
|
+
- category: ALWAYS_SAFE/NEEDS_REVIEW/FORBIDDEN
|
|
208
|
+
- description: Human-readable operation description
|
|
209
|
+
- risk_factors: List of identified risk factors
|
|
210
|
+
- requires_confirmation: Whether user must confirm
|
|
211
|
+
- override_allowed: Whether override is possible
|
|
212
|
+
"""
|
|
213
|
+
classified = self._classifier.classify(
|
|
214
|
+
operation_id=operation,
|
|
215
|
+
target=target,
|
|
216
|
+
context=context,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
**classified.to_dict(),
|
|
221
|
+
"level_info": self.OPERATION_LEVELS.get(classified.category, {}),
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
def check_permissions(
|
|
225
|
+
self,
|
|
226
|
+
action: str,
|
|
227
|
+
user_role: str = "viewer",
|
|
228
|
+
target: Optional[str] = None,
|
|
229
|
+
description: str = "",
|
|
230
|
+
) -> Dict[str, Any]:
|
|
231
|
+
"""
|
|
232
|
+
Check permissions for an action using PermissionGuard four-level system.
|
|
233
|
+
|
|
234
|
+
Levels (low to high):
|
|
235
|
+
- PLAN (0): Read-only, writes denied
|
|
236
|
+
- DEFAULT (1): Confirmation required for dangerous ops
|
|
237
|
+
- AUTO (2): AI classifier + whitelist
|
|
238
|
+
- BYPASS (3): Skip all checks
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
action: Action type string (file_read/file_write/delete/shell/etc.)
|
|
242
|
+
user_role: User role identifier (default: "viewer")
|
|
243
|
+
target: Optional target path/URL
|
|
244
|
+
description: Action description for audit trail
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
Dict with permission decision:
|
|
248
|
+
- outcome: ALLOWED/DENIED/PROMPT/ESCALATED
|
|
249
|
+
- reason: Decision explanation
|
|
250
|
+
- requires_confirmation: Whether user must confirm
|
|
251
|
+
- confidence: Decision confidence [0.1, 1.0]
|
|
252
|
+
- risk_score: Calculated risk [0.0, 1.0]
|
|
253
|
+
- current_level: Current permission level
|
|
254
|
+
"""
|
|
255
|
+
action_type_map = {
|
|
256
|
+
"file_read": ActionType.FILE_READ,
|
|
257
|
+
"file_create": ActionType.FILE_CREATE,
|
|
258
|
+
"file_write": ActionType.FILE_MODIFY,
|
|
259
|
+
"file_modify": ActionType.FILE_MODIFY,
|
|
260
|
+
"file_delete": ActionType.FILE_DELETE,
|
|
261
|
+
"shell": ActionType.SHELL_EXECUTE,
|
|
262
|
+
"shell_execute": ActionType.SHELL_EXECUTE,
|
|
263
|
+
"network": ActionType.NETWORK_REQUEST,
|
|
264
|
+
"network_request": ActionType.NETWORK_REQUEST,
|
|
265
|
+
"git": ActionType.GIT_OPERATION,
|
|
266
|
+
"git_operation": ActionType.GIT_OPERATION,
|
|
267
|
+
"env": ActionType.ENVIRONMENT,
|
|
268
|
+
"environment": ActionType.ENVIRONMENT,
|
|
269
|
+
"process": ActionType.PROCESS_SPAWN,
|
|
270
|
+
"process_spawn": ActionType.PROCESS_SPAWN,
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
action_type = action_type_map.get(action.lower(), ActionType.FILE_READ)
|
|
274
|
+
|
|
275
|
+
proposed = ProposedAction(
|
|
276
|
+
action_type=action_type,
|
|
277
|
+
target=target or "",
|
|
278
|
+
description=description,
|
|
279
|
+
source_role_id=user_role,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
decision = self._guard.check(proposed)
|
|
283
|
+
|
|
284
|
+
return {
|
|
285
|
+
**decision.to_dict(),
|
|
286
|
+
"current_level": self._guard.current_level.value,
|
|
287
|
+
"level_info": self.PERMISSION_LEVELS.get(self._guard.current_level, {}),
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
def audit_task(self, task_description: str) -> Dict[str, Any]:
|
|
291
|
+
"""
|
|
292
|
+
Comprehensive security audit combining all three checks.
|
|
293
|
+
|
|
294
|
+
Performs:
|
|
295
|
+
1. Injection detection on task description
|
|
296
|
+
2. Operation classification (extracts operations from text)
|
|
297
|
+
3. Permission check simulation
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
task_description: Task description to audit comprehensively
|
|
301
|
+
|
|
302
|
+
Returns:
|
|
303
|
+
Dict with complete audit report:
|
|
304
|
+
- overall_status: PASS/WARN/FAIL/BLOCK
|
|
305
|
+
- injection_scan: Results from scan_input()
|
|
306
|
+
- operations_found: List of classified operations extracted from task
|
|
307
|
+
- permission_summary: Summary of permission requirements
|
|
308
|
+
- recommendations: List of security recommendations
|
|
309
|
+
- audit_metadata: Timestamp, version, etc.
|
|
310
|
+
"""
|
|
311
|
+
from datetime import datetime
|
|
312
|
+
|
|
313
|
+
injection_result = self.scan_input(task_description)
|
|
314
|
+
|
|
315
|
+
operations_found = []
|
|
316
|
+
operation_keywords = {
|
|
317
|
+
"read_file": ["read", "open", "load", "view", "display"],
|
|
318
|
+
"write_file": ["write", "save", "create", "generate", "output"],
|
|
319
|
+
"modify_file": ["modify", "edit", "update", "change", "refactor"],
|
|
320
|
+
"delete_file": ["delete", "remove", "clean", "purge"],
|
|
321
|
+
"execute_shell": ["run", "execute", "command", "shell", "script"],
|
|
322
|
+
"network_request": ["fetch", "download", "upload", "api", "http", "request"],
|
|
323
|
+
"git_operation": ["commit", "push", "pull", "merge", "branch"],
|
|
324
|
+
"access_secrets": ["secret", "password", "credential", "api_key", "token"],
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
task_lower = task_description.lower()
|
|
328
|
+
for op_id, keywords in operation_keywords.items():
|
|
329
|
+
if any(kw in task_lower for kw in keywords):
|
|
330
|
+
classified = self.classify_operation(operation=op_id)
|
|
331
|
+
operations_found.append({
|
|
332
|
+
"operation_id": op_id,
|
|
333
|
+
**classified,
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
permission_summary = {
|
|
337
|
+
"min_required_level": "DEFAULT",
|
|
338
|
+
"requires_confirmation": any(
|
|
339
|
+
op.get("requires_confirmation") for op in operations_found
|
|
340
|
+
),
|
|
341
|
+
"forbidden_operations": [
|
|
342
|
+
op["operation_id"] for op in operations_found
|
|
343
|
+
if op.get("category") == "forbidden"
|
|
344
|
+
],
|
|
345
|
+
"safe_operations": [
|
|
346
|
+
op["operation_id"] for op in operations_found
|
|
347
|
+
if op.get("category") == "always_safe"
|
|
348
|
+
],
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if permission_summary["forbidden_operations"]:
|
|
352
|
+
permission_summary["min_required_level"] = "BYPASS"
|
|
353
|
+
|
|
354
|
+
recommendations = []
|
|
355
|
+
|
|
356
|
+
if not injection_result["is_safe"]:
|
|
357
|
+
recommendations.append(
|
|
358
|
+
f"⚠️ BLOCK: {len(injection_result['injection_patterns'])} injection pattern(s) detected - "
|
|
359
|
+
"task rejected for safety"
|
|
360
|
+
)
|
|
361
|
+
overall_status = "BLOCK"
|
|
362
|
+
|
|
363
|
+
elif injection_result["risk_level"] in ("high", "critical"):
|
|
364
|
+
recommendations.append(
|
|
365
|
+
f"⚠️ WARN: High-risk injection indicators found ({injection_result['pattern_count']} patterns)"
|
|
366
|
+
)
|
|
367
|
+
overall_status = "WARN"
|
|
368
|
+
|
|
369
|
+
elif permission_summary["forbidden_operations"]:
|
|
370
|
+
forbidden_list = ", ".join(permission_summary["forbidden_operations"])
|
|
371
|
+
recommendations.append(
|
|
372
|
+
f"🚫 FAIL: Forbidden operation(s) detected: {forbidden_list}"
|
|
373
|
+
)
|
|
374
|
+
overall_status = "FAIL"
|
|
375
|
+
|
|
376
|
+
elif permission_summary["requires_confirmation"]:
|
|
377
|
+
review_ops = [
|
|
378
|
+
op["operation_id"] for op in operations_found
|
|
379
|
+
if op.get("category") == "needs_review"
|
|
380
|
+
]
|
|
381
|
+
if review_ops:
|
|
382
|
+
recommendations.append(
|
|
383
|
+
f"✅ PASS: Task contains operations requiring confirmation: "
|
|
384
|
+
f"{', '.join(review_ops[:5])}"
|
|
385
|
+
)
|
|
386
|
+
else:
|
|
387
|
+
recommendations.append("✅ PASS: No security issues detected")
|
|
388
|
+
overall_status = "PASS"
|
|
389
|
+
|
|
390
|
+
else:
|
|
391
|
+
recommendations.append("✅ PASS: Task appears safe for execution")
|
|
392
|
+
overall_status = "PASS"
|
|
393
|
+
|
|
394
|
+
if len(operations_found) == 0:
|
|
395
|
+
recommendations.append(
|
|
396
|
+
"ℹ️ INFO: No specific operations detected in task description"
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
return {
|
|
400
|
+
"overall_status": overall_status,
|
|
401
|
+
"injection_scan": injection_result,
|
|
402
|
+
"operations_found": operations_found,
|
|
403
|
+
"operation_count": len(operations_found),
|
|
404
|
+
"permission_summary": permission_summary,
|
|
405
|
+
"recommendations": recommendations,
|
|
406
|
+
"audit_metadata": {
|
|
407
|
+
"timestamp": datetime.now().isoformat(),
|
|
408
|
+
"skill_version": self.version,
|
|
409
|
+
"task_length": len(task_description),
|
|
410
|
+
},
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
def run(self, *args, **kwargs):
|
|
414
|
+
"""
|
|
415
|
+
Main entry point for the security skill.
|
|
416
|
+
|
|
417
|
+
Supports multiple calling patterns:
|
|
418
|
+
|
|
419
|
+
1. Input scanning: run(mode="scan", text="...")
|
|
420
|
+
2. Operation classification: run(mode="classify", operation="...")
|
|
421
|
+
3. Permission check: run(mode="check", action="...", user_role="...")
|
|
422
|
+
4. Full audit: run(mode="audit", task_description="...") or default
|
|
423
|
+
"""
|
|
424
|
+
mode = kwargs.get("mode", "audit")
|
|
425
|
+
|
|
426
|
+
if mode == "scan":
|
|
427
|
+
text = kwargs.get("text", "") or kwargs.get("input", "")
|
|
428
|
+
return self.scan_input(text)
|
|
429
|
+
|
|
430
|
+
elif mode == "classify":
|
|
431
|
+
operation = kwargs.get("operation", "")
|
|
432
|
+
target = kwargs.get("target")
|
|
433
|
+
context = kwargs.get("context")
|
|
434
|
+
return self.classify_operation(operation=operation, target=target, context=context)
|
|
435
|
+
|
|
436
|
+
elif mode == "check":
|
|
437
|
+
action = kwargs.get("action", "")
|
|
438
|
+
user_role = kwargs.get("user_role", "viewer")
|
|
439
|
+
target = kwargs.get("target")
|
|
440
|
+
description = kwargs.get("description", "")
|
|
441
|
+
return self.check_permissions(
|
|
442
|
+
action=action,
|
|
443
|
+
user_role=user_role,
|
|
444
|
+
target=target,
|
|
445
|
+
description=description,
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
else:
|
|
449
|
+
task = kwargs.get("task_description", "") or \
|
|
450
|
+
kwargs.get("task", "") or \
|
|
451
|
+
kwargs.get("text", "") or \
|
|
452
|
+
(str(args[0]) if args else "")
|
|
453
|
+
|
|
454
|
+
return self.audit_task(task_description=task)
|
skills/test/__init__.py
ADDED
|
File without changes
|
skills/test/handler.py
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Test Strategy Generation Skill - V3.6.0"""
|
|
2
|
+
|
|
3
|
+
from skills.registry import BaseSkill
|
|
4
|
+
from scripts.collaboration.test_quality_guard import (
|
|
5
|
+
TestQualityGuard,
|
|
6
|
+
TestDimension,
|
|
7
|
+
APISignature,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TestSkill(BaseSkill):
|
|
12
|
+
name = "test"
|
|
13
|
+
description = "测试策略生成与质量审计 - API验证/反模式检测/维度覆盖"
|
|
14
|
+
version = "3.6.0"
|
|
15
|
+
|
|
16
|
+
SUPPORTED_TYPES = ["unit", "integration", "e2e"]
|
|
17
|
+
COVERAGE_DIMENSIONS = [
|
|
18
|
+
"API validation",
|
|
19
|
+
"Anti-pattern detection",
|
|
20
|
+
"Dimension coverage",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
def run(self, action="info", **kwargs):
|
|
24
|
+
actions = {
|
|
25
|
+
"generate_strategy": self.generate_strategy,
|
|
26
|
+
"audit_test_quality": self.audit_test_quality,
|
|
27
|
+
"suggest_cases": self.suggest_cases,
|
|
28
|
+
"coverage_dimensions": self.coverage_dimensions,
|
|
29
|
+
}
|
|
30
|
+
fn = actions.get(action)
|
|
31
|
+
if not fn:
|
|
32
|
+
return {"error": f"Unknown action: {action}. Available: {list(actions.keys())}"}
|
|
33
|
+
return fn(**kwargs)
|
|
34
|
+
|
|
35
|
+
def generate_strategy(self, code_context: str, test_type: str = "unit") -> dict:
|
|
36
|
+
if test_type not in self.SUPPORTED_TYPES:
|
|
37
|
+
return {"error": f"Unsupported test_type: {test_type}. Use: {self.SUPPORTED_TYPES}"}
|
|
38
|
+
dim_map = {
|
|
39
|
+
"unit": [TestDimension.HAPPY_PATH, TestDimension.ERROR_CASE, TestDimension.BOUNDARY],
|
|
40
|
+
"integration": [TestDimension.INTEGRATION, TestDimension.CONFIGURATION],
|
|
41
|
+
"e2e": [TestDimension.PERFORMANCE, TestDimension.SECURITY, TestDimension.INTEGRATION],
|
|
42
|
+
}
|
|
43
|
+
dims = dim_map.get(test_type, [TestDimension.HAPPY_PATH])
|
|
44
|
+
mock_sig = APISignature(name="target_function", kind="function", params=[
|
|
45
|
+
{"name": "param1", "type": "str"}, {"name": "param2", "type": "int"}
|
|
46
|
+
])
|
|
47
|
+
template = TestQualityGuard("", "").generate_test_template(mock_sig, dims)
|
|
48
|
+
return {
|
|
49
|
+
"test_type": test_type,
|
|
50
|
+
"code_context_summary": code_context[:200] if code_context else "",
|
|
51
|
+
"dimensions": [d.value for d in dims],
|
|
52
|
+
"strategy_template": template,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
def audit_test_quality(self, test_file: str) -> dict:
|
|
56
|
+
guard = TestQualityGuard(module_path="", test_path=test_file)
|
|
57
|
+
report = guard.audit()
|
|
58
|
+
return report.to_dict()
|
|
59
|
+
|
|
60
|
+
def suggest_cases(self, requirements: str) -> dict:
|
|
61
|
+
suggestions = []
|
|
62
|
+
keywords_map = {
|
|
63
|
+
"登录": ["valid_credentials", "invalid_password", "empty_fields", "account_locked", "session_timeout"],
|
|
64
|
+
"API": ["valid_request", "missing_params", "invalid_format", "rate_limit", "auth_failure"],
|
|
65
|
+
"数据库": ["insert_success", "duplicate_key", "connection_timeout", "transaction_rollback"],
|
|
66
|
+
"文件": ["normal_upload", "large_file", "invalid_type", "permission_denied"],
|
|
67
|
+
}
|
|
68
|
+
matched = False
|
|
69
|
+
for kw, cases in keywords_map.items():
|
|
70
|
+
if kw in requirements:
|
|
71
|
+
suggestions.extend(cases)
|
|
72
|
+
matched = True
|
|
73
|
+
if not matched:
|
|
74
|
+
suggestions = ["happy_path", "error_case", "boundary", "performance_baseline"]
|
|
75
|
+
return {"requirements": requirements, "suggested_cases": suggestions}
|
|
76
|
+
|
|
77
|
+
def coverage_dimensions(self) -> list:
|
|
78
|
+
return self.COVERAGE_DIMENSIONS
|