sdd-full 4.2.0 → 4.3.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/bin.js +31 -63
- package/package.json +1 -1
- package/skills/README.md +97 -0
- package/skills/call-adaptation/SKILL.md +23 -0
- package/skills/call-adaptation/call-adaptation-guide.md +136 -0
- package/skills/call-adaptation/claude-code-call-spec.md +50 -0
- package/skills/call-adaptation/trae-call-spec.md +56 -0
- package/skills/checklist.md +154 -0
- package/skills/design-planning/ai-coding-rules/SKILL.md +52 -0
- package/skills/design-planning/design-to-code/SKILL.md +53 -0
- package/skills/design-planning/enterprise-spec/SKILL.md +52 -3
- package/skills/design-planning/flutter-av/SKILL.md +44 -34
- package/skills/design-planning/flutter-map/SKILL.md +41 -31
- package/skills/design-planning/function-sdd/SKILL.md +54 -0
- package/skills/design-planning/sdd-code/SKILL.md +347 -0
- package/skills/design-planning/sdd-deploy/SKILL.md +501 -0
- package/skills/design-planning/sdd-ops/SKILL.md +306 -0
- package/skills/design-planning/sdd-test/SKILL.md +383 -0
- package/skills/design-planning/ui-sdd/SKILL.md +291 -0
- package/skills/design-planning/ui-sdd-specialized/SKILL.md +46 -40
- package/skills/design-planning/writing-plans/SKILL.md +144 -0
- package/skills/development-execution/flutter-errors/SKILL.md +44 -34
- package/skills/development-execution/sdd-add/SKILL.md +540 -0
- package/skills/development-execution/systematic-debugging/SKILL.md +298 -0
- package/skills/development-execution/test-driven-development/SKILL.md +373 -0
- package/skills/development-execution/verification-before-completion/SKILL.md +141 -0
- package/skills/knowledge-precipitation/claudeception/SKILL.md +96 -0
- package/skills/knowledge-precipitation/mempalace-auto-saver/SKILL.md +302 -0
- package/skills/quality-assurance/bdd-acceptance/SKILL.md +44 -37
- package/skills/quality-assurance/flutter-test/SKILL.md +56 -0
- package/skills/quality-assurance/quality-gate/SKILL.md +350 -0
- package/skills/quality-assurance/security-audit/SKILL.md +386 -0
- package/skills/release-ops/finishing-a-development-branch/SKILL.md +202 -0
- package/skills/release-ops/release-flow/SKILL.md +404 -0
- package/skills/requirement-analysis/brainstorming/SKILL.md +166 -0
- package/skills/requirement-analysis/competitive-brief/SKILL.md +121 -0
- package/skills/requirement-analysis/market-research/SKILL.md +143 -0
- package/skills/requirement-analysis/prd-write/SKILL.md +111 -0
- package/skills/requirement-analysis/requirement-completion-officer/SKILL.md +124 -0
- package/skills/requirement-analysis/sdd/SKILL.md +1044 -0
- package/skills/requirement-analysis/sdd-full/SKILL.md +717 -36
- package/skills/requirement-analysis/unified-flow/SKILL.md +128 -26
- package/skills/rules/project_rules.md +167 -0
- package/skills/rules/user_rules.md +254 -69
- package/skills/special-tools/env-check/SKILL.md +40 -34
- package/skills/special-tools/receiving-code-review/SKILL.md +215 -0
- package/skills/special-tools/requesting-code-review/SKILL.md +107 -0
- package/skills/special-tools/using-superpowers/SKILL.md +117 -0
- package/skills/templates/API-SDD.md +31 -0
- package/skills/templates/Andrej Karpathy AI/347/274/226/347/240/201/350/247/204/345/210/231/350/220/275/345/234/260SDD.md" +117 -0
- package/skills/templates/BDD/351/243/216/346/240/274/351/252/214/346/224/266/346/240/207/345/207/206SDD.md +147 -0
- package/skills/templates/Base-SDD.md +38 -0
- package/skills/templates/Brain-SDD.md +36 -0
- package/skills/templates/Code-SDD.md +41 -0
- package/skills/templates/Competitor-SDD.md +34 -0
- package/skills/templates/Env-SDD.md +37 -0
- package/skills/templates/Flutter/345/205/250/347/261/273/345/236/213/346/265/213/350/257/225/347/255/226/347/225/245SDD.md +162 -0
- package/skills/templates/Flutter/345/234/260/345/233/276/345/257/274/350/210/252/344/270/232/345/212/241SDD.md +136 -0
- package/skills/templates/Flutter/345/270/270/350/247/201/345/274/202/345/270/270/344/270/223/351/241/271SDD.md +159 -0
- package/skills/templates/Flutter/351/237/263/350/247/206/351/242/221/345/205/250/346/240/210SDD.md +121 -0
- package/skills/templates/PRD-SDD.md +45 -0
- package/skills/templates/SKILL.md +91 -0
- package/skills/templates/Test-SDD.md +34 -0
- package/skills/templates/UI-SDD.md +38 -0
- package/skills/templates/UI-SDD/344/270/223/347/224/250/346/250/241/346/235/277.md +141 -0
- package/skills/templates/UI/350/265/204/346/272/220/346/217/220/347/244/272/350/257/215/347/224/237/346/210/220SDD.md +67 -0
- package/skills/templates//344/274/201/344/270/232/347/272/247/345/205/250/346/240/210/345/267/245/347/250/213/350/247/204/350/214/203SDD.md +152 -0
- package/skills/templates//345/205/250/346/265/201/347/250/213SDD/350/236/215/345/220/210/344/275/223/347/263/273.md +198 -0
- package/skills/templates//345/212/237/350/203/275SDD/344/270/223/347/224/250/346/250/241/346/235/277.md +132 -0
- package/skills/templates//347/216/257/345/242/203/351/242/204/346/243/200/346/240/207/345/207/206/345/214/226SDD.md +153 -0
- package/skills/templates//351/253/230/344/277/235/347/234/237/350/256/276/350/256/241/350/275/254/344/273/243/347/240/201SDD.md +119 -0
- package/skills//345/256/214/346/225/264/345/274/200/345/217/221/346/265/201/347/250/213/346/211/213/345/206/214.md +408 -0
- package/skills//346/212/200/350/203/275/344/275/223/347/263/273/345/256/214/345/226/204/345/273/272/350/256/256.md +305 -0
- package/skills//346/212/200/350/203/275/344/275/277/347/224/250/346/214/207/345/215/227.md +285 -0
- package/skills//346/212/200/350/203/275/345/206/263/347/255/226/346/240/221.md +320 -0
- package/skills/brainstorming/SKILL.md +0 -164
- package/skills/brainstorming/scripts/frame-template.html +0 -214
- package/skills/brainstorming/scripts/helper.js +0 -88
- package/skills/brainstorming/scripts/server.cjs +0 -338
- package/skills/brainstorming/scripts/start-server.sh +0 -153
- package/skills/brainstorming/scripts/stop-server.sh +0 -55
- package/skills/brainstorming/spec-document-reviewer-prompt.md +0 -48
- package/skills/brainstorming/visual-companion.md +0 -286
- package/skills/chinese-code-review/SKILL.md +0 -277
- package/skills/chinese-commit-conventions/SKILL.md +0 -364
- package/skills/chinese-documentation/SKILL.md +0 -448
- package/skills/chinese-git-workflow/SKILL.md +0 -510
- package/skills/dispatching-parallel-agents/SKILL.md +0 -182
- package/skills/executing-plans/SKILL.md +0 -175
- package/skills/finishing-a-development-branch/SKILL.md +0 -200
- package/skills/mcp-builder/SKILL.md +0 -255
- package/skills/receiving-code-review/SKILL.md +0 -213
- package/skills/requesting-code-review/SKILL.md +0 -105
- package/skills/requesting-code-review/code-reviewer.md +0 -146
- package/skills/rules/skill-map.md +0 -97
- package/skills/subagent-driven-development/SKILL.md +0 -277
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +0 -26
- package/skills/subagent-driven-development/implementer-prompt.md +0 -113
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +0 -61
- package/skills/systematic-debugging/CREATION-LOG.md +0 -119
- package/skills/systematic-debugging/SKILL.md +0 -296
- package/skills/systematic-debugging/condition-based-waiting-example.ts +0 -158
- package/skills/systematic-debugging/condition-based-waiting.md +0 -115
- package/skills/systematic-debugging/defense-in-depth.md +0 -122
- package/skills/systematic-debugging/find-polluter.sh +0 -63
- package/skills/systematic-debugging/root-cause-tracing.md +0 -169
- package/skills/systematic-debugging/test-academic.md +0 -14
- package/skills/systematic-debugging/test-pressure-1.md +0 -58
- package/skills/systematic-debugging/test-pressure-2.md +0 -68
- package/skills/systematic-debugging/test-pressure-3.md +0 -69
- package/skills/test-driven-development/SKILL.md +0 -371
- package/skills/test-driven-development/testing-anti-patterns.md +0 -299
- package/skills/using-git-worktrees/SKILL.md +0 -218
- package/skills/using-superpowers/SKILL.md +0 -134
- package/skills/using-superpowers/references/codex-tools.md +0 -25
- package/skills/using-superpowers/references/gemini-tools.md +0 -33
- package/skills/verification-before-completion/SKILL.md +0 -139
- package/skills/workflow-runner/SKILL.md +0 -172
- package/skills/writing-plans/SKILL.md +0 -152
- package/skills/writing-plans/plan-document-reviewer-prompt.md +0 -49
- package/skills/writing-skills/SKILL.md +0 -654
- package/skills/writing-skills/anthropic-best-practices.md +0 -1149
- package/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +0 -189
- package/skills/writing-skills/graphviz-conventions.dot +0 -172
- package/skills/writing-skills/persuasion-principles.md +0 -187
- package/skills/writing-skills/render-graphs.js +0 -168
- package/skills/writing-skills/testing-skills-with-subagents.md +0 -384
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
【claude code调用标识:systematic-debugging】【trae调用标识:systematic-debugging+系统性调试】【流程场景:4.Bug处理】
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
name: systematic-debugging
|
|
5
|
+
description: 在遇到任何错误、测试失败或意外行为时使用,在提出修复方案之前
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# 系统性调试
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
随机修复浪费时间并创建新错误。快速补丁掩盖潜在问题。
|
|
13
|
+
|
|
14
|
+
**核心原则:** 在尝试修复之前始终找到根本原因。症状修复是失败。
|
|
15
|
+
|
|
16
|
+
**违反此流程的字面意思就是违反调试的精神。**
|
|
17
|
+
|
|
18
|
+
## 铁律
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
没有根本原因调查,就没有修复
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
如果你还没有完成第 1 阶段,你不能提出修复方案。
|
|
25
|
+
|
|
26
|
+
## 何时使用
|
|
27
|
+
|
|
28
|
+
用于任何技术问题:
|
|
29
|
+
- 测试失败
|
|
30
|
+
- 生产中的错误
|
|
31
|
+
- 意外行为
|
|
32
|
+
- 性能问题
|
|
33
|
+
- 构建失败
|
|
34
|
+
- 集成问题
|
|
35
|
+
|
|
36
|
+
**特别使用当:**
|
|
37
|
+
- 在时间压力下(紧急情况使猜测变得诱人)
|
|
38
|
+
- "只需一个快速修复"看起来很明显
|
|
39
|
+
- 你已经尝试了多个修复
|
|
40
|
+
- 之前的修复不起作用
|
|
41
|
+
- 你不完全理解问题
|
|
42
|
+
|
|
43
|
+
**不要跳过当:**
|
|
44
|
+
- 问题看起来简单(简单错误也有根本原因)
|
|
45
|
+
- 你很匆忙(匆忙保证返工)
|
|
46
|
+
- 经理希望立即修复(系统性比混乱更快)
|
|
47
|
+
|
|
48
|
+
## 四个阶段
|
|
49
|
+
|
|
50
|
+
你必须完成每个阶段才能进入下一个阶段。
|
|
51
|
+
|
|
52
|
+
### 阶段 1:根本原因调查
|
|
53
|
+
|
|
54
|
+
**在尝试任何修复之前:**
|
|
55
|
+
|
|
56
|
+
1. **仔细阅读错误消息**
|
|
57
|
+
- 不要跳过错误或警告
|
|
58
|
+
- 它们通常包含确切的解决方案
|
|
59
|
+
- 完全阅读堆栈跟踪
|
|
60
|
+
- 注意行号、文件路径、错误代码
|
|
61
|
+
|
|
62
|
+
2. **一致地重现**
|
|
63
|
+
- 你能可靠地触发它吗?
|
|
64
|
+
- 确切的步骤是什么?
|
|
65
|
+
- 它每次都会发生吗?
|
|
66
|
+
- 如果不可重现 → 收集更多数据,不要猜测
|
|
67
|
+
|
|
68
|
+
3. **检查最近的更改**
|
|
69
|
+
- 什么更改可能导致此问题?
|
|
70
|
+
- Git diff,最近的提交
|
|
71
|
+
- 新依赖项,配置更改
|
|
72
|
+
- 环境差异
|
|
73
|
+
|
|
74
|
+
4. **在多组件系统中收集证据**
|
|
75
|
+
|
|
76
|
+
**当系统有多个组件时(CI → 构建 → 签名,API → 服务 → 数据库):**
|
|
77
|
+
|
|
78
|
+
**在提出修复之前,添加诊断工具:**
|
|
79
|
+
```
|
|
80
|
+
对于每个组件边界:
|
|
81
|
+
- 记录什么数据进入组件
|
|
82
|
+
- 记录什么数据离开组件
|
|
83
|
+
- 验证环境/配置传播
|
|
84
|
+
- 检查每层的状态
|
|
85
|
+
|
|
86
|
+
运行一次以收集显示它在哪里中断的证据
|
|
87
|
+
然后分析证据以识别失败的组件
|
|
88
|
+
然后调查该特定组件
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**示例(多层系统):**
|
|
92
|
+
```bash
|
|
93
|
+
# 第 1 层:工作流
|
|
94
|
+
echo "=== 工作流中可用的密钥:==="
|
|
95
|
+
echo "IDENTITY: ${IDENTITY:+SET}${IDENTITY:-UNSET}"
|
|
96
|
+
|
|
97
|
+
# 第 2 层:构建脚本
|
|
98
|
+
echo "=== 构建脚本中的环境变量:==="
|
|
99
|
+
env | grep IDENTITY || echo "IDENTITY 不在环境中"
|
|
100
|
+
|
|
101
|
+
# 第 3 层:签名脚本
|
|
102
|
+
echo "=== 钥匙串状态:==="
|
|
103
|
+
security list-keychains
|
|
104
|
+
security find-identity -v
|
|
105
|
+
|
|
106
|
+
# 第 4 层:实际签名
|
|
107
|
+
codesign --sign "$IDENTITY" --verbose=4 "$APP"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**这揭示:** 哪一层失败(密钥 → 工作流 ✓,工作流 → 构建 ✗)
|
|
111
|
+
|
|
112
|
+
5. **跟踪数据流**
|
|
113
|
+
|
|
114
|
+
**当错误在调用堆栈深处时:**
|
|
115
|
+
|
|
116
|
+
请参阅此目录中的 `root-cause-tracing.md` 了解完整的向后跟踪技术。
|
|
117
|
+
|
|
118
|
+
**快速版本:**
|
|
119
|
+
- 坏值源自哪里?
|
|
120
|
+
- 什么用坏值调用了这个?
|
|
121
|
+
- 继续向上跟踪直到找到源
|
|
122
|
+
- 在源处修复,而不是在症状处
|
|
123
|
+
|
|
124
|
+
### 阶段 2:模式分析
|
|
125
|
+
|
|
126
|
+
**在修复前找到模式:**
|
|
127
|
+
|
|
128
|
+
1. **找到工作示例**
|
|
129
|
+
- 在同一代码库中定位类似的工作代码
|
|
130
|
+
- 什么与损坏的代码类似但能工作?
|
|
131
|
+
|
|
132
|
+
2. **与参考进行比较**
|
|
133
|
+
- 如果实现模式,完全阅读参考实现
|
|
134
|
+
- 不要浏览 - 阅读每一行
|
|
135
|
+
- 在应用前完全理解模式
|
|
136
|
+
|
|
137
|
+
3. **识别差异**
|
|
138
|
+
- 工作的和损坏的之间有什么不同?
|
|
139
|
+
- 列出每个差异,无论多小
|
|
140
|
+
- 不要假设"那不重要"
|
|
141
|
+
|
|
142
|
+
4. **理解依赖关系**
|
|
143
|
+
- 这需要其他哪些组件?
|
|
144
|
+
- 需要什么设置、配置、环境?
|
|
145
|
+
- 它做了什么假设?
|
|
146
|
+
|
|
147
|
+
### 阶段 3:假设和测试
|
|
148
|
+
|
|
149
|
+
**科学方法:**
|
|
150
|
+
|
|
151
|
+
1. **形成单一假设**
|
|
152
|
+
- 明确说明:"我认为 X 是根本原因,因为 Y"
|
|
153
|
+
- 写下来
|
|
154
|
+
- 具体,不要模糊
|
|
155
|
+
|
|
156
|
+
2. **最小测试**
|
|
157
|
+
- 做最小可能的更改来测试假设
|
|
158
|
+
- 一次一个变量
|
|
159
|
+
- 不要一次修复多个问题
|
|
160
|
+
|
|
161
|
+
3. **继续前验证**
|
|
162
|
+
- 它工作了吗?是 → 阶段 4
|
|
163
|
+
- 没工作?形成新假设
|
|
164
|
+
- 不要在上面添加更多修复
|
|
165
|
+
|
|
166
|
+
4. **当你不知道时**
|
|
167
|
+
- 说"我不理解 X"
|
|
168
|
+
- 不要假装知道
|
|
169
|
+
- 寻求帮助
|
|
170
|
+
- 研究更多
|
|
171
|
+
|
|
172
|
+
### 阶段 4:实施
|
|
173
|
+
|
|
174
|
+
**修复根本原因,不是症状:**
|
|
175
|
+
|
|
176
|
+
1. **创建失败测试用例**
|
|
177
|
+
- 最简单的可能复现
|
|
178
|
+
- 尽可能自动测试
|
|
179
|
+
- 如果没有框架,使用一次性测试脚本
|
|
180
|
+
- 修复前必须有
|
|
181
|
+
- 使用 `superpowers:test-driven-development` 技能编写适当的失败测试
|
|
182
|
+
|
|
183
|
+
2. **实施单一修复**
|
|
184
|
+
- 解决已识别的根本原因
|
|
185
|
+
- 一次一个更改
|
|
186
|
+
- 没有"顺便"改进
|
|
187
|
+
- 没有捆绑重构
|
|
188
|
+
|
|
189
|
+
3. **验证修复**
|
|
190
|
+
- 测试现在通过了吗?
|
|
191
|
+
- 没有其他测试损坏?
|
|
192
|
+
- 问题实际解决了?
|
|
193
|
+
|
|
194
|
+
4. **如果修复不起作用**
|
|
195
|
+
- 停止
|
|
196
|
+
- 计数:你尝试了多少个修复?
|
|
197
|
+
- 如果 < 3:返回阶段 1,用新信息重新分析
|
|
198
|
+
- **如果 ≥ 3:停止并质疑架构(见下面的步骤 5)**
|
|
199
|
+
- 不要在没有架构讨论的情况下尝试修复 #4
|
|
200
|
+
|
|
201
|
+
5. **如果 3+ 修复失败:质疑架构**
|
|
202
|
+
|
|
203
|
+
**表明架构问题的模式:**
|
|
204
|
+
- 每个修复都揭示不同地方的新共享状态/耦合/问题
|
|
205
|
+
- 修复需要"大规模重构"来实现
|
|
206
|
+
- 每个修复都在其他地方创建新症状
|
|
207
|
+
|
|
208
|
+
**停止并质疑基础:**
|
|
209
|
+
- 这个模式从根本上是否健全?
|
|
210
|
+
- 我们是否"仅仅因为惯性而坚持它"?
|
|
211
|
+
- 我们应该重构架构还是继续修复症状?
|
|
212
|
+
|
|
213
|
+
**在尝试更多修复之前与你的人类伙伴讨论**
|
|
214
|
+
|
|
215
|
+
这不是失败的假设 - 这是错误的架构。
|
|
216
|
+
|
|
217
|
+
## 红旗 - 停止并遵循流程
|
|
218
|
+
|
|
219
|
+
如果你发现自己在想:
|
|
220
|
+
- "现在快速修复,以后调查"
|
|
221
|
+
- "只需尝试更改 X 看看是否有效"
|
|
222
|
+
- "添加多个更改,运行测试"
|
|
223
|
+
- "跳过测试,我会手动验证"
|
|
224
|
+
- "可能是 X,让我修复它"
|
|
225
|
+
- "我不完全理解,但这可能有效"
|
|
226
|
+
- "模式说 X 但我会以不同方式适应它"
|
|
227
|
+
- "这里是主要问题:[列出没有调查的修复]"
|
|
228
|
+
- 在跟踪数据流之前提出解决方案
|
|
229
|
+
- **"再尝试一次修复"(已经尝试了 2+)**
|
|
230
|
+
- **每个修复都揭示不同地方的新问题**
|
|
231
|
+
|
|
232
|
+
**所有这些都意味着:停止。返回阶段 1。**
|
|
233
|
+
|
|
234
|
+
**如果 3+ 修复失败:** 质疑架构(见阶段 4.5)
|
|
235
|
+
|
|
236
|
+
## 你的人类伙伴的信号你做错了
|
|
237
|
+
|
|
238
|
+
**注意这些重定向:**
|
|
239
|
+
- "那不是发生了吗?" - 你未经验证就假设
|
|
240
|
+
- "它会告诉我们...?" - 你应该添加证据收集
|
|
241
|
+
- "停止猜测" - 你在不理解的情况下提出修复
|
|
242
|
+
- "超级思考这个" - 质疑基础,而不仅仅是症状
|
|
243
|
+
- "我们卡住了?"(沮丧)- 你的方法不起作用
|
|
244
|
+
|
|
245
|
+
**当你看到这些:** 停止。返回阶段 1。
|
|
246
|
+
|
|
247
|
+
## 常见的合理化
|
|
248
|
+
|
|
249
|
+
| 借口 | 现实 |
|
|
250
|
+
|------|------|
|
|
251
|
+
| "问题简单,不需要流程" | 简单问题也有根本原因。流程对简单错误很快。 |
|
|
252
|
+
| "紧急情况,没时间流程" | 系统性调试比猜测和检查的混乱更快。 |
|
|
253
|
+
| "先试试这个,然后调查" | 第一个修复设定模式。从一开始就做对。 |
|
|
254
|
+
| "我会在确认修复有效后写测试" | 未经测试的修复不会持久。先测试证明它。 |
|
|
255
|
+
| "一次多个修复节省时间" | 无法隔离什么有效。导致新错误。 |
|
|
256
|
+
| "参考太长,我会适应模式" | 部分理解保证错误。完全阅读它。 |
|
|
257
|
+
| "我看到问题了,让我修复它" | 看到症状 ≠ 理解根本原因。 |
|
|
258
|
+
| "再尝试一次修复"(2+ 失败后) | 3+ 失败 = 架构问题。质疑模式,不要再修复。 |
|
|
259
|
+
|
|
260
|
+
## 快速参考
|
|
261
|
+
|
|
262
|
+
| 阶段 | 关键活动 | 成功标准 |
|
|
263
|
+
|------|----------|----------|
|
|
264
|
+
| **1. 根本原因** | 阅读错误,重现,检查更改,收集证据 | 理解 WHAT 和 WHY |
|
|
265
|
+
| **2. 模式** | 找到工作示例,比较 | 识别差异 |
|
|
266
|
+
| **3. 假设** | 形成理论,最小测试 | 确认或新假设 |
|
|
267
|
+
| **4. 实施** | 创建测试,修复,验证 | 错误解决,测试通过 |
|
|
268
|
+
|
|
269
|
+
## 当流程揭示"无根本原因"时
|
|
270
|
+
|
|
271
|
+
如果系统性调查揭示问题确实是环境性、时间依赖性或外部的:
|
|
272
|
+
|
|
273
|
+
1. 你已经完成了流程
|
|
274
|
+
2. 记录你调查了什么
|
|
275
|
+
3. 实施适当的处理(重试,超时,错误消息)
|
|
276
|
+
4. 添加监控/日志以便将来调查
|
|
277
|
+
|
|
278
|
+
**但:** 95% 的"无根本原因"案例是调查不完整。
|
|
279
|
+
|
|
280
|
+
## 支持技术
|
|
281
|
+
|
|
282
|
+
这些技术是系统性调试的一部分,在此目录中可用:
|
|
283
|
+
|
|
284
|
+
- **`root-cause-tracing.md`** - 通过调用堆栈向后跟踪错误以找到原始触发器
|
|
285
|
+
- **`defense-in-depth.md`** - 在找到根本原因后在多个层添加验证
|
|
286
|
+
- **`condition-based-waiting.md`** - 用条件轮询替换任意超时
|
|
287
|
+
|
|
288
|
+
**相关技能:**
|
|
289
|
+
- **superpowers:test-driven-development** - 用于创建失败测试用例(阶段 4,步骤 1)
|
|
290
|
+
- **superpowers:verification-before-completion** - 在声称成功之前验证修复有效
|
|
291
|
+
|
|
292
|
+
## 现实影响
|
|
293
|
+
|
|
294
|
+
来自调试会话:
|
|
295
|
+
- 系统方法:15-30 分钟修复
|
|
296
|
+
- 随机修复方法:2-3 小时混乱
|
|
297
|
+
- 首次修复率:95% 对 40%
|
|
298
|
+
- 引入的新错误:几乎为零对常见
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
【claude code调用标识:test-driven-development】【trae调用标识:test-driven-development+测试驱动开发】【流程场景:1.完整3阶段SDD流程、3.小型功能迭代、4.Bug处理】
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
name: test-driven-development
|
|
5
|
+
description: 在编写实现代码之前,实现任何功能或错误修复时使用
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# 测试驱动开发 (TDD)
|
|
9
|
+
|
|
10
|
+
## 概述
|
|
11
|
+
|
|
12
|
+
先写测试。看着它失败。编写最小代码使其通过。
|
|
13
|
+
|
|
14
|
+
**核心原则:** 如果你没有看到测试失败,你就不知道它是否测试了正确的东西。
|
|
15
|
+
|
|
16
|
+
**违反规则的字面意思就是违反规则的精神。**
|
|
17
|
+
|
|
18
|
+
## 何时使用
|
|
19
|
+
|
|
20
|
+
**始终:**
|
|
21
|
+
- 新功能
|
|
22
|
+
- 错误修复
|
|
23
|
+
- 重构
|
|
24
|
+
- 行为变更
|
|
25
|
+
|
|
26
|
+
**例外(询问你的人类伙伴):**
|
|
27
|
+
- 一次性原型
|
|
28
|
+
- 生成的代码
|
|
29
|
+
- 配置文件
|
|
30
|
+
|
|
31
|
+
想“就这一次跳过 TDD”?停止。那是合理化。
|
|
32
|
+
|
|
33
|
+
## 铁律
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
没有先失败的测试,就没有生产代码
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
在测试之前写代码?删除它。重新开始。
|
|
40
|
+
|
|
41
|
+
**没有例外:**
|
|
42
|
+
- 不要将其作为“参考”保留
|
|
43
|
+
- 不要在编写测试时“适应”它
|
|
44
|
+
- 不要看它
|
|
45
|
+
- 删除意味着删除
|
|
46
|
+
|
|
47
|
+
从测试中重新实现。就这样。
|
|
48
|
+
|
|
49
|
+
## 红-绿-重构
|
|
50
|
+
|
|
51
|
+
```dot
|
|
52
|
+
digraph tdd_cycle {
|
|
53
|
+
rankdir=LR;
|
|
54
|
+
red [label="RED\n编写失败的测试", shape=box, style=filled, fillcolor="#ffcccc"];
|
|
55
|
+
verify_red [label="验证失败\n正确", shape=diamond];
|
|
56
|
+
green [label="GREEN\n最小代码", shape=box, style=filled, fillcolor="#ccffcc"];
|
|
57
|
+
verify_green [label="验证通过\n全部绿色", shape=diamond];
|
|
58
|
+
refactor [label="REFACTOR\n清理", shape=box, style=filled, fillcolor="#ccccff"];
|
|
59
|
+
next [label="下一个", shape=ellipse];
|
|
60
|
+
|
|
61
|
+
red -> verify_red;
|
|
62
|
+
verify_red -> green [label="是"];
|
|
63
|
+
verify_red -> red [label="错误\n失败"];
|
|
64
|
+
green -> verify_green;
|
|
65
|
+
verify_green -> refactor [label="是"];
|
|
66
|
+
verify_green -> green [label="否"];
|
|
67
|
+
refactor -> verify_green [label="保持\n绿色"];
|
|
68
|
+
verify_green -> next;
|
|
69
|
+
next -> red;
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 红 - 编写失败的测试
|
|
74
|
+
|
|
75
|
+
编写一个最小测试,显示应该发生什么。
|
|
76
|
+
|
|
77
|
+
<Good>
|
|
78
|
+
```typescript
|
|
79
|
+
test('重试失败操作 3 次', async () => {
|
|
80
|
+
let attempts = 0;
|
|
81
|
+
const operation = () => {
|
|
82
|
+
attempts++;
|
|
83
|
+
if (attempts < 3) throw new Error('fail');
|
|
84
|
+
return 'success';
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const result = await retryOperation(operation);
|
|
88
|
+
|
|
89
|
+
expect(result).toBe('success');
|
|
90
|
+
expect(attempts).toBe(3);
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
名称清晰,测试真实行为,一个测试一个行为
|
|
94
|
+
</Good>
|
|
95
|
+
|
|
96
|
+
<Bad>
|
|
97
|
+
```typescript
|
|
98
|
+
test('重试有效', async () => {
|
|
99
|
+
const mock = jest.fn()
|
|
100
|
+
.mockRejectedValueOnce(new Error())
|
|
101
|
+
.mockRejectedValueOnce(new Error())
|
|
102
|
+
.mockResolvedValueOnce('success');
|
|
103
|
+
await retryOperation(mock);
|
|
104
|
+
expect(mock).toHaveBeenCalledTimes(3);
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
名称模糊,测试模拟而非代码
|
|
108
|
+
</Bad>
|
|
109
|
+
|
|
110
|
+
**要求:**
|
|
111
|
+
- 一个行为
|
|
112
|
+
- 清晰的名称
|
|
113
|
+
- 真实代码(除非不可避免,否则不要使用模拟)
|
|
114
|
+
|
|
115
|
+
### 验证红 - 看着它失败
|
|
116
|
+
|
|
117
|
+
**必须执行。永远不要跳过。**
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npm test path/to/test.test.ts
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
确认:
|
|
124
|
+
- 测试失败(不是错误)
|
|
125
|
+
- 失败消息符合预期
|
|
126
|
+
- 失败是因为功能缺失(不是拼写错误)
|
|
127
|
+
|
|
128
|
+
**测试通过?** 你在测试现有行为。修复测试。
|
|
129
|
+
|
|
130
|
+
**测试错误?** 修复错误,重新运行直到正确失败。
|
|
131
|
+
|
|
132
|
+
### 绿 - 最小代码
|
|
133
|
+
|
|
134
|
+
编写最简单的代码以通过测试。
|
|
135
|
+
|
|
136
|
+
<Good>
|
|
137
|
+
```typescript
|
|
138
|
+
async function retryOperation<T>(fn: () => Promise<T>): Promise<T> {
|
|
139
|
+
for (let i = 0; i < 3; i++) {
|
|
140
|
+
try {
|
|
141
|
+
return await fn();
|
|
142
|
+
} catch (e) {
|
|
143
|
+
if (i === 2) throw e;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
throw new Error('unreachable');
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
刚好足够通过
|
|
150
|
+
</Good>
|
|
151
|
+
|
|
152
|
+
<Bad>
|
|
153
|
+
```typescript
|
|
154
|
+
async function retryOperation<T>(
|
|
155
|
+
fn: () => Promise<T>,
|
|
156
|
+
options?: {
|
|
157
|
+
maxRetries?: number;
|
|
158
|
+
backoff?: 'linear' | 'exponential';
|
|
159
|
+
onRetry?: (attempt: number) => void;
|
|
160
|
+
}
|
|
161
|
+
): Promise<T> {
|
|
162
|
+
// YAGNI
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
过度设计
|
|
166
|
+
</Bad>
|
|
167
|
+
|
|
168
|
+
不要添加功能、重构其他代码或超出测试范围的“改进”。
|
|
169
|
+
|
|
170
|
+
### 验证绿 - 看着它通过
|
|
171
|
+
|
|
172
|
+
**必须执行。**
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
npm test path/to/test.test.ts
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
确认:
|
|
179
|
+
- 测试通过
|
|
180
|
+
- 其他测试仍然通过
|
|
181
|
+
- 输出纯净(无错误、警告)
|
|
182
|
+
|
|
183
|
+
**测试失败?** 修复代码,不是测试。
|
|
184
|
+
|
|
185
|
+
**其他测试失败?** 立即修复。
|
|
186
|
+
|
|
187
|
+
### 重构 - 清理
|
|
188
|
+
|
|
189
|
+
仅在绿色之后:
|
|
190
|
+
- 移除重复
|
|
191
|
+
- 改进名称
|
|
192
|
+
- 提取辅助函数
|
|
193
|
+
|
|
194
|
+
保持测试绿色。不要添加行为。
|
|
195
|
+
|
|
196
|
+
### 重复
|
|
197
|
+
|
|
198
|
+
下一个失败的测试用于下一个功能。
|
|
199
|
+
|
|
200
|
+
## 好的测试
|
|
201
|
+
|
|
202
|
+
| 质量 | 好 | 坏 |
|
|
203
|
+
|------|----|----|
|
|
204
|
+
| **最小** | 一个行为。名称中有 "and"?拆分它。 | `test('validates email and domain and whitespace')` |
|
|
205
|
+
| **清晰** | 名称描述行为 | `test('test1')` |
|
|
206
|
+
| **展示意图** | 演示期望的 API | 掩盖代码应该做什么 |
|
|
207
|
+
|
|
208
|
+
## 为什么顺序很重要
|
|
209
|
+
|
|
210
|
+
**"我会在之后写测试来验证它有效"**
|
|
211
|
+
|
|
212
|
+
在代码之后写的测试立即通过。立即通过证明不了什么:
|
|
213
|
+
- 可能测试错误的东西
|
|
214
|
+
- 可能测试实现,而不是行为
|
|
215
|
+
- 可能遗漏你忘记的边缘情况
|
|
216
|
+
- 你从未看到它捕获错误
|
|
217
|
+
|
|
218
|
+
测试优先迫使你看到测试失败,证明它实际上测试了某些东西。
|
|
219
|
+
|
|
220
|
+
**"我已经手动测试了所有边缘情况"**
|
|
221
|
+
|
|
222
|
+
手动测试是临时的。你认为你测试了一切,但:
|
|
223
|
+
- 没有记录你测试了什么
|
|
224
|
+
- 代码更改时无法重新运行
|
|
225
|
+
- 在压力下容易忘记情况
|
|
226
|
+
- "我尝试时它有效" ≠ 全面
|
|
227
|
+
|
|
228
|
+
自动化测试是系统的。它们每次都以相同的方式运行。
|
|
229
|
+
|
|
230
|
+
**"删除 X 小时的工作是浪费的"**
|
|
231
|
+
|
|
232
|
+
沉没成本谬误。时间已经过去了。你现在的选择:
|
|
233
|
+
- 删除并重写 TDD(再 X 小时,高信心)
|
|
234
|
+
- 保留它并在之后添加测试(30 分钟,低信心,可能有错误)
|
|
235
|
+
|
|
236
|
+
"浪费"是保留你不能信任的代码。没有真实测试的工作代码是技术债务。
|
|
237
|
+
|
|
238
|
+
**"TDD 是教条的,务实意味着适应"**
|
|
239
|
+
|
|
240
|
+
TDD 就是务实:
|
|
241
|
+
- 在提交前发现错误(比之后调试更快)
|
|
242
|
+
- 防止回归(测试立即捕获中断)
|
|
243
|
+
- 记录行为(测试展示如何使用代码)
|
|
244
|
+
- 启用重构(自由更改,测试捕获中断)
|
|
245
|
+
|
|
246
|
+
"务实"的捷径 = 在生产中调试 = 更慢。
|
|
247
|
+
|
|
248
|
+
**"测试之后达到相同的目标 - 这是精神不是仪式"**
|
|
249
|
+
|
|
250
|
+
不。测试之后回答"这做什么?"。测试之前回答"这应该做什么?"。
|
|
251
|
+
|
|
252
|
+
测试之后被你的实现所偏见。你测试你构建的东西,而不是需要的东西。你验证记住的边缘情况,而不是发现的边缘情况。
|
|
253
|
+
|
|
254
|
+
测试之前迫使在实现之前发现边缘情况。测试之后验证你记住了一切(你没有)。
|
|
255
|
+
|
|
256
|
+
30 分钟的测试之后 ≠ TDD。你获得覆盖率,失去测试工作的证明。
|
|
257
|
+
|
|
258
|
+
## 常见的合理化
|
|
259
|
+
|
|
260
|
+
| 借口 | 现实 |
|
|
261
|
+
|------|------|
|
|
262
|
+
| "太简单了,不需要测试" | 简单代码会中断。测试需要 30 秒。 |
|
|
263
|
+
| "我会之后测试" | 立即通过的测试证明不了什么。 |
|
|
264
|
+
| "测试之后达到相同的目标" | 测试之后 = "这做什么?" 测试之前 = "这应该做什么?" |
|
|
265
|
+
| "已经手动测试过了" | 临时 ≠ 系统。无记录,无法重新运行。 |
|
|
266
|
+
| "删除 X 小时是浪费的" | 沉没成本谬误。保留未验证的代码是技术债务。 |
|
|
267
|
+
| "保留作为参考,先写测试" | 你会适应它。那是测试之后。删除意味着删除。 |
|
|
268
|
+
| "需要先探索" | 很好。扔掉探索,从 TDD 开始。 |
|
|
269
|
+
| "测试难 = 设计不清" | 听测试的。难测试 = 难使用。 |
|
|
270
|
+
| "TDD 会减慢我" | TDD 比调试快。务实 = 测试优先。 |
|
|
271
|
+
| "手动测试更快" | 手动不能证明边缘情况。你会重新测试每个更改。 |
|
|
272
|
+
| "现有代码没有测试" | 你正在改进它。为现有代码添加测试。 |
|
|
273
|
+
|
|
274
|
+
## 红旗 - 停止并重新开始
|
|
275
|
+
|
|
276
|
+
- 测试之前的代码
|
|
277
|
+
- 实现之后的测试
|
|
278
|
+
- 测试立即通过
|
|
279
|
+
- 无法解释测试为什么失败
|
|
280
|
+
- "稍后"添加的测试
|
|
281
|
+
- 合理化"就这一次"
|
|
282
|
+
- "我已经手动测试过了"
|
|
283
|
+
- "测试之后达到相同的目的"
|
|
284
|
+
- "这是精神不是仪式"
|
|
285
|
+
- "保留作为参考"或"适应现有代码"
|
|
286
|
+
- "已经花了 X 小时,删除是浪费的"
|
|
287
|
+
- "TDD 是教条的,我在务实"
|
|
288
|
+
- "这不同因为..."
|
|
289
|
+
|
|
290
|
+
**所有这些都意味着:删除代码。用 TDD 重新开始。**
|
|
291
|
+
|
|
292
|
+
## 示例:错误修复
|
|
293
|
+
|
|
294
|
+
**错误:** 接受空电子邮件
|
|
295
|
+
|
|
296
|
+
**红**
|
|
297
|
+
```typescript
|
|
298
|
+
test('拒绝空电子邮件', async () => {
|
|
299
|
+
const result = await submitForm({ email: '' });
|
|
300
|
+
expect(result.error).toBe('Email required');
|
|
301
|
+
});
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**验证红**
|
|
305
|
+
```bash
|
|
306
|
+
$ npm test
|
|
307
|
+
失败:期望 'Email required',得到 undefined
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
**绿**
|
|
311
|
+
```typescript
|
|
312
|
+
function submitForm(data: FormData) {
|
|
313
|
+
if (!data.email?.trim()) {
|
|
314
|
+
return { error: 'Email required' };
|
|
315
|
+
}
|
|
316
|
+
// ...
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
**验证绿**
|
|
321
|
+
```bash
|
|
322
|
+
$ npm test
|
|
323
|
+
通过
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
**重构**
|
|
327
|
+
如果需要,提取多个字段的验证。
|
|
328
|
+
|
|
329
|
+
## 验证清单
|
|
330
|
+
|
|
331
|
+
在标记工作完成之前:
|
|
332
|
+
|
|
333
|
+
- [ ] 每个新函数/方法都有测试
|
|
334
|
+
- [ ] 每个测试在实现前都看到失败
|
|
335
|
+
- [ ] 每个测试因预期原因失败(功能缺失,不是拼写错误)
|
|
336
|
+
- [ ] 为每个测试编写最小代码以通过
|
|
337
|
+
- [ ] 所有测试通过
|
|
338
|
+
- [ ] 输出纯净(无错误、警告)
|
|
339
|
+
- [ ] 测试使用真实代码(仅在不可避免时使用模拟)
|
|
340
|
+
- [ ] 覆盖边缘情况和错误
|
|
341
|
+
|
|
342
|
+
无法检查所有框?你跳过了 TDD。重新开始。
|
|
343
|
+
|
|
344
|
+
## 卡住时
|
|
345
|
+
|
|
346
|
+
| 问题 | 解决方案 |
|
|
347
|
+
|------|----------|
|
|
348
|
+
| 不知道如何测试 | 编写期望的 API。先编写断言。询问你的人类伙伴。 |
|
|
349
|
+
| 测试太复杂 | 设计太复杂。简化接口。 |
|
|
350
|
+
| 必须模拟一切 | 代码耦合度太高。使用依赖注入。 |
|
|
351
|
+
| 测试设置庞大 | 提取辅助函数。仍然复杂?简化设计。 |
|
|
352
|
+
|
|
353
|
+
## 调试集成
|
|
354
|
+
|
|
355
|
+
发现错误?编写重现错误的失败测试。遵循 TDD 循环。测试证明修复并防止回归。
|
|
356
|
+
|
|
357
|
+
永远不要没有测试就修复错误。
|
|
358
|
+
|
|
359
|
+
## 测试反模式
|
|
360
|
+
|
|
361
|
+
添加模拟或测试实用程序时,阅读 @testing-anti-patterns.md 以避免常见陷阱:
|
|
362
|
+
- 测试模拟行为而不是真实行为
|
|
363
|
+
- 向生产类添加仅测试方法
|
|
364
|
+
- 在不理解依赖关系的情况下模拟
|
|
365
|
+
|
|
366
|
+
## 最终规则
|
|
367
|
+
|
|
368
|
+
```
|
|
369
|
+
生产代码 → 测试存在且首先失败
|
|
370
|
+
否则 → 不是 TDD
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
未经你的人类伙伴许可,无例外。
|