sdd-skills 1.0.0
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.
- package/LICENSE +21 -0
- package/README.md +204 -0
- package/config/dingtalk-config.template.json +5 -0
- package/docs/workflow-guide.md +836 -0
- package/install.js +272 -0
- package/package.json +42 -0
- package/skills/backend-engineer/SKILL.md +373 -0
- package/skills/code-reviewer/SKILL.md +535 -0
- package/skills/frontend-engineer/SKILL.md +551 -0
- package/skills/git-engineer/SKILL.md +556 -0
- package/skills/notifier/SKILL.md +462 -0
- package/skills/sae/SKILL.md +200 -0
- package/skills/tester/SKILL.md +466 -0
- package/uninstall.js +226 -0
|
@@ -0,0 +1,836 @@
|
|
|
1
|
+
# SDD 工作流指南
|
|
2
|
+
|
|
3
|
+
本文档详细介绍 SDD (Spec-Driven Development) 工作流的完整流程。
|
|
4
|
+
|
|
5
|
+
## 目录
|
|
6
|
+
|
|
7
|
+
- [工作流概述](#工作流概述)
|
|
8
|
+
- [角色说明](#角色说明)
|
|
9
|
+
- [完整流程](#完整流程)
|
|
10
|
+
- [Pre-Execution Review](#pre-execution-review)
|
|
11
|
+
- [实施阶段](#实施阶段)
|
|
12
|
+
- [质量保障](#质量保障)
|
|
13
|
+
- [钉钉通知](#钉钉通知)
|
|
14
|
+
- [最佳实践](#最佳实践)
|
|
15
|
+
- [常见问题](#常见问题)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 工作流概述
|
|
20
|
+
|
|
21
|
+
SDD 工作流是一个规格书驱动的开发流程,通过多个专业角色协作完成软件开发全生命周期。
|
|
22
|
+
|
|
23
|
+
### 核心理念
|
|
24
|
+
|
|
25
|
+
1. **规格先行**: 先定义详细的技术规格,再开始编码
|
|
26
|
+
2. **角色分工**: 每个角色专注于特定领域的工作
|
|
27
|
+
3. **质量内建**: 在开发过程中持续验证质量
|
|
28
|
+
4. **反馈及时**: 失败时立即通知,快速修复
|
|
29
|
+
|
|
30
|
+
### 工作流阶段
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
用户需求
|
|
34
|
+
↓
|
|
35
|
+
Pre-Execution Review (多角色讨论)
|
|
36
|
+
↓
|
|
37
|
+
SAE (需求分析 + 架构设计)
|
|
38
|
+
↓
|
|
39
|
+
Backend/Frontend Engineer (OpenSpec + 代码实现 + 验证)
|
|
40
|
+
↓
|
|
41
|
+
Tester (测试验证)
|
|
42
|
+
↓
|
|
43
|
+
Code Reviewer (代码审查)
|
|
44
|
+
↓
|
|
45
|
+
Git Engineer (预检测 + 提交 + MR)
|
|
46
|
+
↓
|
|
47
|
+
完成 (等待 MR 批准)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 角色说明
|
|
53
|
+
|
|
54
|
+
### 1. SAE (Software Architecture Engineer)
|
|
55
|
+
|
|
56
|
+
**职责**: 需求分析、架构设计、技术方案
|
|
57
|
+
|
|
58
|
+
**输出**:
|
|
59
|
+
- 需求规格文档 (`specs/requirements/[feature-name].md`)
|
|
60
|
+
- 技术方案设计
|
|
61
|
+
- 前后端接口契约
|
|
62
|
+
- 验收标准
|
|
63
|
+
|
|
64
|
+
**关键能力**:
|
|
65
|
+
- 5W1H 需求分析
|
|
66
|
+
- 系统架构设计
|
|
67
|
+
- 技术选型评估
|
|
68
|
+
- 风险识别
|
|
69
|
+
|
|
70
|
+
### 2. Backend Engineer
|
|
71
|
+
|
|
72
|
+
**职责**: 后端 API 设计与实现 (Golang)
|
|
73
|
+
|
|
74
|
+
**输出**:
|
|
75
|
+
- 后端 OpenSpec
|
|
76
|
+
- API 接口实现
|
|
77
|
+
- 数据库设计
|
|
78
|
+
- 单元测试 (覆盖率 >= 90%)
|
|
79
|
+
|
|
80
|
+
**技术栈**:
|
|
81
|
+
- Go 1.21+, Gin 框架
|
|
82
|
+
- PostgreSQL/MySQL, Redis
|
|
83
|
+
- GORM, testify
|
|
84
|
+
|
|
85
|
+
### 3. Frontend Engineer
|
|
86
|
+
|
|
87
|
+
**职责**: 前端组件与交互实现 (Vue)
|
|
88
|
+
|
|
89
|
+
**输出**:
|
|
90
|
+
- 前端 OpenSpec
|
|
91
|
+
- 页面和组件实现
|
|
92
|
+
- 状态管理 (Pinia)
|
|
93
|
+
- 单元测试 (覆盖率 >= 70%)
|
|
94
|
+
|
|
95
|
+
**技术栈**:
|
|
96
|
+
- Vue 3, Composition API
|
|
97
|
+
- Pinia, Vue Router
|
|
98
|
+
- Vite, Vitest, Playwright
|
|
99
|
+
|
|
100
|
+
### 4. Tester
|
|
101
|
+
|
|
102
|
+
**职责**: 测试验证和质量保障
|
|
103
|
+
|
|
104
|
+
**输出**:
|
|
105
|
+
- 测试报告
|
|
106
|
+
- 覆盖率报告
|
|
107
|
+
- E2E 测试结果
|
|
108
|
+
- 验收标准检查
|
|
109
|
+
|
|
110
|
+
**验证内容**:
|
|
111
|
+
- 后端单元测试 + 覆盖率
|
|
112
|
+
- 前端单元测试 + 覆盖率
|
|
113
|
+
- E2E 测试
|
|
114
|
+
- 性能测试 (可选)
|
|
115
|
+
|
|
116
|
+
### 5. Code Reviewer
|
|
117
|
+
|
|
118
|
+
**职责**: 代码质量、安全审查
|
|
119
|
+
|
|
120
|
+
**输出**:
|
|
121
|
+
- 代码审查报告
|
|
122
|
+
- 问题清单 (严重/中等/轻微)
|
|
123
|
+
- 修复建议
|
|
124
|
+
|
|
125
|
+
**审查内容**:
|
|
126
|
+
- 代码质量 (规范、可维护性)
|
|
127
|
+
- 安全性 (SQL 注入、XSS、认证授权)
|
|
128
|
+
- 性能 (N+1 查询、缓存策略)
|
|
129
|
+
- 最佳实践
|
|
130
|
+
|
|
131
|
+
### 6. Git Engineer
|
|
132
|
+
|
|
133
|
+
**职责**: 代码提交、版本管理、MR 创建
|
|
134
|
+
|
|
135
|
+
**输出**:
|
|
136
|
+
- 规范化的 Git 提交
|
|
137
|
+
- GitLab Merge Request
|
|
138
|
+
- CI/CD 流水线验证
|
|
139
|
+
|
|
140
|
+
**工作内容**:
|
|
141
|
+
- 预检测 (lint, build, test)
|
|
142
|
+
- Conventional Commits 提交规范
|
|
143
|
+
- MR 创建和审查人指定
|
|
144
|
+
|
|
145
|
+
### 7. Notifier
|
|
146
|
+
|
|
147
|
+
**职责**: 钉钉通知发送
|
|
148
|
+
|
|
149
|
+
**输出**:
|
|
150
|
+
- 失败告警通知
|
|
151
|
+
- 成功事件通知 (可选)
|
|
152
|
+
|
|
153
|
+
**触发场景**:
|
|
154
|
+
- 测试失败
|
|
155
|
+
- 代码审查不通过
|
|
156
|
+
- 预检测失败
|
|
157
|
+
- MR 创建成功
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 完整流程
|
|
162
|
+
|
|
163
|
+
### 阶段 0: Pre-Execution Review
|
|
164
|
+
|
|
165
|
+
**目的**: 在开始实施前,多角色讨论需求的可行性、复杂度和风险。
|
|
166
|
+
|
|
167
|
+
**参与角色**: 所有角色
|
|
168
|
+
|
|
169
|
+
**讨论内容**:
|
|
170
|
+
- SAE: 需求清晰度、架构复杂度
|
|
171
|
+
- Backend Engineer: 技术可行性、性能评估
|
|
172
|
+
- Frontend Engineer: UI/UX 复杂度、组件设计
|
|
173
|
+
- Tester: 测试策略、环境需求
|
|
174
|
+
- Code Reviewer: 潜在风险、安全关注
|
|
175
|
+
- Git Engineer: CI/CD 兼容性
|
|
176
|
+
|
|
177
|
+
**输出**: 汇总反馈 + 用户决策
|
|
178
|
+
|
|
179
|
+
**示例**:
|
|
180
|
+
```
|
|
181
|
+
🗣️ SAE 角度:
|
|
182
|
+
- 需求清晰度:⭐⭐⭐⭐ (需澄清:第三方登录)
|
|
183
|
+
- 架构复杂度:中等
|
|
184
|
+
|
|
185
|
+
🗣️ Backend Engineer 角度:
|
|
186
|
+
- 技术可行性:高
|
|
187
|
+
- 性能评估:响应时间 < 100ms
|
|
188
|
+
- 依赖风险:需要 Redis
|
|
189
|
+
|
|
190
|
+
🗣️ Frontend Engineer 角度:
|
|
191
|
+
- UI/UX 复杂度:中等
|
|
192
|
+
- 组件设计:可复用登录表单
|
|
193
|
+
|
|
194
|
+
...
|
|
195
|
+
|
|
196
|
+
📋 汇总反馈:整体可行,需澄清 3 个问题...
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### 阶段 1: 需求分析 (SAE)
|
|
200
|
+
|
|
201
|
+
**输入**: 用户原始需求
|
|
202
|
+
|
|
203
|
+
**工作流程**:
|
|
204
|
+
1. 读取用户需求
|
|
205
|
+
2. 使用 5W1H 分析需求
|
|
206
|
+
3. 使用 AskUserQuestion 澄清模糊点
|
|
207
|
+
4. 探索现有代码库 (Grep/Glob)
|
|
208
|
+
5. 编写需求规格文档
|
|
209
|
+
|
|
210
|
+
**输出**: `specs/requirements/[feature-name].md`
|
|
211
|
+
|
|
212
|
+
**关键内容**:
|
|
213
|
+
- 需求概述
|
|
214
|
+
- 功能需求
|
|
215
|
+
- 技术方案
|
|
216
|
+
- 接口设计 (前后端契约)
|
|
217
|
+
- 数据模型
|
|
218
|
+
- 验收标准
|
|
219
|
+
|
|
220
|
+
### 阶段 2: 后端实现 (Backend Engineer)
|
|
221
|
+
|
|
222
|
+
**输入**: 需求规格文档
|
|
223
|
+
|
|
224
|
+
**工作流程**:
|
|
225
|
+
1. 读取需求规格
|
|
226
|
+
2. 调用 `/openspec:proposal` 生成后端 OpenSpec
|
|
227
|
+
3. 等待用户批准 OpenSpec
|
|
228
|
+
4. 调用 `/openspec:apply` 实现代码
|
|
229
|
+
5. **验证检查** (必须通过):
|
|
230
|
+
- 语法检查 (`go vet`)
|
|
231
|
+
- 编译检查 (`go build`)
|
|
232
|
+
- Lint 检查 (`golangci-lint`)
|
|
233
|
+
- 单元测试 (`go test`)
|
|
234
|
+
- 覆盖率 >= 90%
|
|
235
|
+
6. 提交代码到特性分支
|
|
236
|
+
|
|
237
|
+
**输出**:
|
|
238
|
+
- 后端 OpenSpec
|
|
239
|
+
- API 接口代码
|
|
240
|
+
- 单元测试
|
|
241
|
+
- 数据库迁移 (如需要)
|
|
242
|
+
|
|
243
|
+
### 阶段 3: 前端实现 (Frontend Engineer)
|
|
244
|
+
|
|
245
|
+
**输入**: 需求规格文档
|
|
246
|
+
|
|
247
|
+
**工作流程**:
|
|
248
|
+
1. 读取需求规格
|
|
249
|
+
2. 调用 `/openspec:proposal` 生成前端 OpenSpec
|
|
250
|
+
3. 等待用户批准 OpenSpec
|
|
251
|
+
4. 调用 `/openspec:apply` 实现代码
|
|
252
|
+
5. **验证检查** (必须通过):
|
|
253
|
+
- 类型检查 (`npm run type-check`)
|
|
254
|
+
- 编译检查 (`npm run build`)
|
|
255
|
+
- Lint 检查 (`npm run lint`)
|
|
256
|
+
- 单元测试 (`npm run test:unit`)
|
|
257
|
+
- 覆盖率 >= 70%
|
|
258
|
+
6. 提交代码到特性分支
|
|
259
|
+
|
|
260
|
+
**输出**:
|
|
261
|
+
- 前端 OpenSpec
|
|
262
|
+
- 页面和组件代码
|
|
263
|
+
- Pinia stores
|
|
264
|
+
- 单元测试
|
|
265
|
+
|
|
266
|
+
### 阶段 4: 测试验证 (Tester)
|
|
267
|
+
|
|
268
|
+
**输入**: 后端和前端代码实现
|
|
269
|
+
|
|
270
|
+
**工作流程**:
|
|
271
|
+
1. 读取需求规格和 OpenSpec
|
|
272
|
+
2. 执行后端测试:
|
|
273
|
+
- 单元测试
|
|
274
|
+
- 集成测试
|
|
275
|
+
- 覆盖率检查 (>= 90%)
|
|
276
|
+
3. 执行前端测试:
|
|
277
|
+
- 单元测试
|
|
278
|
+
- E2E 测试 (Playwright)
|
|
279
|
+
- 覆盖率检查 (>= 70%)
|
|
280
|
+
4. 验收标准检查
|
|
281
|
+
5. 生成测试报告
|
|
282
|
+
|
|
283
|
+
**成功**: 交给 Code Reviewer
|
|
284
|
+
**失败**: 返回对应 Engineer + 发送钉钉通知
|
|
285
|
+
|
|
286
|
+
**输出**:
|
|
287
|
+
- 测试报告
|
|
288
|
+
- 覆盖率报告
|
|
289
|
+
|
|
290
|
+
### 阶段 5: 代码审查 (Code Reviewer)
|
|
291
|
+
|
|
292
|
+
**输入**: 通过测试的代码
|
|
293
|
+
|
|
294
|
+
**工作流程**:
|
|
295
|
+
1. 读取需求规格和 OpenSpec
|
|
296
|
+
2. 获取变更文件列表 (`git diff`)
|
|
297
|
+
3. 执行自动化检查:
|
|
298
|
+
- 后端: `golangci-lint`, `gosec`
|
|
299
|
+
- 前端: `npm run lint`, `npm audit`
|
|
300
|
+
4. 人工审查:
|
|
301
|
+
- 代码质量
|
|
302
|
+
- 安全性 (OWASP Top 10)
|
|
303
|
+
- 性能
|
|
304
|
+
- 可维护性
|
|
305
|
+
5. 生成审查报告
|
|
306
|
+
|
|
307
|
+
**成功**: 交给 Git Engineer
|
|
308
|
+
**失败**: 返回对应 Engineer + 发送钉钉通知
|
|
309
|
+
|
|
310
|
+
**输出**:
|
|
311
|
+
- 代码审查报告
|
|
312
|
+
- 问题清单 (如有)
|
|
313
|
+
|
|
314
|
+
### 阶段 6: 提交和 MR (Git Engineer)
|
|
315
|
+
|
|
316
|
+
**输入**: 通过审查的代码
|
|
317
|
+
|
|
318
|
+
**工作流程**:
|
|
319
|
+
1. 执行预检测:
|
|
320
|
+
- 后端: lint, build, test, coverage
|
|
321
|
+
- 前端: lint, build, test, coverage
|
|
322
|
+
2. 提交代码 (Conventional Commits 规范)
|
|
323
|
+
3. 推送到远程分支
|
|
324
|
+
4. 创建 GitLab Merge Request (使用 `glab`)
|
|
325
|
+
5. 指定审查人和标签
|
|
326
|
+
|
|
327
|
+
**成功**: 工作流完成 + 发送钉钉通知 (可选)
|
|
328
|
+
**失败**: 返回对应 Engineer + 发送钉钉通知
|
|
329
|
+
|
|
330
|
+
**输出**:
|
|
331
|
+
- Git 提交
|
|
332
|
+
- GitLab MR
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## Pre-Execution Review
|
|
337
|
+
|
|
338
|
+
### 为什么需要 Pre-Execution Review?
|
|
339
|
+
|
|
340
|
+
1. **早期发现问题**: 在编码前识别技术风险
|
|
341
|
+
2. **多角度评估**: 不同角色提供专业视角
|
|
342
|
+
3. **降低返工**: 减少后期修改成本
|
|
343
|
+
4. **统一理解**: 确保所有角色对需求理解一致
|
|
344
|
+
|
|
345
|
+
### Review 流程
|
|
346
|
+
|
|
347
|
+
1. **SAE 首先发言**:
|
|
348
|
+
- 评估需求清晰度
|
|
349
|
+
- 识别需要澄清的问题
|
|
350
|
+
- 评估架构复杂度
|
|
351
|
+
|
|
352
|
+
2. **Backend Engineer**:
|
|
353
|
+
- 技术可行性
|
|
354
|
+
- 性能预估
|
|
355
|
+
- 依赖风险
|
|
356
|
+
|
|
357
|
+
3. **Frontend Engineer**:
|
|
358
|
+
- UI/UX 复杂度
|
|
359
|
+
- 组件可复用性
|
|
360
|
+
- 状态管理策略
|
|
361
|
+
|
|
362
|
+
4. **Tester**:
|
|
363
|
+
- 测试策略
|
|
364
|
+
- 是否需要特殊测试环境
|
|
365
|
+
- E2E 测试场景完整性
|
|
366
|
+
|
|
367
|
+
5. **Code Reviewer**:
|
|
368
|
+
- 潜在安全风险
|
|
369
|
+
- 性能瓶颈预判
|
|
370
|
+
- 可维护性挑战
|
|
371
|
+
|
|
372
|
+
6. **Git Engineer**:
|
|
373
|
+
- CI/CD 兼容性
|
|
374
|
+
- 分支策略
|
|
375
|
+
- MR 审查流程
|
|
376
|
+
|
|
377
|
+
7. **汇总反馈**:
|
|
378
|
+
- 整合所有角色的反馈
|
|
379
|
+
- 提出澄清问题
|
|
380
|
+
- 给出整体可行性评估
|
|
381
|
+
|
|
382
|
+
8. **用户决策**:
|
|
383
|
+
- 回答澄清问题
|
|
384
|
+
- 决定是否继续
|
|
385
|
+
|
|
386
|
+
### Review 模板
|
|
387
|
+
|
|
388
|
+
```markdown
|
|
389
|
+
📍 Pre-Execution Review
|
|
390
|
+
|
|
391
|
+
## 需求概述
|
|
392
|
+
[简要描述需求]
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
🗣️ SAE 角度:
|
|
397
|
+
- 需求清晰度:⭐⭐⭐⭐ (1-5星)
|
|
398
|
+
- 需要澄清:[问题列表]
|
|
399
|
+
- 架构复杂度:[低/中/高]
|
|
400
|
+
|
|
401
|
+
🗣️ Backend Engineer 角度:
|
|
402
|
+
- 技术可行性:[高/中/低]
|
|
403
|
+
- 性能评估:[预估指标]
|
|
404
|
+
- 依赖风险:[新依赖?版本兼容?]
|
|
405
|
+
|
|
406
|
+
🗣️ Frontend Engineer 角度:
|
|
407
|
+
- UI/UX 复杂度:[低/中/高]
|
|
408
|
+
- 组件设计:[可复用性评估]
|
|
409
|
+
- 状态管理:[策略建议]
|
|
410
|
+
|
|
411
|
+
🗣️ Tester 角度:
|
|
412
|
+
- 测试复杂度:[低/中/高]
|
|
413
|
+
- 环境需求:[特殊环境?]
|
|
414
|
+
- E2E 场景:[场景完整性]
|
|
415
|
+
|
|
416
|
+
🗣️ Code Reviewer 角度:
|
|
417
|
+
- 潜在风险:[安全、性能等]
|
|
418
|
+
- 技术债务:[可能引入的债务]
|
|
419
|
+
|
|
420
|
+
🗣️ Git Engineer 角度:
|
|
421
|
+
- CI/CD 兼容性:[是否需要调整?]
|
|
422
|
+
- 分支策略:[建议]
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
📋 汇总反馈:
|
|
427
|
+
- 整体可行性:[高/中/低]
|
|
428
|
+
- 需澄清问题:[列表]
|
|
429
|
+
- 主要风险:[列表]
|
|
430
|
+
- 建议操作:[继续/暂缓/调整方案]
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## 实施阶段
|
|
436
|
+
|
|
437
|
+
### OpenSpec 工作流
|
|
438
|
+
|
|
439
|
+
每个 Engineer 角色都使用 OpenSpec 来管理设计和实现:
|
|
440
|
+
|
|
441
|
+
1. **Proposal (规划)**:
|
|
442
|
+
```bash
|
|
443
|
+
/openspec:proposal
|
|
444
|
+
```
|
|
445
|
+
- 生成详细的实现规格
|
|
446
|
+
- 包含接口定义、数据模型、测试用例
|
|
447
|
+
- 等待用户批准
|
|
448
|
+
|
|
449
|
+
2. **Apply (实施)**:
|
|
450
|
+
```bash
|
|
451
|
+
/openspec:apply
|
|
452
|
+
```
|
|
453
|
+
- 基于批准的 OpenSpec 实现代码
|
|
454
|
+
- 确保实现符合规格
|
|
455
|
+
- 包含测试代码
|
|
456
|
+
|
|
457
|
+
3. **Archive (归档)**:
|
|
458
|
+
```bash
|
|
459
|
+
/openspec:archive
|
|
460
|
+
```
|
|
461
|
+
- 功能上线后归档 OpenSpec
|
|
462
|
+
- 更新项目文档
|
|
463
|
+
|
|
464
|
+
### 验证检查清单
|
|
465
|
+
|
|
466
|
+
#### Backend Engineer
|
|
467
|
+
```bash
|
|
468
|
+
cd backend
|
|
469
|
+
|
|
470
|
+
# 1. 语法检查
|
|
471
|
+
go vet ./...
|
|
472
|
+
|
|
473
|
+
# 2. 编译检查
|
|
474
|
+
go build ./...
|
|
475
|
+
|
|
476
|
+
# 3. Lint 检查
|
|
477
|
+
golangci-lint run
|
|
478
|
+
|
|
479
|
+
# 4. 单元测试
|
|
480
|
+
go test ./... -v
|
|
481
|
+
|
|
482
|
+
# 5. 覆盖率 (>= 90%)
|
|
483
|
+
go test ./... -coverprofile=coverage.out
|
|
484
|
+
go tool cover -func=coverage.out | grep total
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
#### Frontend Engineer
|
|
488
|
+
```bash
|
|
489
|
+
cd frontend
|
|
490
|
+
|
|
491
|
+
# 1. 类型检查
|
|
492
|
+
npm run type-check
|
|
493
|
+
|
|
494
|
+
# 2. 编译检查
|
|
495
|
+
npm run build
|
|
496
|
+
|
|
497
|
+
# 3. Lint 检查
|
|
498
|
+
npm run lint
|
|
499
|
+
|
|
500
|
+
# 4. 单元测试
|
|
501
|
+
npm run test:unit
|
|
502
|
+
|
|
503
|
+
# 5. 覆盖率 (>= 70%)
|
|
504
|
+
npm run test:coverage
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
## 质量保障
|
|
510
|
+
|
|
511
|
+
### 测试策略
|
|
512
|
+
|
|
513
|
+
#### 1. 单元测试
|
|
514
|
+
|
|
515
|
+
**后端** (Go):
|
|
516
|
+
```go
|
|
517
|
+
func TestUserService_CreateUser(t *testing.T) {
|
|
518
|
+
tests := []struct {
|
|
519
|
+
name string
|
|
520
|
+
input CreateUserRequest
|
|
521
|
+
wantErr bool
|
|
522
|
+
}{
|
|
523
|
+
{"valid user", CreateUserRequest{Email: "test@example.com"}, false},
|
|
524
|
+
{"invalid email", CreateUserRequest{Email: "invalid"}, true},
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
for _, tt := range tests {
|
|
528
|
+
t.Run(tt.name, func(t *testing.T) {
|
|
529
|
+
err := service.CreateUser(tt.input)
|
|
530
|
+
if (err != nil) != tt.wantErr {
|
|
531
|
+
t.Errorf("error = %v, wantErr %v", err, tt.wantErr)
|
|
532
|
+
}
|
|
533
|
+
})
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
**前端** (Vue + Vitest):
|
|
539
|
+
```typescript
|
|
540
|
+
import { describe, it, expect } from 'vitest'
|
|
541
|
+
import { render, screen } from '@testing-library/vue'
|
|
542
|
+
import LoginForm from '@/components/LoginForm.vue'
|
|
543
|
+
|
|
544
|
+
describe('LoginForm', () => {
|
|
545
|
+
it('renders login form', () => {
|
|
546
|
+
render(LoginForm)
|
|
547
|
+
expect(screen.getByLabelText('Email')).toBeInTheDocument()
|
|
548
|
+
})
|
|
549
|
+
})
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
#### 2. 集成测试
|
|
553
|
+
|
|
554
|
+
**后端 API 测试**:
|
|
555
|
+
```go
|
|
556
|
+
func TestAuthAPI_Login(t *testing.T) {
|
|
557
|
+
router := setupRouter()
|
|
558
|
+
w := httptest.NewRecorder()
|
|
559
|
+
|
|
560
|
+
body := `{"email":"test@example.com","password":"password123"}`
|
|
561
|
+
req, _ := http.NewRequest("POST", "/api/v1/auth/login", strings.NewReader(body))
|
|
562
|
+
req.Header.Set("Content-Type", "application/json")
|
|
563
|
+
|
|
564
|
+
router.ServeHTTP(w, req)
|
|
565
|
+
|
|
566
|
+
assert.Equal(t, 200, w.Code)
|
|
567
|
+
}
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
#### 3. E2E 测试
|
|
571
|
+
|
|
572
|
+
**前端 E2E (Playwright)**:
|
|
573
|
+
```typescript
|
|
574
|
+
import { test, expect } from '@playwright/test'
|
|
575
|
+
|
|
576
|
+
test('user login flow', async ({ page }) => {
|
|
577
|
+
await page.goto('/login')
|
|
578
|
+
await page.fill('input[name="email"]', 'test@example.com')
|
|
579
|
+
await page.fill('input[name="password"]', 'password123')
|
|
580
|
+
await page.click('button[type="submit"]')
|
|
581
|
+
|
|
582
|
+
await expect(page).toHaveURL('/dashboard')
|
|
583
|
+
})
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
### 代码审查清单
|
|
587
|
+
|
|
588
|
+
#### 安全检查 (OWASP Top 10)
|
|
589
|
+
- [ ] SQL 注入防护 (参数化查询)
|
|
590
|
+
- [ ] XSS 防护 (输出转义)
|
|
591
|
+
- [ ] 密码加密存储 (bcrypt)
|
|
592
|
+
- [ ] 认证授权机制
|
|
593
|
+
- [ ] CORS 配置正确
|
|
594
|
+
- [ ] 敏感信息不泄露
|
|
595
|
+
|
|
596
|
+
#### 性能检查
|
|
597
|
+
- [ ] 无 N+1 查询
|
|
598
|
+
- [ ] 数据库索引合理
|
|
599
|
+
- [ ] 大数据量分页
|
|
600
|
+
- [ ] 热点数据缓存
|
|
601
|
+
- [ ] 前端组件懒加载
|
|
602
|
+
|
|
603
|
+
#### 可维护性检查
|
|
604
|
+
- [ ] 代码结构清晰
|
|
605
|
+
- [ ] 函数职责单一
|
|
606
|
+
- [ ] 无魔法数字
|
|
607
|
+
- [ ] 无重复代码
|
|
608
|
+
- [ ] 测试覆盖率达标
|
|
609
|
+
|
|
610
|
+
---
|
|
611
|
+
|
|
612
|
+
## 钉钉通知
|
|
613
|
+
|
|
614
|
+
### 配置钉钉 Webhook
|
|
615
|
+
|
|
616
|
+
1. **创建钉钉机器人**:
|
|
617
|
+
- 在钉钉群中添加"自定义机器人"
|
|
618
|
+
- 安全设置选择"自定义关键词"
|
|
619
|
+
- 添加关键词:**SDD**
|
|
620
|
+
- 复制 Webhook URL
|
|
621
|
+
|
|
622
|
+
2. **配置文件**:
|
|
623
|
+
- 全局: `~/.claude/dingtalk-config.json`
|
|
624
|
+
- 项目: `<project>/.claude/dingtalk-config.json`
|
|
625
|
+
|
|
626
|
+
3. **配置内容**:
|
|
627
|
+
```json
|
|
628
|
+
{
|
|
629
|
+
"webhook_url": "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN",
|
|
630
|
+
"notify_on": ["failure", "success"],
|
|
631
|
+
"enabled": true
|
|
632
|
+
}
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
### 通知场景
|
|
636
|
+
|
|
637
|
+
#### 失败通知 (自动发送)
|
|
638
|
+
- Tester 测试失败
|
|
639
|
+
- Code Reviewer 审查不通过
|
|
640
|
+
- Git Engineer 预检测失败
|
|
641
|
+
- Backend/Frontend Engineer 验证失败
|
|
642
|
+
|
|
643
|
+
#### 成功通知 (可选)
|
|
644
|
+
- Git Engineer MR 创建成功
|
|
645
|
+
- 整个工作流完成
|
|
646
|
+
|
|
647
|
+
### 通知示例
|
|
648
|
+
|
|
649
|
+
**测试失败**:
|
|
650
|
+
```
|
|
651
|
+
❌ SDD 工作流失败
|
|
652
|
+
|
|
653
|
+
- 工作流: user-login
|
|
654
|
+
- 失败阶段: Tester
|
|
655
|
+
- 失败详情:
|
|
656
|
+
- 后端测试失败:2/12
|
|
657
|
+
- 覆盖率不达标:85% (要求 >= 90%)
|
|
658
|
+
- 建议操作: 返回 Backend Engineer 修复
|
|
659
|
+
|
|
660
|
+
🕐 时间: 2026-01-06 14:30:00
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
**代码审查不通过**:
|
|
664
|
+
```
|
|
665
|
+
❌ SDD 代码审查不通过
|
|
666
|
+
|
|
667
|
+
- 工作流: user-login
|
|
668
|
+
- 失败阶段: Code Reviewer
|
|
669
|
+
- 问题统计:
|
|
670
|
+
- 严重问题:2 个
|
|
671
|
+
- 中等问题:1 个
|
|
672
|
+
- 主要问题:
|
|
673
|
+
- 密码明文存储(严重)
|
|
674
|
+
- N+1 查询问题(严重)
|
|
675
|
+
- 建议操作: 返回 Backend Engineer 修复
|
|
676
|
+
|
|
677
|
+
🕐 时间: 2026-01-06 15:00:00
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
**MR 创建成功**:
|
|
681
|
+
```
|
|
682
|
+
✅ SDD MR 已创建
|
|
683
|
+
|
|
684
|
+
- 工作流: user-login
|
|
685
|
+
- MR 标题: feat(auth): Add user login functionality
|
|
686
|
+
- MR 链接: https://git.in.chaitin.net/project/-/merge_requests/1
|
|
687
|
+
- 审查人: @reviewer1
|
|
688
|
+
|
|
689
|
+
🕐 时间: 2026-01-06 16:30:00
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
---
|
|
693
|
+
|
|
694
|
+
## 最佳实践
|
|
695
|
+
|
|
696
|
+
### 1. 需求分析
|
|
697
|
+
|
|
698
|
+
- ✅ 使用 5W1H 方法全面分析需求
|
|
699
|
+
- ✅ 主动澄清模糊点,不要猜测
|
|
700
|
+
- ✅ 明确前后端职责边界
|
|
701
|
+
- ✅ 定义清晰的验收标准
|
|
702
|
+
|
|
703
|
+
### 2. 代码实现
|
|
704
|
+
|
|
705
|
+
- ✅ 先通过验证检查再流转下一阶段
|
|
706
|
+
- ✅ 遵循语言和框架的最佳实践
|
|
707
|
+
- ✅ 编写有意义的测试用例
|
|
708
|
+
- ✅ 达到覆盖率要求 (后端 90%, 前端 70%)
|
|
709
|
+
|
|
710
|
+
### 3. 测试验证
|
|
711
|
+
|
|
712
|
+
- ✅ 对照验收标准逐项检查
|
|
713
|
+
- ✅ 运行所有自动化测试
|
|
714
|
+
- ✅ 验证性能指标 (响应时间 < 200ms)
|
|
715
|
+
- ✅ 检查安全性 (SQL 注入、XSS 等)
|
|
716
|
+
|
|
717
|
+
### 4. 代码审查
|
|
718
|
+
|
|
719
|
+
- ✅ 使用自动化工具辅助审查
|
|
720
|
+
- ✅ 重点关注安全和性能问题
|
|
721
|
+
- ✅ 提供具体的修复建议
|
|
722
|
+
- ✅ 严重问题必须修复后才能通过
|
|
723
|
+
|
|
724
|
+
### 5. 提交规范
|
|
725
|
+
|
|
726
|
+
- ✅ 遵循 Conventional Commits 规范
|
|
727
|
+
- ✅ 提交消息清晰描述变更内容
|
|
728
|
+
- ✅ MR 描述包含功能概述、测试结果、验收标准
|
|
729
|
+
- ✅ 指定合适的审查人
|
|
730
|
+
|
|
731
|
+
---
|
|
732
|
+
|
|
733
|
+
## 常见问题
|
|
734
|
+
|
|
735
|
+
### Q1: 如果验证检查失败怎么办?
|
|
736
|
+
|
|
737
|
+
**答**:
|
|
738
|
+
1. 查看失败详情 (语法错误、测试失败、覆盖率不达标等)
|
|
739
|
+
2. 修复所有问题
|
|
740
|
+
3. 重新运行验证检查
|
|
741
|
+
4. 通过后才能进入下一阶段
|
|
742
|
+
|
|
743
|
+
### Q2: 测试覆盖率不达标怎么办?
|
|
744
|
+
|
|
745
|
+
**答**:
|
|
746
|
+
1. 使用覆盖率报告查看未覆盖的代码
|
|
747
|
+
2. 补充测试用例覆盖未测试的分支
|
|
748
|
+
3. 重新运行测试并检查覆盖率
|
|
749
|
+
4. 后端要求 >= 90%, 前端要求 >= 70%
|
|
750
|
+
|
|
751
|
+
### Q3: 代码审查不通过怎么办?
|
|
752
|
+
|
|
753
|
+
**答**:
|
|
754
|
+
1. 仔细阅读审查报告中的问题清单
|
|
755
|
+
2. 根据修复建议修改代码
|
|
756
|
+
3. 严重问题必须修复,中等问题建议修复
|
|
757
|
+
4. 修复后重新提交给 Code Reviewer
|
|
758
|
+
|
|
759
|
+
### Q4: 如何处理 N+1 查询问题?
|
|
760
|
+
|
|
761
|
+
**答** (后端 Go + GORM):
|
|
762
|
+
```go
|
|
763
|
+
// ❌ N+1 查询
|
|
764
|
+
for _, user := range users {
|
|
765
|
+
db.Model(&user).Association("Orders").Find(&user.Orders)
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// ✅ 使用 Preload
|
|
769
|
+
db.Preload("Orders").Find(&users)
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
### Q5: 如何避免 SQL 注入?
|
|
773
|
+
|
|
774
|
+
**答**:
|
|
775
|
+
```go
|
|
776
|
+
// ❌ 危险:SQL 拼接
|
|
777
|
+
query := "SELECT * FROM users WHERE email = '" + email + "'"
|
|
778
|
+
|
|
779
|
+
// ✅ 安全:参数化查询
|
|
780
|
+
db.Where("email = ?", email).First(&user)
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
### Q6: 如何避免 XSS 攻击?
|
|
784
|
+
|
|
785
|
+
**答** (前端 Vue):
|
|
786
|
+
```vue
|
|
787
|
+
<!-- ❌ 危险:v-html -->
|
|
788
|
+
<div v-html="userInput"></div>
|
|
789
|
+
|
|
790
|
+
<!-- ✅ 安全:自动转义 -->
|
|
791
|
+
<div>{{ userInput }}</div>
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
### Q7: 钉钉通知发送失败怎么办?
|
|
795
|
+
|
|
796
|
+
**答**:
|
|
797
|
+
1. 检查 Webhook URL 是否正确
|
|
798
|
+
2. 确认消息包含 "SDD" 关键字
|
|
799
|
+
3. 检查发送频率 (避免过于频繁)
|
|
800
|
+
4. 运行测试脚本验证配置
|
|
801
|
+
|
|
802
|
+
### Q8: 如何跳过某个阶段?
|
|
803
|
+
|
|
804
|
+
**答**: 不建议跳过阶段。每个阶段都有其重要的质量保障作用。如果确实需要调整流程,建议与团队讨论后修改工作流定义。
|
|
805
|
+
|
|
806
|
+
### Q9: 多个功能并行开发怎么办?
|
|
807
|
+
|
|
808
|
+
**答**:
|
|
809
|
+
1. 为每个功能创建独立的特性分支
|
|
810
|
+
2. 每个功能独立走完整的 SDD 流程
|
|
811
|
+
3. 避免分支间的代码冲突
|
|
812
|
+
4. 合并时按优先级顺序进行
|
|
813
|
+
|
|
814
|
+
### Q10: 如何查看工作流状态?
|
|
815
|
+
|
|
816
|
+
**答**:
|
|
817
|
+
1. 查看钉钉通知了解失败阶段
|
|
818
|
+
2. 查看 Git 分支了解代码提交状态
|
|
819
|
+
3. 查看 GitLab MR 了解审查进度
|
|
820
|
+
4. 查看 OpenSpec 变更了解实施计划
|
|
821
|
+
|
|
822
|
+
---
|
|
823
|
+
|
|
824
|
+
## 总结
|
|
825
|
+
|
|
826
|
+
SDD 工作流通过多角色协作、质量内建和及时反馈,确保软件开发的高质量和高效率。
|
|
827
|
+
|
|
828
|
+
关键要素:
|
|
829
|
+
- ✅ Pre-Execution Review 提前识别风险
|
|
830
|
+
- ✅ OpenSpec 驱动实施
|
|
831
|
+
- ✅ 验证检查确保质量
|
|
832
|
+
- ✅ 自动化测试保障功能
|
|
833
|
+
- ✅ 代码审查提升质量
|
|
834
|
+
- ✅ 钉钉通知及时反馈
|
|
835
|
+
|
|
836
|
+
遵循 SDD 工作流,享受高效、高质量的开发体验!
|