super-dev 2.0.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.
- super_dev/__init__.py +11 -0
- super_dev/analyzer/__init__.py +34 -0
- super_dev/analyzer/analyzer.py +440 -0
- super_dev/analyzer/detectors.py +511 -0
- super_dev/analyzer/models.py +285 -0
- super_dev/cli.py +3257 -0
- super_dev/config/__init__.py +11 -0
- super_dev/config/frontend.py +557 -0
- super_dev/config/manager.py +281 -0
- super_dev/creators/__init__.py +26 -0
- super_dev/creators/creator.py +134 -0
- super_dev/creators/document_generator.py +2473 -0
- super_dev/creators/frontend_builder.py +371 -0
- super_dev/creators/implementation_builder.py +789 -0
- super_dev/creators/prompt_generator.py +289 -0
- super_dev/creators/requirement_parser.py +354 -0
- super_dev/creators/spec_builder.py +195 -0
- super_dev/deployers/__init__.py +20 -0
- super_dev/deployers/cicd.py +1269 -0
- super_dev/deployers/delivery.py +229 -0
- super_dev/deployers/migration.py +1032 -0
- super_dev/design/__init__.py +74 -0
- super_dev/design/aesthetics.py +530 -0
- super_dev/design/charts.py +396 -0
- super_dev/design/codegen.py +379 -0
- super_dev/design/engine.py +528 -0
- super_dev/design/generator.py +395 -0
- super_dev/design/landing.py +422 -0
- super_dev/design/tech_stack.py +524 -0
- super_dev/design/tokens.py +269 -0
- super_dev/design/ux_guide.py +391 -0
- super_dev/exceptions.py +119 -0
- super_dev/experts/__init__.py +19 -0
- super_dev/experts/service.py +161 -0
- super_dev/integrations/__init__.py +7 -0
- super_dev/integrations/manager.py +264 -0
- super_dev/orchestrator/__init__.py +12 -0
- super_dev/orchestrator/engine.py +958 -0
- super_dev/orchestrator/experts.py +423 -0
- super_dev/orchestrator/knowledge.py +352 -0
- super_dev/orchestrator/quality.py +356 -0
- super_dev/reviewers/__init__.py +17 -0
- super_dev/reviewers/code_review.py +471 -0
- super_dev/reviewers/quality_gate.py +964 -0
- super_dev/reviewers/redteam.py +881 -0
- super_dev/skills/__init__.py +7 -0
- super_dev/skills/manager.py +307 -0
- super_dev/specs/__init__.py +44 -0
- super_dev/specs/generator.py +264 -0
- super_dev/specs/manager.py +428 -0
- super_dev/specs/models.py +348 -0
- super_dev/specs/validator.py +415 -0
- super_dev/utils/__init__.py +11 -0
- super_dev/utils/logger.py +133 -0
- super_dev/web/api.py +1402 -0
- super_dev-2.0.0.dist-info/METADATA +252 -0
- super_dev-2.0.0.dist-info/RECORD +61 -0
- super_dev-2.0.0.dist-info/WHEEL +5 -0
- super_dev-2.0.0.dist-info/entry_points.txt +2 -0
- super_dev-2.0.0.dist-info/licenses/LICENSE +21 -0
- super_dev-2.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Skill 安装管理器
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import shutil
|
|
8
|
+
import subprocess # nosec B404
|
|
9
|
+
import tempfile
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class SkillInstallResult:
|
|
16
|
+
name: str
|
|
17
|
+
target: str
|
|
18
|
+
path: Path
|
|
19
|
+
source: str
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SkillManager:
|
|
23
|
+
"""跨平台 AI Coding 工具 Skill 管理"""
|
|
24
|
+
|
|
25
|
+
TARGET_PATHS = {
|
|
26
|
+
"claude-code": ".claude/skills",
|
|
27
|
+
"codex-cli": ".codex/skills",
|
|
28
|
+
"opencode": ".opencode/skills",
|
|
29
|
+
"cursor": ".super-dev/skills/cursor",
|
|
30
|
+
"qoder": ".super-dev/skills/qoder",
|
|
31
|
+
"trae": ".super-dev/skills/trae",
|
|
32
|
+
"codebuddy": ".super-dev/skills/codebuddy",
|
|
33
|
+
"antigravity": ".super-dev/skills/antigravity",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
def __init__(self, project_dir: Path):
|
|
37
|
+
self.project_dir = Path(project_dir).resolve()
|
|
38
|
+
|
|
39
|
+
def list_targets(self) -> list[str]:
|
|
40
|
+
return list(self.TARGET_PATHS.keys())
|
|
41
|
+
|
|
42
|
+
def list_installed(self, target: str) -> list[str]:
|
|
43
|
+
base = self._target_dir(target)
|
|
44
|
+
if not base.exists():
|
|
45
|
+
return []
|
|
46
|
+
return sorted(
|
|
47
|
+
d.name for d in base.iterdir() if d.is_dir() and (d / "SKILL.md").exists()
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
def install(
|
|
51
|
+
self,
|
|
52
|
+
source: str,
|
|
53
|
+
target: str,
|
|
54
|
+
name: str | None = None,
|
|
55
|
+
force: bool = False,
|
|
56
|
+
) -> SkillInstallResult:
|
|
57
|
+
"""安装 skill 到指定 target"""
|
|
58
|
+
base = self._target_dir(target)
|
|
59
|
+
base.mkdir(parents=True, exist_ok=True)
|
|
60
|
+
|
|
61
|
+
if self._is_git_source(source):
|
|
62
|
+
return self._install_from_git(source=source, target=target, name=name, force=force)
|
|
63
|
+
|
|
64
|
+
source_path = Path(source).expanduser().resolve()
|
|
65
|
+
if source_path.is_dir():
|
|
66
|
+
return self._install_from_directory(
|
|
67
|
+
source_dir=source_path,
|
|
68
|
+
target=target,
|
|
69
|
+
name=name,
|
|
70
|
+
force=force,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# 内置 skill
|
|
74
|
+
if source == "super-dev":
|
|
75
|
+
skill_name = name or "super-dev"
|
|
76
|
+
target_dir = base / skill_name
|
|
77
|
+
self._prepare_target_dir(target_dir, force=force)
|
|
78
|
+
self._write_builtin_skill(target_dir, skill_name)
|
|
79
|
+
return SkillInstallResult(
|
|
80
|
+
name=skill_name,
|
|
81
|
+
target=target,
|
|
82
|
+
path=target_dir,
|
|
83
|
+
source="builtin",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
raise FileNotFoundError(
|
|
87
|
+
f"Skill source not found: {source}. Use a local directory, git url, or 'super-dev'."
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
def uninstall(self, name: str, target: str) -> Path:
|
|
91
|
+
target_dir = self._target_dir(target) / name
|
|
92
|
+
if not target_dir.exists():
|
|
93
|
+
raise FileNotFoundError(f"Skill not found: {name} ({target})")
|
|
94
|
+
shutil.rmtree(target_dir)
|
|
95
|
+
return target_dir
|
|
96
|
+
|
|
97
|
+
def _target_dir(self, target: str) -> Path:
|
|
98
|
+
relative = self.TARGET_PATHS.get(target)
|
|
99
|
+
if relative is None:
|
|
100
|
+
raise ValueError(f"Unsupported target: {target}")
|
|
101
|
+
return self.project_dir / relative
|
|
102
|
+
|
|
103
|
+
def _is_git_source(self, source: str) -> bool:
|
|
104
|
+
return source.startswith("http://") or source.startswith("https://") or source.endswith(".git")
|
|
105
|
+
|
|
106
|
+
def _validate_git_source(self, source: str) -> None:
|
|
107
|
+
if source.startswith("-"):
|
|
108
|
+
raise ValueError("Invalid git source")
|
|
109
|
+
|
|
110
|
+
def _install_from_git(
|
|
111
|
+
self,
|
|
112
|
+
source: str,
|
|
113
|
+
target: str,
|
|
114
|
+
name: str | None,
|
|
115
|
+
force: bool,
|
|
116
|
+
) -> SkillInstallResult:
|
|
117
|
+
self._validate_git_source(source)
|
|
118
|
+
git_executable = shutil.which("git")
|
|
119
|
+
if not git_executable:
|
|
120
|
+
raise FileNotFoundError("git executable not found in PATH")
|
|
121
|
+
|
|
122
|
+
with tempfile.TemporaryDirectory(prefix="super-dev-skill-") as temp_dir:
|
|
123
|
+
temp_path = Path(temp_dir)
|
|
124
|
+
clone_dir = temp_path / "repo"
|
|
125
|
+
subprocess.run(
|
|
126
|
+
[git_executable, "clone", "--depth", "1", "--", source, str(clone_dir)],
|
|
127
|
+
check=True,
|
|
128
|
+
capture_output=True,
|
|
129
|
+
text=True,
|
|
130
|
+
) # nosec B603
|
|
131
|
+
|
|
132
|
+
skill_dirs = self._find_skill_dirs(clone_dir)
|
|
133
|
+
if not skill_dirs:
|
|
134
|
+
raise FileNotFoundError("No SKILL.md found in git repository")
|
|
135
|
+
|
|
136
|
+
selected_dir = self._select_skill_dir(skill_dirs, name)
|
|
137
|
+
return self._install_from_directory(
|
|
138
|
+
source_dir=selected_dir,
|
|
139
|
+
target=target,
|
|
140
|
+
name=name or selected_dir.name,
|
|
141
|
+
force=force,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
def _install_from_directory(
|
|
145
|
+
self,
|
|
146
|
+
source_dir: Path,
|
|
147
|
+
target: str,
|
|
148
|
+
name: str | None,
|
|
149
|
+
force: bool,
|
|
150
|
+
) -> SkillInstallResult:
|
|
151
|
+
if not (source_dir / "SKILL.md").exists():
|
|
152
|
+
raise FileNotFoundError(f"Directory does not contain SKILL.md: {source_dir}")
|
|
153
|
+
|
|
154
|
+
skill_name = name or source_dir.name
|
|
155
|
+
target_dir = self._target_dir(target) / skill_name
|
|
156
|
+
self._prepare_target_dir(target_dir, force=force)
|
|
157
|
+
shutil.copytree(source_dir, target_dir)
|
|
158
|
+
return SkillInstallResult(
|
|
159
|
+
name=skill_name,
|
|
160
|
+
target=target,
|
|
161
|
+
path=target_dir,
|
|
162
|
+
source=str(source_dir),
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
def _prepare_target_dir(self, target_dir: Path, force: bool) -> None:
|
|
166
|
+
if target_dir.exists():
|
|
167
|
+
if not force:
|
|
168
|
+
raise FileExistsError(f"Target skill already exists: {target_dir}")
|
|
169
|
+
shutil.rmtree(target_dir)
|
|
170
|
+
|
|
171
|
+
def _find_skill_dirs(self, root: Path) -> list[Path]:
|
|
172
|
+
dirs = []
|
|
173
|
+
for file_path in root.rglob("SKILL.md"):
|
|
174
|
+
parent = file_path.parent
|
|
175
|
+
if ".git" in parent.parts:
|
|
176
|
+
continue
|
|
177
|
+
dirs.append(parent)
|
|
178
|
+
return dirs
|
|
179
|
+
|
|
180
|
+
def _select_skill_dir(self, skill_dirs: list[Path], name: str | None) -> Path:
|
|
181
|
+
if name is None:
|
|
182
|
+
return skill_dirs[0]
|
|
183
|
+
for skill_dir in skill_dirs:
|
|
184
|
+
if skill_dir.name == name:
|
|
185
|
+
return skill_dir
|
|
186
|
+
raise FileNotFoundError(f"Skill '{name}' not found in repository")
|
|
187
|
+
|
|
188
|
+
def _write_builtin_skill(self, target_dir: Path, skill_name: str) -> None:
|
|
189
|
+
target_dir.mkdir(parents=True, exist_ok=True)
|
|
190
|
+
skill_content = f"""# {skill_name} - Super Dev AI Coding Skill
|
|
191
|
+
|
|
192
|
+
> 版本: 2.0.0 | 适用工具: Claude Code, Codex CLI, OpenCode, Cursor, Antigravity 等所有 AI Coding 工具
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 🎯 Skill 角色定义
|
|
197
|
+
|
|
198
|
+
你是一个由 **10 位顶级专家**组成的 AI 开发战队成员。当用户调用 Super Dev 时,你需要根据任务类型自动切换专家角色:
|
|
199
|
+
|
|
200
|
+
| 专家角色 | 触发场景 | 核心职责 |
|
|
201
|
+
|:---|:---|:---|
|
|
202
|
+
| **PM(产品经理)** | 需求分析、PRD 生成 | 需求拆解、用户故事、验收标准 |
|
|
203
|
+
| **ARCHITECT(架构师)** | 系统设计、技术选型 | 架构图、技术栈选型、API 契约 |
|
|
204
|
+
| **UI(UI 设计师)** | 视觉设计、组件规范 | 设计系统、色彩规范、组件库 |
|
|
205
|
+
| **UX(UX 设计师)** | 交互设计、用户体验 | 用户旅程、信息架构、可用性 |
|
|
206
|
+
| **SECURITY(安全专家)** | 红队审查、漏洞检测 | OWASP Top 10、威胁建模 |
|
|
207
|
+
| **CODE(代码专家)** | 代码实现、最佳实践 | 设计模式、代码审查、重构 |
|
|
208
|
+
| **DBA(数据库专家)** | 数据库设计、优化 | 表结构、索引策略、迁移脚本 |
|
|
209
|
+
| **QA(质量保证)** | 测试策略、质量门禁 | 测试计划、覆盖率、质量评分 |
|
|
210
|
+
| **DEVOPS(运维工程师)** | CI/CD、部署配置 | 流水线、容器化、监控告警 |
|
|
211
|
+
| **RCA(根因分析)** | 故障复盘、风险识别 | 根因分析、改进建议、预防措施 |
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## 🚀 12 阶段开发流水线
|
|
216
|
+
|
|
217
|
+
接到任务后,**严格按以下顺序执行**:
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
第 0 阶段 需求增强 → 解析需求 + 注入知识库 + 联网检索
|
|
221
|
+
第 1 阶段 文档生成 → PRD + 架构设计 + UI/UX 文档
|
|
222
|
+
第 2 阶段 前端骨架 → 先交付可演示前端(前端先行原则)
|
|
223
|
+
第 3 阶段 Spec 创建 → OpenSpec 风格规范 + 任务列表
|
|
224
|
+
第 4 阶段 实现骨架 → 前后端目录结构 + API 契约
|
|
225
|
+
第 5 阶段 红队审查 → 安全 + 性能 + 架构三维审查
|
|
226
|
+
第 6 阶段 质量门禁 → 统一阈值(80+)
|
|
227
|
+
第 7 阶段 代码审查 → 生成代码审查指南
|
|
228
|
+
第 8 阶段 AI 提示词 → 生成给 AI 开发的提示词
|
|
229
|
+
第 9 阶段 CI/CD → 5 大平台配置(GitHub/GitLab/Jenkins/Azure/Bitbucket)
|
|
230
|
+
第 10 阶段 部署修复模板 → 环境变量示例 + 平台检查清单
|
|
231
|
+
第 11 阶段 交付收敛 → 6 种 ORM 迁移脚本 + 交付包(manifest/report/zip)
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## 📋 开始前必读(强制)
|
|
237
|
+
|
|
238
|
+
**在写任何一行代码之前**,必须先读取以下文档:
|
|
239
|
+
|
|
240
|
+
1. `output/*-prd.md` — 产品需求文档(功能边界、验收标准)
|
|
241
|
+
2. `output/*-architecture.md` — 架构设计文档(技术栈、API 规范)
|
|
242
|
+
3. `output/*-uiux.md` — UI/UX 设计文档(设计系统、组件规范)
|
|
243
|
+
4. `output/*-execution-plan.md` — 执行路线图(阶段任务和里程碑)
|
|
244
|
+
5. `.super-dev/changes/*/tasks.md` — Spec 任务列表(逐项实现)
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## ⚡ 执行规则
|
|
249
|
+
|
|
250
|
+
### 前端先行原则
|
|
251
|
+
- 先完成前端骨架并可演示,再实现后端 API
|
|
252
|
+
- 前端使用 Mock/占位数据,完成视觉验证后再联调
|
|
253
|
+
- UI 严格遵循 `output/*-uiux.md` 的设计规范
|
|
254
|
+
|
|
255
|
+
### 代码质量规则
|
|
256
|
+
- 禁止使用 emoji 作为图标(用 Lucide/Heroicons/Tabler 等图标库)
|
|
257
|
+
- 所有用户输入必须验证(防 SQL 注入、XSS)
|
|
258
|
+
- 使用参数化查询,禁止字符串拼接 SQL
|
|
259
|
+
- 测试覆盖率目标 ≥ 80%
|
|
260
|
+
- 遵循 Conventional Commits 提交规范
|
|
261
|
+
|
|
262
|
+
### 质量门禁规则
|
|
263
|
+
- **统一标准**:质量分 **≥ 80 分** 才可通过
|
|
264
|
+
- 必检项(文档/安全/性能/测试)出现失败即阻断
|
|
265
|
+
- 交付前运行:`super-dev quality --type all`
|
|
266
|
+
- 红队发现 Critical 问题必须修复后才能继续
|
|
267
|
+
|
|
268
|
+
### 任务跟踪规则
|
|
269
|
+
- 每完成一个任务,在 `.super-dev/changes/*/tasks.md` 标记 `[x]`
|
|
270
|
+
- 遇到不清楚的地方,优先查阅架构文档,再看 PRD
|
|
271
|
+
- 不要自行扩展需求范围,严格按 Spec 实现
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 🔧 常用命令参考
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
# 查看当前 Spec
|
|
279
|
+
super-dev spec view
|
|
280
|
+
|
|
281
|
+
# 运行质量检查
|
|
282
|
+
super-dev quality --type all
|
|
283
|
+
|
|
284
|
+
# 生成 CI/CD 配置
|
|
285
|
+
super-dev deploy --cicd github
|
|
286
|
+
|
|
287
|
+
# 调用专家
|
|
288
|
+
super-dev expert SECURITY "审查登录模块"
|
|
289
|
+
super-dev expert ARCHITECT "评审微服务拆分方案"
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## ✅ 交付标准
|
|
295
|
+
|
|
296
|
+
所有任务完成后,确认:
|
|
297
|
+
|
|
298
|
+
- [ ] 所有 `.super-dev/changes/*/tasks.md` 中的任务标记为 `[x]`
|
|
299
|
+
- [ ] 前端可正常演示,无控制台报错
|
|
300
|
+
- [ ] 后端 API 联调通过
|
|
301
|
+
- [ ] 数据库迁移脚本可正常执行
|
|
302
|
+
- [ ] `output/delivery/*` 交付包状态为 ready
|
|
303
|
+
- [ ] CI/CD 流水线配置完整
|
|
304
|
+
- [ ] 质量门禁通过(`super-dev quality --type all`)
|
|
305
|
+
- [ ] 红队发现的 Critical/High 问题均已修复
|
|
306
|
+
"""
|
|
307
|
+
(target_dir / "SKILL.md").write_text(skill_content, encoding="utf-8")
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Super Dev Spec-Driven Development (SDD) 模块
|
|
3
|
+
|
|
4
|
+
开发:Excellent(11964948@qq.com)
|
|
5
|
+
功能:规范驱动开发工具,类似 OpenSpec
|
|
6
|
+
作用:在开发前达成规范共识,让 AI 遵循规范而非随意发挥
|
|
7
|
+
创建时间:2025-12-30
|
|
8
|
+
最后修改:2025-12-30
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from .generator import SpecGenerator
|
|
12
|
+
from .manager import ChangeManager, SpecManager
|
|
13
|
+
from .models import (
|
|
14
|
+
Change,
|
|
15
|
+
ChangeStatus,
|
|
16
|
+
DeltaType,
|
|
17
|
+
Proposal,
|
|
18
|
+
Requirement,
|
|
19
|
+
Scenario,
|
|
20
|
+
Spec,
|
|
21
|
+
SpecDelta,
|
|
22
|
+
Task,
|
|
23
|
+
TaskStatus,
|
|
24
|
+
)
|
|
25
|
+
from .validator import SpecValidator, ValidationError, ValidationResult
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"Spec",
|
|
29
|
+
"Requirement",
|
|
30
|
+
"Scenario",
|
|
31
|
+
"Change",
|
|
32
|
+
"ChangeStatus",
|
|
33
|
+
"Proposal",
|
|
34
|
+
"Task",
|
|
35
|
+
"TaskStatus",
|
|
36
|
+
"DeltaType",
|
|
37
|
+
"SpecDelta",
|
|
38
|
+
"SpecManager",
|
|
39
|
+
"ChangeManager",
|
|
40
|
+
"SpecGenerator",
|
|
41
|
+
"SpecValidator",
|
|
42
|
+
"ValidationResult",
|
|
43
|
+
"ValidationError",
|
|
44
|
+
]
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Spec-Driven Development 生成器
|
|
3
|
+
|
|
4
|
+
开发:Excellent(11964948@qq.com)
|
|
5
|
+
功能:从需求或 PRD 自动生成规范和变更提案
|
|
6
|
+
作用:辅助用户快速创建 SDD 文档
|
|
7
|
+
创建时间:2025-12-30
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from .manager import ChangeManager, SpecManager
|
|
13
|
+
from .models import (
|
|
14
|
+
Change,
|
|
15
|
+
ChangeStatus,
|
|
16
|
+
DeltaType,
|
|
17
|
+
Proposal,
|
|
18
|
+
Requirement,
|
|
19
|
+
Scenario,
|
|
20
|
+
SpecDelta,
|
|
21
|
+
Task,
|
|
22
|
+
TaskStatus,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SpecGenerator:
|
|
27
|
+
"""规范生成器 - 从需求自动生成规范"""
|
|
28
|
+
|
|
29
|
+
def __init__(self, project_dir: Path | str):
|
|
30
|
+
"""初始化生成器"""
|
|
31
|
+
self.project_dir = Path(project_dir).resolve()
|
|
32
|
+
self.spec_manager = SpecManager(self.project_dir)
|
|
33
|
+
self.change_manager = ChangeManager(self.project_dir)
|
|
34
|
+
|
|
35
|
+
def create_change(
|
|
36
|
+
self,
|
|
37
|
+
change_id: str,
|
|
38
|
+
title: str,
|
|
39
|
+
description: str,
|
|
40
|
+
motivation: str = "",
|
|
41
|
+
impact: str = ""
|
|
42
|
+
) -> Change:
|
|
43
|
+
"""创建新变更提案"""
|
|
44
|
+
change = Change(
|
|
45
|
+
id=change_id,
|
|
46
|
+
title=title,
|
|
47
|
+
status=ChangeStatus.PROPOSED,
|
|
48
|
+
proposal=Proposal(
|
|
49
|
+
title=title,
|
|
50
|
+
description=description,
|
|
51
|
+
motivation=motivation,
|
|
52
|
+
impact=impact
|
|
53
|
+
)
|
|
54
|
+
)
|
|
55
|
+
self.change_manager.save_change(change)
|
|
56
|
+
return change
|
|
57
|
+
|
|
58
|
+
def add_requirement_to_change(
|
|
59
|
+
self,
|
|
60
|
+
change_id: str,
|
|
61
|
+
spec_name: str,
|
|
62
|
+
requirement_name: str,
|
|
63
|
+
description: str,
|
|
64
|
+
scenarios: list[dict] | None = None,
|
|
65
|
+
delta_type: DeltaType = DeltaType.ADDED
|
|
66
|
+
) -> SpecDelta:
|
|
67
|
+
"""向变更添加需求"""
|
|
68
|
+
change = self.change_manager.load_change(change_id)
|
|
69
|
+
if not change:
|
|
70
|
+
raise FileNotFoundError(f"变更不存在: {change_id}")
|
|
71
|
+
|
|
72
|
+
# 创建场景
|
|
73
|
+
req_scenarios = []
|
|
74
|
+
if scenarios:
|
|
75
|
+
for s in scenarios:
|
|
76
|
+
req_scenarios.append(Scenario(
|
|
77
|
+
given=s.get("given", ""),
|
|
78
|
+
when=s.get("when", ""),
|
|
79
|
+
then=s.get("then", "")
|
|
80
|
+
))
|
|
81
|
+
|
|
82
|
+
requirement = Requirement(
|
|
83
|
+
name=requirement_name,
|
|
84
|
+
description=description,
|
|
85
|
+
keyword="SHALL"
|
|
86
|
+
)
|
|
87
|
+
requirement.scenarios = req_scenarios
|
|
88
|
+
|
|
89
|
+
# 查找或创建增量
|
|
90
|
+
for delta in change.spec_deltas:
|
|
91
|
+
if delta.spec_name == spec_name:
|
|
92
|
+
delta.requirements.append(requirement)
|
|
93
|
+
break
|
|
94
|
+
else:
|
|
95
|
+
delta = SpecDelta(
|
|
96
|
+
spec_name=spec_name,
|
|
97
|
+
delta_type=delta_type,
|
|
98
|
+
requirements=[requirement]
|
|
99
|
+
)
|
|
100
|
+
change.spec_deltas.append(delta)
|
|
101
|
+
|
|
102
|
+
self.change_manager.save_change(change)
|
|
103
|
+
return delta
|
|
104
|
+
|
|
105
|
+
def generate_tasks_from_requirements(
|
|
106
|
+
self,
|
|
107
|
+
change_id: str,
|
|
108
|
+
tech_stack: dict | None = None
|
|
109
|
+
) -> list[Task]:
|
|
110
|
+
"""从需求自动生成任务"""
|
|
111
|
+
change = self.change_manager.load_change(change_id)
|
|
112
|
+
if not change:
|
|
113
|
+
raise FileNotFoundError(f"变更不存在: {change_id}")
|
|
114
|
+
|
|
115
|
+
tasks = []
|
|
116
|
+
task_id = [1, 1] # [major, minor]
|
|
117
|
+
|
|
118
|
+
# 根据规范增量生成任务
|
|
119
|
+
for delta in change.spec_deltas:
|
|
120
|
+
for req in delta.requirements:
|
|
121
|
+
# 为每个需求生成实现任务
|
|
122
|
+
task_id[1] += 1
|
|
123
|
+
task = Task(
|
|
124
|
+
id=f"{task_id[0]}.{task_id[1]}",
|
|
125
|
+
title=f"Implement: {req.name}",
|
|
126
|
+
description=req.description,
|
|
127
|
+
status=TaskStatus.PENDING,
|
|
128
|
+
spec_refs=[f"{delta.spec_name}::{req.name}"]
|
|
129
|
+
)
|
|
130
|
+
tasks.append(task)
|
|
131
|
+
|
|
132
|
+
# 添加测试任务
|
|
133
|
+
task_id[0] += 1
|
|
134
|
+
task_id[1] = 0
|
|
135
|
+
for delta in change.spec_deltas:
|
|
136
|
+
task_id[1] += 1
|
|
137
|
+
task = Task(
|
|
138
|
+
id=f"{task_id[0]}.{task_id[1]}",
|
|
139
|
+
title=f"Test: {delta.spec_name} requirements",
|
|
140
|
+
description=f"Verify all scenarios for {delta.spec_name}",
|
|
141
|
+
status=TaskStatus.PENDING,
|
|
142
|
+
spec_refs=[delta.spec_name]
|
|
143
|
+
)
|
|
144
|
+
tasks.append(task)
|
|
145
|
+
|
|
146
|
+
# 更新变更
|
|
147
|
+
change.tasks = tasks
|
|
148
|
+
self.change_manager.save_change(change)
|
|
149
|
+
|
|
150
|
+
return tasks
|
|
151
|
+
|
|
152
|
+
def propose_from_prd(self, prd_content: str) -> Change:
|
|
153
|
+
"""从 PRD 内容生成变更提案 (简化版)"""
|
|
154
|
+
# 解析 PRD 提取关键信息
|
|
155
|
+
lines = prd_content.split("\n")
|
|
156
|
+
|
|
157
|
+
title = "Feature from PRD"
|
|
158
|
+
description = ""
|
|
159
|
+
features = []
|
|
160
|
+
|
|
161
|
+
current_section = None
|
|
162
|
+
for line in lines:
|
|
163
|
+
if line.startswith("# "):
|
|
164
|
+
title = line[2:].strip()
|
|
165
|
+
elif line.startswith("## 概述") or line.startswith("## Overview"):
|
|
166
|
+
current_section = "overview"
|
|
167
|
+
elif line.startswith("## 功能需求") or line.startswith("## Features"):
|
|
168
|
+
current_section = "features"
|
|
169
|
+
elif line.startswith("- ") or line.startswith("* "):
|
|
170
|
+
if current_section == "features":
|
|
171
|
+
features.append(line[2:].strip())
|
|
172
|
+
elif current_section == "overview" and line.strip():
|
|
173
|
+
description += line.strip() + "\n"
|
|
174
|
+
|
|
175
|
+
# 创建变更 ID
|
|
176
|
+
change_id = title.lower().replace(" ", "-").replace("/", "-")[:50]
|
|
177
|
+
|
|
178
|
+
change = self.create_change(
|
|
179
|
+
change_id=change_id,
|
|
180
|
+
title=title,
|
|
181
|
+
description=description.strip(),
|
|
182
|
+
motivation="Derived from PRD",
|
|
183
|
+
impact=", ".join(features[:3])
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
return change
|
|
187
|
+
|
|
188
|
+
def init_sdd(self):
|
|
189
|
+
"""初始化 SDD 目录结构"""
|
|
190
|
+
self.spec_manager.init()
|
|
191
|
+
self.change_manager.init()
|
|
192
|
+
|
|
193
|
+
# 创建 AGENTS.md 文件
|
|
194
|
+
agents_path = self.project_dir / ".super-dev" / "AGENTS.md"
|
|
195
|
+
if not agents_path.exists():
|
|
196
|
+
agents_content = """# Super Dev Spec-Driven Development
|
|
197
|
+
|
|
198
|
+
This project uses Super Dev's Spec-Driven Development (SDD) workflow.
|
|
199
|
+
|
|
200
|
+
## Workflow
|
|
201
|
+
|
|
202
|
+
1. **Propose**: Create a change proposal with `super-dev spec propose <id>`
|
|
203
|
+
2. **Review**: Review the generated specs and tasks
|
|
204
|
+
3. **Implement**: Work through the tasks with AI assistance
|
|
205
|
+
4. **Archive**: Archive the change with `super-dev spec archive <id>`
|
|
206
|
+
|
|
207
|
+
## Directory Structure
|
|
208
|
+
|
|
209
|
+
```
|
|
210
|
+
.super-dev/
|
|
211
|
+
├── specs/ # Current specifications (source of truth)
|
|
212
|
+
├── changes/ # Proposed changes (proposals + tasks + deltas)
|
|
213
|
+
└── archive/ # Archived changes
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Commands
|
|
217
|
+
|
|
218
|
+
- `super-dev spec list` - List all changes
|
|
219
|
+
- `super-dev spec show <id>` - Show change details
|
|
220
|
+
- `super-dev spec propose <id>` - Create new change proposal
|
|
221
|
+
- `super-dev spec apply <id>` - Start implementing a change
|
|
222
|
+
- `super-dev spec archive <id>` - Archive completed change
|
|
223
|
+
|
|
224
|
+
## AI Integration
|
|
225
|
+
|
|
226
|
+
When working with AI coding assistants, reference the change:
|
|
227
|
+
|
|
228
|
+
"Please help me implement change `add-user-auth`. The tasks are in `.super-dev/changes/add-user-auth/tasks.md` and the specs are in `.super-dev/changes/add-user-auth/specs/`."
|
|
229
|
+
"""
|
|
230
|
+
agents_path.write_text(agents_content, encoding="utf-8")
|
|
231
|
+
|
|
232
|
+
# 创建 project.md 模板
|
|
233
|
+
project_path = self.project_dir / ".super-dev" / "project.md"
|
|
234
|
+
if not project_path.exists():
|
|
235
|
+
project_content = """# Project Context
|
|
236
|
+
|
|
237
|
+
## Purpose
|
|
238
|
+
_What is this project about?_
|
|
239
|
+
|
|
240
|
+
## Tech Stack
|
|
241
|
+
- **Language**: _e.g., Python, JavaScript, Go_
|
|
242
|
+
- **Framework**: _e.g., FastAPI, Express, Gin_
|
|
243
|
+
- **Database**: _e.g., PostgreSQL, MongoDB_
|
|
244
|
+
- **Frontend**: _e.g., React, Vue, None_
|
|
245
|
+
|
|
246
|
+
## Conventions
|
|
247
|
+
### Code Style
|
|
248
|
+
- _e.g., PEP 8 for Python, ESLint + Prettier for JS_
|
|
249
|
+
|
|
250
|
+
### Git Flow
|
|
251
|
+
- _e.g., main for production, develop for integration_
|
|
252
|
+
|
|
253
|
+
### Testing
|
|
254
|
+
- _e.g., pytest with >80% coverage required_
|
|
255
|
+
|
|
256
|
+
## Architecture Notes
|
|
257
|
+
_Add architectural patterns and decisions here_
|
|
258
|
+
|
|
259
|
+
## Domain Knowledge
|
|
260
|
+
_Add domain-specific information here_
|
|
261
|
+
"""
|
|
262
|
+
project_path.write_text(project_content, encoding="utf-8")
|
|
263
|
+
|
|
264
|
+
return agents_path, project_path
|