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,352 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Concern Pack Loader — 关注点增强包加载引擎
|
|
4
|
+
|
|
5
|
+
根据任务描述自动匹配并加载相关的增强包,将领域知识注入到角色提示词中。
|
|
6
|
+
|
|
7
|
+
增强包位置: templates/concerns/*.yaml
|
|
8
|
+
触发机制: 任务描述中的关键词匹配增强包的 triggers.keywords
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
from scripts.collaboration.concern_pack_loader import ConcernPackLoader
|
|
12
|
+
|
|
13
|
+
loader = ConcernPackLoader()
|
|
14
|
+
packs = loader.match_packs("设计用户权限系统")
|
|
15
|
+
# → [PermissionPack]
|
|
16
|
+
|
|
17
|
+
enhancements = loader.get_role_enhancements(packs, "security")
|
|
18
|
+
# → "【权限设计专项检查】..."
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import os
|
|
22
|
+
import sys
|
|
23
|
+
import logging
|
|
24
|
+
import threading
|
|
25
|
+
from typing import Dict, List, Optional, Any
|
|
26
|
+
from dataclasses import dataclass, field
|
|
27
|
+
|
|
28
|
+
logger = logging.getLogger(__name__)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class DecisionOption:
|
|
33
|
+
id: str
|
|
34
|
+
name: str
|
|
35
|
+
when: str
|
|
36
|
+
examples: str = ""
|
|
37
|
+
complexity: int = 1
|
|
38
|
+
pros: str = ""
|
|
39
|
+
cons: str = ""
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class DecisionStep:
|
|
44
|
+
question: str
|
|
45
|
+
description: str = ""
|
|
46
|
+
options: List[DecisionOption] = field(default_factory=list)
|
|
47
|
+
selection_guide: str = ""
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass
|
|
51
|
+
class ChecklistItem:
|
|
52
|
+
item: str
|
|
53
|
+
severity: str = "required"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass
|
|
57
|
+
class Pitfall:
|
|
58
|
+
title: str
|
|
59
|
+
description: str
|
|
60
|
+
severity: str = "medium"
|
|
61
|
+
check: str = ""
|
|
62
|
+
fix: str = ""
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass
|
|
66
|
+
class ConcernPack:
|
|
67
|
+
concern_id: str
|
|
68
|
+
name: str
|
|
69
|
+
version: str = "1.0"
|
|
70
|
+
description: str = ""
|
|
71
|
+
triggers: Dict[str, Any] = field(default_factory=dict)
|
|
72
|
+
decision_framework: Dict[str, Any] = field(default_factory=dict)
|
|
73
|
+
checklist: Dict[str, Any] = field(default_factory=dict)
|
|
74
|
+
role_enhancements: Dict[str, str] = field(default_factory=dict)
|
|
75
|
+
|
|
76
|
+
def get_checklist_summary(self) -> str:
|
|
77
|
+
must_have = self.checklist.get("must_have", [])
|
|
78
|
+
pitfalls = self.checklist.get("common_pitfalls", [])
|
|
79
|
+
|
|
80
|
+
lines = [f"\n### {self.name} — 检查清单\n"]
|
|
81
|
+
|
|
82
|
+
if must_have:
|
|
83
|
+
lines.append("**必须检查项**:")
|
|
84
|
+
for item in must_have:
|
|
85
|
+
severity = item.get("severity", "required") if isinstance(item, dict) else "required"
|
|
86
|
+
text = item.get("item", str(item)) if isinstance(item, dict) else str(item)
|
|
87
|
+
icon = "🔴" if severity == "required" else "🟡"
|
|
88
|
+
lines.append(f"- [{icon}] {text}")
|
|
89
|
+
|
|
90
|
+
if pitfalls:
|
|
91
|
+
lines.append("\n**常见陷阱**:")
|
|
92
|
+
for p in pitfalls:
|
|
93
|
+
if isinstance(p, dict):
|
|
94
|
+
severity = p.get("severity", "medium")
|
|
95
|
+
icon = {"critical": "🔴", "high": "🟠", "medium": "🟡"}.get(severity, "🟡")
|
|
96
|
+
lines.append(f"- [{icon}] **{p.get('title', '')}** ({severity})")
|
|
97
|
+
lines.append(f" → {p.get('check', p.get('description', ''))}")
|
|
98
|
+
|
|
99
|
+
return "\n".join(lines)
|
|
100
|
+
|
|
101
|
+
def get_decision_summary(self) -> str:
|
|
102
|
+
steps = self.decision_framework
|
|
103
|
+
if not steps:
|
|
104
|
+
return ""
|
|
105
|
+
|
|
106
|
+
lines = [f"\n### {self.name} — 决策框架\n"]
|
|
107
|
+
|
|
108
|
+
for step_key, step_data in steps.items():
|
|
109
|
+
if not isinstance(step_data, dict):
|
|
110
|
+
continue
|
|
111
|
+
question = step_data.get("question", "")
|
|
112
|
+
if question:
|
|
113
|
+
lines.append(f"**{question}**")
|
|
114
|
+
|
|
115
|
+
options = step_data.get("options", [])
|
|
116
|
+
if options:
|
|
117
|
+
for opt in options:
|
|
118
|
+
if isinstance(opt, dict):
|
|
119
|
+
complexity_stars = "⭐" * opt.get("complexity", 1)
|
|
120
|
+
lines.append(f"- **{opt.get('name', '')}** {complexity_stars}")
|
|
121
|
+
when = opt.get("when", "")
|
|
122
|
+
if when:
|
|
123
|
+
lines.append(f" 适用: {when}")
|
|
124
|
+
|
|
125
|
+
guide = step_data.get("selection_guide", "")
|
|
126
|
+
if guide:
|
|
127
|
+
lines.append(f"\n{guide}")
|
|
128
|
+
|
|
129
|
+
lines.append("")
|
|
130
|
+
|
|
131
|
+
return "\n".join(lines)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class ConcernPackLoader:
|
|
135
|
+
"""
|
|
136
|
+
关注点增强包加载器
|
|
137
|
+
|
|
138
|
+
职责:
|
|
139
|
+
1. 从 templates/concerns/ 加载所有增强包定义
|
|
140
|
+
2. 根据任务描述匹配相关增强包
|
|
141
|
+
3. 提取角色增强提示词
|
|
142
|
+
4. 生成检查清单和决策框架摘要
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
def __init__(self, concerns_dir: Optional[str] = None):
|
|
146
|
+
if concerns_dir is None:
|
|
147
|
+
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
148
|
+
concerns_dir = os.path.join(base_dir, "templates", "concerns")
|
|
149
|
+
self.concerns_dir = os.path.realpath(concerns_dir)
|
|
150
|
+
self._packs: Dict[str, ConcernPack] = {}
|
|
151
|
+
self._loaded = False
|
|
152
|
+
self._lock = threading.Lock()
|
|
153
|
+
|
|
154
|
+
def _load_all_packs(self):
|
|
155
|
+
"""加载所有增强包"""
|
|
156
|
+
with self._lock:
|
|
157
|
+
if self._loaded:
|
|
158
|
+
return
|
|
159
|
+
|
|
160
|
+
if not os.path.isdir(self.concerns_dir):
|
|
161
|
+
logger.debug("Concerns directory not found: %s", self.concerns_dir)
|
|
162
|
+
self._loaded = True
|
|
163
|
+
return
|
|
164
|
+
|
|
165
|
+
for filename in os.listdir(self.concerns_dir):
|
|
166
|
+
if not filename.endswith((".yaml", ".yml")):
|
|
167
|
+
continue
|
|
168
|
+
|
|
169
|
+
filepath = os.path.join(self.concerns_dir, filename)
|
|
170
|
+
try:
|
|
171
|
+
pack = self._load_pack(filepath)
|
|
172
|
+
if pack:
|
|
173
|
+
self._packs[pack.concern_id] = pack
|
|
174
|
+
logger.debug("Loaded concern pack: %s (%s)", pack.concern_id, pack.name)
|
|
175
|
+
except Exception as e:
|
|
176
|
+
logger.warning("Failed to load concern pack %s: %s", filename, e)
|
|
177
|
+
|
|
178
|
+
self._loaded = True
|
|
179
|
+
logger.info("Loaded %d concern packs", len(self._packs))
|
|
180
|
+
|
|
181
|
+
def _load_pack(self, filepath: str) -> Optional[ConcernPack]:
|
|
182
|
+
"""加载单个增强包文件"""
|
|
183
|
+
try:
|
|
184
|
+
import yaml
|
|
185
|
+
except ImportError:
|
|
186
|
+
return self._load_pack_simple(filepath)
|
|
187
|
+
|
|
188
|
+
with open(filepath, "r", encoding="utf-8") as f:
|
|
189
|
+
data = yaml.safe_load(f)
|
|
190
|
+
|
|
191
|
+
if not data or not data.get("concern_id"):
|
|
192
|
+
return None
|
|
193
|
+
|
|
194
|
+
return ConcernPack(
|
|
195
|
+
concern_id=data["concern_id"],
|
|
196
|
+
name=data.get("name", data["concern_id"]),
|
|
197
|
+
version=data.get("version", "1.0"),
|
|
198
|
+
description=data.get("description", ""),
|
|
199
|
+
triggers=data.get("triggers", {}),
|
|
200
|
+
decision_framework=data.get("decision_framework", {}),
|
|
201
|
+
checklist=data.get("checklist", {}),
|
|
202
|
+
role_enhancements=data.get("role_enhancements", {}),
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
def _load_pack_simple(self, filepath: str) -> Optional[ConcernPack]:
|
|
206
|
+
"""无YAML依赖时的简单加载(JSON格式备选)"""
|
|
207
|
+
json_path = filepath.replace(".yaml", ".json").replace(".yml", ".json")
|
|
208
|
+
if os.path.exists(json_path):
|
|
209
|
+
import json
|
|
210
|
+
with open(json_path, "r", encoding="utf-8") as f:
|
|
211
|
+
data = json.load(f)
|
|
212
|
+
if data and data.get("concern_id"):
|
|
213
|
+
return ConcernPack(
|
|
214
|
+
concern_id=data["concern_id"],
|
|
215
|
+
name=data.get("name", data["concern_id"]),
|
|
216
|
+
version=data.get("version", "1.0"),
|
|
217
|
+
description=data.get("description", ""),
|
|
218
|
+
triggers=data.get("triggers", {}),
|
|
219
|
+
decision_framework=data.get("decision_framework", {}),
|
|
220
|
+
checklist=data.get("checklist", {}),
|
|
221
|
+
role_enhancements=data.get("role_enhancements", {}),
|
|
222
|
+
)
|
|
223
|
+
return None
|
|
224
|
+
|
|
225
|
+
def match_packs(self, task_description: str) -> List[ConcernPack]:
|
|
226
|
+
"""
|
|
227
|
+
根据任务描述匹配相关增强包
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
task_description: 任务描述文本
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
匹配到的增强包列表
|
|
234
|
+
"""
|
|
235
|
+
self._load_all_packs()
|
|
236
|
+
|
|
237
|
+
if not self._packs:
|
|
238
|
+
return []
|
|
239
|
+
|
|
240
|
+
task_lower = task_description.lower()
|
|
241
|
+
matched = []
|
|
242
|
+
|
|
243
|
+
for pack_id, pack in self._packs.items():
|
|
244
|
+
keywords = pack.triggers.get("keywords", [])
|
|
245
|
+
if not keywords:
|
|
246
|
+
continue
|
|
247
|
+
|
|
248
|
+
match_count = 0
|
|
249
|
+
for kw in keywords:
|
|
250
|
+
if kw.lower() in task_lower:
|
|
251
|
+
match_count += 1
|
|
252
|
+
|
|
253
|
+
if match_count > 0:
|
|
254
|
+
matched.append((match_count, pack))
|
|
255
|
+
|
|
256
|
+
matched.sort(key=lambda x: x[0], reverse=True)
|
|
257
|
+
|
|
258
|
+
result = [pack for _, pack in matched]
|
|
259
|
+
if result:
|
|
260
|
+
pack_names = ", ".join(p.name for p in result)
|
|
261
|
+
logger.info("Matched %d concern pack(s): %s", len(result), pack_names)
|
|
262
|
+
|
|
263
|
+
return result
|
|
264
|
+
|
|
265
|
+
def get_role_enhancements(self, packs: List[ConcernPack], role_id: str) -> str:
|
|
266
|
+
"""
|
|
267
|
+
获取指定角色的增强提示词
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
packs: 匹配到的增强包列表
|
|
271
|
+
role_id: 角色ID(如 security, architect, tester)
|
|
272
|
+
|
|
273
|
+
Returns:
|
|
274
|
+
合并后的增强提示词
|
|
275
|
+
"""
|
|
276
|
+
enhancements = []
|
|
277
|
+
|
|
278
|
+
for pack in packs:
|
|
279
|
+
enhancement = pack.role_enhancements.get(role_id, "")
|
|
280
|
+
text = self._extract_enhancement_text(enhancement)
|
|
281
|
+
if text:
|
|
282
|
+
enhancements.append(text)
|
|
283
|
+
|
|
284
|
+
if enhancements:
|
|
285
|
+
return "\n\n".join(enhancements)
|
|
286
|
+
return ""
|
|
287
|
+
|
|
288
|
+
def get_all_role_enhancements(self, packs: List[ConcernPack]) -> Dict[str, str]:
|
|
289
|
+
"""
|
|
290
|
+
获取所有角色的增强提示词
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
{role_id: enhancement_text} 字典
|
|
294
|
+
"""
|
|
295
|
+
result = {}
|
|
296
|
+
for pack in packs:
|
|
297
|
+
for role_id, enhancement in pack.role_enhancements.items():
|
|
298
|
+
text = self._extract_enhancement_text(enhancement)
|
|
299
|
+
if not text:
|
|
300
|
+
continue
|
|
301
|
+
if role_id in result:
|
|
302
|
+
result[role_id] += "\n\n" + text
|
|
303
|
+
else:
|
|
304
|
+
result[role_id] = text
|
|
305
|
+
return result
|
|
306
|
+
|
|
307
|
+
@staticmethod
|
|
308
|
+
def _extract_enhancement_text(enhancement) -> str:
|
|
309
|
+
"""从增强包数据中提取提示词文本"""
|
|
310
|
+
if isinstance(enhancement, str):
|
|
311
|
+
return enhancement
|
|
312
|
+
if isinstance(enhancement, dict):
|
|
313
|
+
return enhancement.get("extra_prompt", "")
|
|
314
|
+
return str(enhancement) if enhancement else ""
|
|
315
|
+
|
|
316
|
+
def get_combined_checklist(self, packs: List[ConcernPack]) -> str:
|
|
317
|
+
"""获取合并后的检查清单摘要"""
|
|
318
|
+
parts = []
|
|
319
|
+
for pack in packs:
|
|
320
|
+
summary = pack.get_checklist_summary()
|
|
321
|
+
if summary:
|
|
322
|
+
parts.append(summary)
|
|
323
|
+
return "\n".join(parts)
|
|
324
|
+
|
|
325
|
+
def get_combined_decision_framework(self, packs: List[ConcernPack]) -> str:
|
|
326
|
+
"""获取合并后的决策框架摘要"""
|
|
327
|
+
parts = []
|
|
328
|
+
for pack in packs:
|
|
329
|
+
summary = pack.get_decision_summary()
|
|
330
|
+
if summary:
|
|
331
|
+
parts.append(summary)
|
|
332
|
+
return "\n".join(parts)
|
|
333
|
+
|
|
334
|
+
def get_pack_info(self, packs: List[ConcernPack]) -> List[Dict[str, Any]]:
|
|
335
|
+
"""获取增强包基本信息列表"""
|
|
336
|
+
return [
|
|
337
|
+
{
|
|
338
|
+
"concern_id": pack.concern_id,
|
|
339
|
+
"name": pack.name,
|
|
340
|
+
"description": pack.description,
|
|
341
|
+
"matched_keywords": list(pack.triggers.get("keywords", []))[:5],
|
|
342
|
+
}
|
|
343
|
+
for pack in packs
|
|
344
|
+
]
|
|
345
|
+
|
|
346
|
+
def list_available_packs(self) -> List[Dict[str, str]]:
|
|
347
|
+
"""列出所有可用的增强包"""
|
|
348
|
+
self._load_all_packs()
|
|
349
|
+
return [
|
|
350
|
+
{"id": pack.concern_id, "name": pack.name, "description": pack.description}
|
|
351
|
+
for pack in self._packs.values()
|
|
352
|
+
]
|