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.
Files changed (95) hide show
  1. devsquad-3.6.0.dist-info/METADATA +944 -0
  2. devsquad-3.6.0.dist-info/RECORD +95 -0
  3. devsquad-3.6.0.dist-info/WHEEL +5 -0
  4. devsquad-3.6.0.dist-info/entry_points.txt +2 -0
  5. devsquad-3.6.0.dist-info/licenses/LICENSE +21 -0
  6. devsquad-3.6.0.dist-info/top_level.txt +2 -0
  7. scripts/__init__.py +0 -0
  8. scripts/ai_semantic_matcher.py +512 -0
  9. scripts/alert_manager.py +505 -0
  10. scripts/api/__init__.py +43 -0
  11. scripts/api/models.py +386 -0
  12. scripts/api/routes/__init__.py +20 -0
  13. scripts/api/routes/dispatch.py +348 -0
  14. scripts/api/routes/lifecycle.py +330 -0
  15. scripts/api/routes/metrics_gates.py +347 -0
  16. scripts/api_server.py +318 -0
  17. scripts/auth.py +451 -0
  18. scripts/cli/__init__.py +1 -0
  19. scripts/cli/cli_visual.py +642 -0
  20. scripts/cli.py +1094 -0
  21. scripts/collaboration/__init__.py +212 -0
  22. scripts/collaboration/_version.py +1 -0
  23. scripts/collaboration/agent_briefing.py +656 -0
  24. scripts/collaboration/ai_semantic_matcher.py +260 -0
  25. scripts/collaboration/anchor_checker.py +281 -0
  26. scripts/collaboration/anti_rationalization.py +470 -0
  27. scripts/collaboration/async_integration_example.py +255 -0
  28. scripts/collaboration/batch_scheduler.py +149 -0
  29. scripts/collaboration/checkpoint_manager.py +561 -0
  30. scripts/collaboration/ci_feedback_adapter.py +351 -0
  31. scripts/collaboration/code_map_generator.py +247 -0
  32. scripts/collaboration/concern_pack_loader.py +352 -0
  33. scripts/collaboration/confidence_score.py +496 -0
  34. scripts/collaboration/config_loader.py +188 -0
  35. scripts/collaboration/consensus.py +244 -0
  36. scripts/collaboration/context_compressor.py +533 -0
  37. scripts/collaboration/coordinator.py +668 -0
  38. scripts/collaboration/dispatcher.py +1636 -0
  39. scripts/collaboration/dual_layer_context.py +128 -0
  40. scripts/collaboration/enhanced_worker.py +539 -0
  41. scripts/collaboration/feature_usage_tracker.py +206 -0
  42. scripts/collaboration/five_axis_consensus.py +334 -0
  43. scripts/collaboration/input_validator.py +401 -0
  44. scripts/collaboration/integration_example.py +287 -0
  45. scripts/collaboration/intent_workflow_mapper.py +350 -0
  46. scripts/collaboration/language_parsers.py +269 -0
  47. scripts/collaboration/lifecycle_protocol.py +1446 -0
  48. scripts/collaboration/llm_backend.py +453 -0
  49. scripts/collaboration/llm_cache.py +448 -0
  50. scripts/collaboration/llm_cache_async.py +347 -0
  51. scripts/collaboration/llm_retry.py +387 -0
  52. scripts/collaboration/llm_retry_async.py +389 -0
  53. scripts/collaboration/mce_adapter.py +597 -0
  54. scripts/collaboration/memory_bridge.py +1607 -0
  55. scripts/collaboration/models.py +537 -0
  56. scripts/collaboration/null_providers.py +297 -0
  57. scripts/collaboration/operation_classifier.py +289 -0
  58. scripts/collaboration/output_slicer.py +225 -0
  59. scripts/collaboration/performance_monitor.py +462 -0
  60. scripts/collaboration/permission_guard.py +865 -0
  61. scripts/collaboration/prompt_assembler.py +756 -0
  62. scripts/collaboration/prompt_variant_generator.py +483 -0
  63. scripts/collaboration/protocols.py +267 -0
  64. scripts/collaboration/report_formatter.py +352 -0
  65. scripts/collaboration/retrospective.py +279 -0
  66. scripts/collaboration/role_matcher.py +92 -0
  67. scripts/collaboration/role_template_market.py +352 -0
  68. scripts/collaboration/rule_collector.py +678 -0
  69. scripts/collaboration/scratchpad.py +346 -0
  70. scripts/collaboration/skill_registry.py +151 -0
  71. scripts/collaboration/skillifier.py +878 -0
  72. scripts/collaboration/standardized_role_template.py +317 -0
  73. scripts/collaboration/task_completion_checker.py +237 -0
  74. scripts/collaboration/test_quality_guard.py +695 -0
  75. scripts/collaboration/unified_gate_engine.py +598 -0
  76. scripts/collaboration/usage_tracker.py +309 -0
  77. scripts/collaboration/user_friendly_error.py +176 -0
  78. scripts/collaboration/verification_gate.py +312 -0
  79. scripts/collaboration/warmup_manager.py +635 -0
  80. scripts/collaboration/worker.py +513 -0
  81. scripts/collaboration/workflow_engine.py +684 -0
  82. scripts/dashboard.py +1088 -0
  83. scripts/generate_benchmark_report.py +786 -0
  84. scripts/history_manager.py +604 -0
  85. scripts/mcp_server.py +289 -0
  86. skills/__init__.py +32 -0
  87. skills/dispatch/handler.py +52 -0
  88. skills/intent/handler.py +59 -0
  89. skills/registry.py +67 -0
  90. skills/retrospective/__init__.py +0 -0
  91. skills/retrospective/handler.py +125 -0
  92. skills/review/handler.py +356 -0
  93. skills/security/handler.py +454 -0
  94. skills/test/__init__.py +0 -0
  95. skills/test/handler.py +78 -0
@@ -0,0 +1,356 @@
1
+ """Five-Axis Code Review Skill - V3.6.0
2
+
3
+ Encapsulates FiveAxisConsensusEngine for multi-dimensional code review:
4
+ 1. Correctness: Logic correctness, bug-free, meets requirements
5
+ 2. Readability: Code clarity, naming, comments, structure
6
+ 3. Architecture: Design patterns, modularity, scalability
7
+ 4. Security: Vulnerabilities, input validation, data protection
8
+ 5. Performance: Efficiency, resource usage, bottlenecks
9
+
10
+ Supports both direct API and dispatcher integration (mode="consensus").
11
+ """
12
+
13
+ from pathlib import Path
14
+ from typing import Any, Dict, List, Optional
15
+
16
+ from skills.registry import BaseSkill
17
+
18
+ from scripts.collaboration.five_axis_consensus import (
19
+ FiveAxisConsensusEngine,
20
+ ReviewAxis,
21
+ ConsensusResult,
22
+ FiveAxisReview,
23
+ )
24
+
25
+
26
+ class ReviewSkill(BaseSkill):
27
+ """Five-axis code review skill for comprehensive code quality assessment."""
28
+
29
+ name = "review"
30
+ description = "Five-axis code review: correctness/readability/architecture/security/performance"
31
+ version = "3.6.0"
32
+
33
+ AXES_INFO = [
34
+ {
35
+ "axis": "correctness",
36
+ "label": "Correctness",
37
+ "description": "Logic correctness, bug-free, meets requirements",
38
+ "weight": 0.30,
39
+ },
40
+ {
41
+ "axis": "readability",
42
+ "label": "Readability",
43
+ "description": "Code clarity, naming conventions, comments, structure",
44
+ "weight": 0.10,
45
+ },
46
+ {
47
+ "axis": "architecture",
48
+ "label": "Architecture",
49
+ "description": "Design patterns, modularity, scalability",
50
+ "weight": 0.20,
51
+ },
52
+ {
53
+ "axis": "security",
54
+ "label": "Security",
55
+ "description": "Vulnerabilities, input validation, data protection",
56
+ "weight": 0.25,
57
+ },
58
+ {
59
+ "axis": "performance",
60
+ "label": "Performance",
61
+ "description": "Efficiency, resource usage, bottleneck detection",
62
+ "weight": 0.15,
63
+ },
64
+ ]
65
+
66
+ def __init__(self):
67
+ self._engine: Optional[FiveAxisConsensusEngine] = None
68
+
69
+ def _get_engine(self, strict_mode: bool = False) -> FiveAxisConsensusEngine:
70
+ if self._engine is None or self._engine._strict_mode != strict_mode:
71
+ self._engine = FiveAxisConsensusEngine(strict_mode=strict_mode)
72
+ return self._engine
73
+
74
+ def review(
75
+ self,
76
+ code: str,
77
+ strict_mode: bool = False,
78
+ file_path: Optional[str] = None,
79
+ ) -> Dict[str, Any]:
80
+ """
81
+ Perform five-axis code review.
82
+
83
+ Args:
84
+ code: Source code to review (required)
85
+ strict_mode: Enable strict mode (security veto on low scores)
86
+ file_path: Optional file path for context (reads file if provided)
87
+
88
+ Returns:
89
+ Dict with review results including:
90
+ - axis_scores: Per-axis consensus scores
91
+ - overall_score: Weighted overall score
92
+ - verdict: APPROVE/CONDITIONAL/REJECT
93
+ - action_items: List of improvement suggestions
94
+ - metadata: Review metadata (file_path, mode, etc.)
95
+ """
96
+ if file_path and not code:
97
+ path = Path(file_path)
98
+ if path.exists():
99
+ code = path.read_text(encoding="utf-8")
100
+ else:
101
+ return {
102
+ "error": f"File not found: {file_path}",
103
+ "verdict": "REJECT",
104
+ }
105
+
106
+ if not code or not code.strip():
107
+ return {
108
+ "error": "No code provided for review",
109
+ "verdict": "REJECT",
110
+ }
111
+
112
+ engine = self._get_engine(strict_mode=strict_mode)
113
+
114
+ review = engine.create_review(reviewer_id="review-skill", role="code-reviewer")
115
+
116
+ axis_scores = self._analyze_code(code)
117
+
118
+ for axis_name, score_data in axis_scores.items():
119
+ try:
120
+ axis = ReviewAxis(axis_name)
121
+ engine.add_axis_vote(
122
+ review=review,
123
+ axis=axis,
124
+ score=score_data["score"],
125
+ confidence=score_data["confidence"],
126
+ comment=score_data["comment"],
127
+ )
128
+ except ValueError:
129
+ continue
130
+
131
+ result: ConsensusResult = engine.compute_consensus([review])
132
+
133
+ return {
134
+ **result.to_dict(),
135
+ "metadata": {
136
+ "file_path": file_path,
137
+ "strict_mode": strict_mode,
138
+ "code_length": len(code),
139
+ "skill_version": self.version,
140
+ },
141
+ }
142
+
143
+ def quick_review(self, code_snippet: str) -> Dict[str, Any]:
144
+ """
145
+ Simplified single-axis quick scan for rapid feedback.
146
+
147
+ Focuses on correctness axis only for fast iteration.
148
+ Suitable for inline code snippets during development.
149
+
150
+ Args:
151
+ code_snippet: Short code snippet to quickly review
152
+
153
+ Returns:
154
+ Dict with quick assessment:
155
+ - score: Correctness score (0.0-1.0)
156
+ - status: PASS/WARN/FAIL
157
+ - issues: List of detected issues
158
+ - suggestion: One-line improvement suggestion
159
+ """
160
+ if not code_snippet or not code_snippet.strip():
161
+ return {
162
+ "score": 0.0,
163
+ "status": "FAIL",
164
+ "issues": ["Empty code snippet"],
165
+ "suggestion": "Provide valid code for review",
166
+ }
167
+
168
+ issues = []
169
+ score = 1.0
170
+
171
+ lines = code_snippet.strip().split("\n")
172
+
173
+ if len(lines) < 3:
174
+ issues.append("Very short snippet - limited analysis possible")
175
+ score -= 0.1
176
+
177
+ has_comments = any(line.strip().startswith("#") for line in lines)
178
+ if not has_comments and len(lines) > 5:
179
+ issues.append("No comments found")
180
+ score -= 0.15
181
+
182
+ if "TODO" in code_snippet or "FIXME" in code_snippet or "XXX" in code_snippet:
183
+ issues.append("Contains TODO/FIXME markers")
184
+ score -= 0.2
185
+
186
+ if "print(" in code_snippet and "logging" not in code_snippet:
187
+ issues.append("Uses print() instead of logging")
188
+ score -= 0.1
189
+
190
+ if "except:" in code_snippet or "except Exception" in code_snippet:
191
+ for line in lines:
192
+ if "except" in line and ("pass" in line or "continue" in line):
193
+ issues.append("Silent exception handling detected")
194
+ score -= 0.2
195
+ break
196
+
197
+ if len(lines[0]) > 120:
198
+ issues.append("Very long first line")
199
+ score -= 0.05
200
+
201
+ score = max(0.0, min(1.0, score))
202
+
203
+ if score >= 0.8:
204
+ status = "PASS"
205
+ elif score >= 0.5:
206
+ status = "WARN"
207
+ else:
208
+ status = "FAIL"
209
+
210
+ suggestion = "Looks good" if status == "PASS" else \
211
+ "Consider addressing warnings" if status == "WARN" else \
212
+ "Needs significant improvement"
213
+
214
+ return {
215
+ "score": round(score, 2),
216
+ "status": status,
217
+ "issues": issues,
218
+ "suggestion": suggestion,
219
+ "snippet_length": len(code_snippet),
220
+ }
221
+
222
+ def list_axes(self) -> List[Dict[str, Any]]:
223
+ """
224
+ Return information about all five review axes.
225
+
226
+ Returns:
227
+ List of dicts with axis details:
228
+ - axis: Axis identifier
229
+ - label: Human-readable name
230
+ - description: What this axis evaluates
231
+ - weight: Default weight in consensus calculation
232
+ """
233
+ return self.AXES_INFO
234
+
235
+ def run(self, *args, **kwargs):
236
+ """
237
+ Main entry point for the skill.
238
+
239
+ Supports multiple calling patterns:
240
+
241
+ 1. Direct call: run(code="...", strict_mode=False)
242
+ 2. Quick mode: run(mode="quick", code_snippet="...")
243
+ 3. Dispatcher integration: run(task="...", mode="consensus")
244
+ """
245
+ mode = kwargs.get("mode", "full")
246
+
247
+ if mode == "quick":
248
+ code_snippet = kwargs.get("code_snippet", "") or kwargs.get("code", "")
249
+ return self.quick_review(code_snippet)
250
+
251
+ elif mode == "consensus":
252
+ task = kwargs.get("task", "")
253
+ code = kwargs.get("code", task)
254
+ strict_mode = kwargs.get("strict_mode", False)
255
+ file_path = kwargs.get("file_path")
256
+ return self.review(code=code, strict_mode=strict_mode, file_path=file_path)
257
+
258
+ else:
259
+ code = kwargs.get("code", "")
260
+ if not code and args:
261
+ code = str(args[0])
262
+ strict_mode = kwargs.get("strict_mode", False)
263
+ file_path = kwargs.get("file_path")
264
+ return self.review(code=code, strict_mode=strict_mode, file_path=file_path)
265
+
266
+ @staticmethod
267
+ def _analyze_code(code: str) -> Dict[str, Dict[str, Any]]:
268
+ """
269
+ Static analysis of code across five axes.
270
+ Returns simulated scores based on heuristics.
271
+ In production, this would integrate LLM-based analysis.
272
+ """
273
+ lines = code.split("\n")
274
+ total_lines = len(lines)
275
+ non_empty = [l for l in lines if l.strip()]
276
+
277
+ scores = {
278
+ "correctness": {"score": 0.85, "confidence": 0.8, "comment": "Basic structure looks valid"},
279
+ "readability": {"score": 0.75, "confidence": 0.7, "comment": "Moderate readability"},
280
+ "architecture": {"score": 0.80, "confidence": 0.6, "comment": "Reasonable structure"},
281
+ "security": {"score": 0.90, "confidence": 0.7, "comment": "No obvious security issues"},
282
+ "performance": {"score": 0.80, "confidence": 0.6, "comment": "Acceptable performance characteristics"},
283
+ }
284
+
285
+ has_imports = any(line.strip().startswith("import ") or line.strip().startswith("from ") for line in lines)
286
+ has_functions = any("def " in line for line in lines)
287
+ has_classes = any("class " in line for line in lines)
288
+ has_docstring = '"""' in code or "'''" in code
289
+ has_comments = any(line.strip().startswith("#") for line in lines)
290
+
291
+ comment_ratio = sum(1 for l in lines if l.strip().startswith("#")) / max(len(non_empty), 1)
292
+
293
+ avg_line_length = sum(len(l) for l in non_empty) / max(len(non_empty), 1)
294
+
295
+ if total_lines < 10:
296
+ scores["correctness"]["score"] -= 0.1
297
+ scores["correctness"]["comment"] = "Short code snippet - limited analysis"
298
+ else:
299
+ if has_functions or has_classes:
300
+ scores["correctness"]["score"] = min(1.0, scores["correctness"]["score"] + 0.05)
301
+ scores["correctness"]["comment"] = "Contains functions/classes - good structure"
302
+
303
+ if has_docstring:
304
+ scores["readability"]["score"] = min(1.0, scores["readability"]["score"] + 0.1)
305
+ scores["readability"]["comment"] = "Has docstrings"
306
+ else:
307
+ scores["readability"]["score"] -= 0.1
308
+ scores["readability"]["comment"] = "Missing docstrings"
309
+
310
+ if 0.1 <= comment_ratio <= 0.3:
311
+ scores["readability"]["score"] = min(1.0, scores["readability"]["score"] + 0.05)
312
+ elif comment_ratio > 0.5:
313
+ scores["readability"]["score"] -= 0.05
314
+ scores["readability"]["comment"] += " (over-commented?)"
315
+
316
+ if avg_line_length > 100:
317
+ scores["readability"]["score"] -= 0.1
318
+ scores["readability"]["comment"] += "; Long lines detected"
319
+
320
+ if has_classes and has_functions:
321
+ scores["architecture"]["score"] = min(1.0, scores["architecture"]["score"] + 0.1)
322
+ scores["architecture"]["comment"] = "OOP structure detected"
323
+ elif has_imports:
324
+ scores["architecture"]["score"] = min(1.0, scores["architecture"]["score"] + 0.05)
325
+ scores["architecture"]["comment"] = "Modular imports present"
326
+
327
+ dangerous_patterns = ["eval(", "exec(", "os.system(", "subprocess.call(", "__import__"]
328
+ for pattern in dangerous_patterns:
329
+ if pattern in code:
330
+ scores["security"]["score"] -= 0.2
331
+ scores["security"]["comment"] = f"Dangerous pattern found: {pattern}"
332
+ break
333
+
334
+ if "password" in code.lower() or "secret" in code.lower() or "api_key" in code.lower():
335
+ if "=" in code and ("\"" in code or "'" in code):
336
+ scores["security"]["score"] -= 0.3
337
+ scores["security"]["comment"] = "Possible hardcoded credentials detected"
338
+
339
+ if "sql" in code.lower() and ("SELECT" in code or "INSERT" in code):
340
+ if "f\"" in code or "f'" in code or "%" in code or ".format(" in code:
341
+ scores["security"]["score"] -= 0.15
342
+ scores["security"]["comment"] += "; Possible SQL injection risk"
343
+
344
+ if "for " in code and " range(" in code:
345
+ if total_lines > 50:
346
+ scores["performance"]["score"] -= 0.1
347
+ scores["performance"]["comment"] = "Nested loops may impact performance at scale"
348
+ elif "while True" in code:
349
+ scores["performance"]["score"] -= 0.15
350
+ scores["performance"]["comment"] = "Infinite loop detected - ensure proper exit condition"
351
+
352
+ for axis in scores:
353
+ scores[axis]["score"] = max(0.0, min(1.0, scores[axis]["score"]))
354
+ scores[axis]["score"] = round(scores[axis]["score"], 2)
355
+
356
+ return scores