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,483 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ PromptVariantGenerator - 提示词变体生成器(Skillify 闭环反哺)
5
+
6
+ 填补 Skillifier → 提示词系统 的数据流断裂:
7
+ 执行成功 → Skillifier 提取模式 → [本模块] → 候选提示词变体
8
+
9
+ WarmupManager 缓存 (A/B 测试)
10
+
11
+ 验证通过 → 晋升为默认模板变体
12
+
13
+ 核心能力:
14
+ 1. 从 SuccessPattern 生成候选 prompt 变体
15
+ 2. 变体质量评分(基于模式置信度/频率/角色匹配度)
16
+ 3. 缓存到 WarmupManager,支持 A/B 对比
17
+ 4. 变体晋升机制(candidate → promoted)
18
+
19
+ 与现有组件的关系:
20
+ - 输入: Skillifier.SuccessPattern(成功执行模式)
21
+ - 输出: 候选提示词文本 + 元数据
22
+ - 存储: WarmupManager.set_cache()(进程级缓存)
23
+ - 消费: PromptAssembler.assemble() 可读取并试用候选变体
24
+
25
+ 设计原则:
26
+ - 不修改原始 ROLE_TEMPLATES,只生成候选变体
27
+ - 变体必须经过验证才可晋升
28
+ - 自动降级:连续 N 次负面反馈则自动淘汰
29
+ """
30
+
31
+ import hashlib
32
+ import threading
33
+ from dataclasses import dataclass, field
34
+ from datetime import datetime, timedelta
35
+ from typing import Any, Dict, List, Optional, Tuple
36
+
37
+ try:
38
+ from .skillifier import SuccessPattern
39
+ except ImportError:
40
+ class SuccessPattern:
41
+ pattern_id = ""
42
+ name = ""
43
+ description = ""
44
+ steps_template = []
45
+ trigger_keywords = []
46
+ applicable_roles = []
47
+ frequency = 1
48
+ confidence = 0.5
49
+
50
+
51
+ @dataclass
52
+ class PromptVariant:
53
+ """
54
+ 提示词变体
55
+
56
+ Attributes:
57
+ variant_id: 变体唯一标识
58
+ role_id: 适用角色
59
+ source_pattern_id: 来源成功模式的 ID
60
+ prompt_text: 生成的提示词文本
61
+ status: 状态 (candidate/promoted/deprecated)
62
+ quality_score: 质量评分 [0, 100]
63
+ usage_count: 使用次数
64
+ positive_feedback: 正面反馈次数
65
+ negative_feedback: 负面反馈次数
66
+ created_at: 创建时间
67
+ promoted_at: 晋升时间(如有)
68
+ """
69
+ variant_id: str = field(default_factory=lambda: f"pv-{hashlib.md5(str(datetime.now()).encode()).hexdigest()[:12]}")
70
+ role_id: str = ""
71
+ source_pattern_id: str = ""
72
+ prompt_text: str = ""
73
+ status: str = "candidate"
74
+ quality_score: float = 0.0
75
+ usage_count: int = 0
76
+ positive_feedback: int = 0
77
+ negative_feedback: int = 0
78
+ created_at: datetime = field(default_factory=datetime.now)
79
+ promoted_at: Optional[datetime] = None
80
+ metadata: Dict[str, Any] = field(default_factory=dict)
81
+
82
+ def to_dict(self) -> Dict:
83
+ """
84
+ 序列化为字典(用于持久化或API返回)
85
+
86
+ Returns:
87
+ Dict: 包含 variant_id/role_id/status/quality_score/
88
+ usage_count/feedback_ratio/created_at 的字典
89
+ """
90
+ return {
91
+ "variant_id": self.variant_id,
92
+ "role_id": self.role_id,
93
+ "source_pattern_id": self.source_pattern_id,
94
+ "status": self.status,
95
+ "quality_score": round(self.quality_score, 1),
96
+ "usage_count": self.usage_count,
97
+ "positive_feedback": self.positive_feedback,
98
+ "negative_feedback": self.negative_feedback,
99
+ "feedback_ratio": round(self._feedback_ratio(), 2),
100
+ "created_at": self.created_at.isoformat(),
101
+ }
102
+
103
+ def _feedback_ratio(self) -> float:
104
+ total = self.positive_feedback + self.negative_feedback
105
+ if total == 0:
106
+ return 0.0
107
+ return self.positive_feedback / total
108
+
109
+
110
+ @dataclass
111
+ class VariantGenerationResult:
112
+ """
113
+ 变体生成结果
114
+
115
+ Attributes:
116
+ success: 是否成功生成变体
117
+ variant: 生成的 PromptVariant 对象(失败时为 None)
118
+ reason: 失败原因说明(成功时为空字符串)
119
+ """
120
+ success: bool
121
+ variant: Optional[PromptVariant] = None
122
+ reason: str = ""
123
+
124
+
125
+ class PromptVariantGenerator:
126
+ """
127
+ 提示词变体生成器
128
+
129
+ 将 Skillifier 的成功模式转化为可用的提示词变体,
130
+ 通过 WarmupManager 缓存实现 A/B 测试和自动晋升。
131
+
132
+ 使用示例:
133
+ gen = PromptVariantGenerator()
134
+ result = gen.generate_from_pattern(success_pattern)
135
+ if result.success:
136
+ gen.cache_variant(result.variant) # 存入缓存供 A/B 测试
137
+ # ... 后续使用中收集反馈 ...
138
+ gen.record_feedback(result.variant.variant_id, positive=True)
139
+ gen.try_promote(result.variant.variant_id) # 尝试晋升
140
+ """
141
+
142
+ MIN_CONFIDENCE = 0.7
143
+ MIN_FREQUENCY = 2
144
+ PROMOTION_THRESHOLD = 0.75
145
+ DEPRECATION_THRESHOLD = 0.35
146
+ MIN_USAGE_FOR_PROMOTION = 3
147
+
148
+ def __init__(self):
149
+ """初始化变体生成器"""
150
+ self._variants: Dict[str, PromptVariant] = {}
151
+ self._lock = threading.RLock()
152
+
153
+ def generate_from_pattern(self,
154
+ pattern: SuccessPattern,
155
+ base_template: str = "") -> VariantGenerationResult:
156
+ """
157
+ 从成功模式生成候选提示词变体
158
+
159
+ 生成逻辑:
160
+ 1. 质量门槛检查(置信度 >= 0.7 且频率 >= 2)
161
+ 2. 从模式步骤提取关键指令片段
162
+ 3. 组装为该角色的增强型提示词
163
+ 4. 计算质量评分
164
+
165
+ Args:
166
+ pattern: 成功执行模式(来自 Skillifier.analyze_history())
167
+ base_template: 该角色的基础提示词模板(可选,用于对比增强)
168
+
169
+ Returns:
170
+ VariantGenerationResult: 包含生成的变体或失败原因
171
+ """
172
+ if pattern.confidence < self.MIN_CONFIDENCE:
173
+ return VariantGenerationResult(
174
+ success=False,
175
+ reason=f"置信度不足: {pattern.confidence:.2f} < {self.MIN_CONFIDENCE}"
176
+ )
177
+
178
+ if pattern.frequency < self.MIN_FREQUENCY:
179
+ return VariantGenerationResult(
180
+ success=False,
181
+ reason=f"频率不足: {pattern.frequency} < {self.MIN_FREQUENCY}"
182
+ )
183
+
184
+ if not pattern.applicable_roles:
185
+ return VariantGenerationResult(
186
+ success=False,
187
+ reason="模式未关联任何角色"
188
+ )
189
+
190
+ role_id = pattern.applicable_roles[0]
191
+ prompt_text = self._assemble_variant_prompt(pattern, base_template)
192
+ quality = self._calculate_quality(pattern, prompt_text)
193
+
194
+ variant = PromptVariant(
195
+ role_id=role_id,
196
+ source_pattern_id=pattern.pattern_id,
197
+ prompt_text=prompt_text,
198
+ status="candidate",
199
+ quality_score=quality,
200
+ metadata={
201
+ "pattern_name": pattern.name,
202
+ "pattern_confidence": pattern.confidence,
203
+ "pattern_frequency": pattern.frequency,
204
+ "trigger_keywords": list(pattern.trigger_keywords)[:10],
205
+ "step_count": len(pattern.steps_template),
206
+ "generated_at": datetime.now().isoformat(),
207
+ },
208
+ )
209
+
210
+ with self._lock:
211
+ self._variants[variant.variant_id] = variant
212
+
213
+ return VariantGenerationResult(success=True, variant=variant)
214
+
215
+ def _assemble_variant_prompt(self,
216
+ pattern: SuccessPattern,
217
+ base_template: str) -> str:
218
+ """
219
+ 从模式组装变体提示词
220
+
221
+ 结构:
222
+ [角色特定头部]
223
+ [从模式提取的关键步骤指引]
224
+ [触发关键词作为上下文锚点]
225
+ [输出要求]
226
+
227
+ Args:
228
+ pattern: 成功模式
229
+ base_template: 基础模板(用于参考头部格式)
230
+
231
+ Returns:
232
+ str: 组装后的变体提示词
233
+ """
234
+ parts = []
235
+
236
+ header = f"=== {pattern.name or '优化提示词'} (来自 {pattern.frequency} 次成功经验) ===\n"
237
+ parts.append(header)
238
+
239
+ if pattern.steps_template:
240
+ parts.append("【推荐执行步骤】")
241
+ for i, step in enumerate(pattern.steps_template[:6], 1):
242
+ desc = step.description_template or step.action_type.value.replace("_", " ")
243
+ risk_note = f" ⚠风险{step.estimated_risk:.0%}" if step.estimated_risk > 0.5 else ""
244
+ req_mark = " *" if step.is_required else ""
245
+ parts.append(f" {i}. {desc}{risk_note}{req_mark}")
246
+ parts.append("")
247
+
248
+ if pattern.trigger_keywords:
249
+ kw_str = ", ".join(pattern.trigger_keywords[:8])
250
+ parts.append(f"【适用场景】包含以下关键词的任务: {kw_str}")
251
+ parts.append("")
252
+
253
+ output_guide = (
254
+ "【输出要求】\n"
255
+ "- 基于以上经验步骤执行\n"
256
+ "- 标注每步的决策依据\n"
257
+ "- 如遇偏差请说明原因"
258
+ )
259
+ parts.append(output_guide)
260
+
261
+ return "\n".join(parts)
262
+
263
+ def _calculate_quality(self, pattern: SuccessPattern,
264
+ prompt_text: str) -> float:
265
+ """
266
+ 计算变体质量评分 [0, 100]
267
+
268
+ 维度:
269
+ - 置信度贡献 (40%): 来自模式本身的置信度
270
+ - 频率贡献 (20%): 出现频率越高越可信
271
+ - 内容丰富度 (20%): 提示词长度和结构完整性
272
+ - 特异性 (15%): 触发关键词数量
273
+ - 步骤质量 (5%): 低风险步骤占比
274
+
275
+ Args:
276
+ pattern: 来源模式
277
+ prompt_text: 生成的提示词
278
+
279
+ Returns:
280
+ float: 质量评分 [0, 100]
281
+ """
282
+ confidence_score = pattern.confidence * 40
283
+
284
+ freq_score = min(20.0, pattern.frequency * 5)
285
+
286
+ length_score = min(20.0, len(prompt_text) / 20 * 5)
287
+ has_structure = "===" in prompt_text or "【" in prompt_text
288
+ structure_bonus = 5.0 if has_structure else 0.0
289
+ content_score = min(20.0, length_score + structure_bonus)
290
+
291
+ specificity_score = min(15.0, len(pattern.trigger_keywords) * 1.5)
292
+
293
+ safe_steps = sum(1 for ps in pattern.steps_template
294
+ if ps.estimated_risk < 0.5)
295
+ total_steps = max(len(pattern.steps_template), 1)
296
+ step_score = 5.0 * (safe_steps / total_steps)
297
+
298
+ return round(confidence_score + freq_score + content_score +
299
+ specificity_score + step_score, 1)
300
+
301
+ def get_variant(self, variant_id: str) -> Optional[PromptVariant]:
302
+ """
303
+ 按 ID 获取变体
304
+
305
+ Args:
306
+ variant_id: 变体 ID
307
+
308
+ Returns:
309
+ Optional[PromptVariant]: 变体对象,不存在返回 None
310
+ """
311
+ with self._lock:
312
+ return self._variants.get(variant_id)
313
+
314
+ def get_candidates_for_role(self, role_id: str) -> List[PromptVariant]:
315
+ """
316
+ 获取指定角色的所有候选变体(按质量排序)
317
+
318
+ Args:
319
+ role_id: 角色 ID
320
+
321
+ Returns:
322
+ List[PromptVariant]: 候选变体列表(质量分降序)
323
+ """
324
+ with self._lock:
325
+ candidates = [v for v in self._variants.values()
326
+ if v.role_id == role_id and v.status == "candidate"]
327
+ candidates.sort(key=lambda v: v.quality_score, reverse=True)
328
+ return candidates
329
+
330
+ def get_promoted_variants(self, role_id: str = "") -> List[PromptVariant]:
331
+ """
332
+ 获取已晋升的变体
333
+
334
+ Args:
335
+ role_id: 角色 ID(为空则返回全部已晋升变体)
336
+
337
+ Returns:
338
+ List[PromptVariant]: 已晋升变体列表
339
+ """
340
+ with self._lock:
341
+ results = [v for v in self._variants.values() if v.status == "promoted"]
342
+ if role_id:
343
+ results = [v for v in results if v.role_id == role_id]
344
+ return results
345
+
346
+ def record_usage(self, variant_id: str) -> bool:
347
+ """
348
+ 记录一次变体使用
349
+
350
+ Args:
351
+ variant_id: 变体 ID
352
+
353
+ Returns:
354
+ bool: 是否成功记录
355
+ """
356
+ with self._lock:
357
+ variant = self._variants.get(variant_id)
358
+ if variant:
359
+ variant.usage_count += 1
360
+ return True
361
+ return False
362
+
363
+ def record_feedback(self, variant_id: str,
364
+ positive: bool = True) -> bool:
365
+ """
366
+ 记录用户/AI 对变体的反馈
367
+
368
+ Args:
369
+ variant_id: 变体 ID
370
+ positive: True=正面反馈, False=负面反馈
371
+
372
+ Returns:
373
+ bool: 是否成功记录
374
+ """
375
+ with self._lock:
376
+ variant = self._variants.get(variant_id)
377
+ if not variant:
378
+ return False
379
+ if positive:
380
+ variant.positive_feedback += 1
381
+ else:
382
+ variant.negative_feedback += 1
383
+ return True
384
+
385
+ def try_promote(self, variant_id: str) -> Tuple[bool, str]:
386
+ """
387
+ 尝试将候选变体晋升为正式变体
388
+
389
+ 晋升条件(需同时满足):
390
+ 1. 使用次数 >= MIN_USAGE_FOR_PROMOTION (3次)
391
+ 2. 正面反馈率 >= PROMOTION_THRESHOLD (75%)
392
+ 3. 当前状态为 candidate
393
+
394
+ Args:
395
+ variant_id: 变体 ID
396
+
397
+ Returns:
398
+ Tuple[bool, str]: (是否晋升成功, 原因说明)
399
+ """
400
+ with self._lock:
401
+ variant = self._variants.get(variant_id)
402
+ if not variant:
403
+ return False, "变体不存在"
404
+
405
+ if variant.status != "candidate":
406
+ return False, f"当前状态非candidate: {variant.status}"
407
+
408
+ if variant.usage_count < self.MIN_USAGE_FOR_PROMOTION:
409
+ return False, f"使用次数不足: {variant.usage_count} < {self.MIN_USAGE_FOR_PROMOTION}"
410
+
411
+ ratio = variant._feedback_ratio()
412
+ if ratio < self.PROMOTION_THRESHOLD:
413
+ return False, f"正面反馈率不足: {ratio:.0%} < {self.PROMOTION_THRESHOLD:.0%}"
414
+
415
+ variant.status = "promoted"
416
+ variant.promoted_at = datetime.now()
417
+ return True, f"晋升成功 (使用{variant.usage_count}次, 反馈率{ratio:.0%})"
418
+
419
+ def auto_deprecate(self) -> List[str]:
420
+ """
421
+ 自动淘汰低质量候选变体
422
+
423
+ 淘汰条件:
424
+ 1. 负面反馈率 >= DEPRECATION_THRESHOLD (35%) 且使用 >= 3 次
425
+ 2. 或创建超过 30 天且无任何使用
426
+
427
+ Returns:
428
+ List[str]: 被淘汰的变体 ID 列表
429
+ """
430
+ deprecated = []
431
+ cutoff = datetime.now() - timedelta(days=30)
432
+
433
+ with self._lock:
434
+ for vid, variant in list(self._variants.items()):
435
+ if variant.status != "candidate":
436
+ continue
437
+
438
+ ratio = variant._feedback_ratio()
439
+ should_deprecate = False
440
+
441
+ if variant.usage_count >= 3 and ratio <= self.DEPRECATION_THRESHOLD:
442
+ should_deprecate = True
443
+ elif variant.created_at < cutoff and variant.usage_count == 0:
444
+ should_deprecate = True
445
+
446
+ if should_deprecate:
447
+ variant.status = "deprecated"
448
+ deprecated.append(vid)
449
+
450
+ return deprecated
451
+
452
+ def get_statistics(self) -> Dict[str, Any]:
453
+ """
454
+ 获取变体统计信息
455
+
456
+ Returns:
457
+ Dict[str, Any]: 统计字典
458
+ """
459
+ with self._lock:
460
+ all_vars = list(self._variants.values())
461
+ candidates = [v for v in all_vars if v.status == "candidate"]
462
+ promoted = [v for v in all_vars if v.status == "promoted"]
463
+ deprecated = [v for v in all_vars if v.status == "deprecated"]
464
+
465
+ total_usage = sum(v.usage_count for v in all_vars)
466
+ total_positive = sum(v.positive_feedback for v in all_vars)
467
+ total_negative = sum(v.negative_feedback for v in all_vars)
468
+
469
+ return {
470
+ "total_variants": len(all_vars),
471
+ "candidates": len(candidates),
472
+ "promoted": len(promoted),
473
+ "deprecated": len(deprecated),
474
+ "total_usage": total_usage,
475
+ "total_positive_feedback": total_positive,
476
+ "total_negative_feedback": total_negative,
477
+ "overall_feedback_ratio": round(
478
+ total_positive / max(total_positive + total_negative, 1), 2
479
+ ),
480
+ "avg_quality_score": round(
481
+ sum(v.quality_score for v in all_vars) / max(len(all_vars), 1), 1
482
+ ) if all_vars else 0.0,
483
+ }