superpowers-zh 1.7.4 → 1.7.6

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.
@@ -9,7 +9,7 @@
9
9
  {
10
10
  "name": "superpowers-zh",
11
11
  "description": "AI 编程超能力中文增强版:20 个 skills(14 翻译 + 4 中国原创 + 2 上游历史保留),支持 Claude Code / Hermes Agent / Cursor / Claw Code / Qoder 等 22 款工具",
12
- "version": "1.7.4",
12
+ "version": "1.7.6",
13
13
  "source": "./",
14
14
  "author": {
15
15
  "name": "jnMetaCode",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "superpowers-zh",
3
3
  "description": "AI 编程超能力中文增强版:20 个 skills(14 翻译 + 4 中国原创 + 2 上游历史保留),支持 Claude Code / Hermes Agent / Cursor / Claw Code / Qoder 等 22 款工具",
4
- "version": "1.7.4",
4
+ "version": "1.7.6",
5
5
  "author": {
6
6
  "name": "jnMetaCode",
7
7
  "url": "https://github.com/jnMetaCode"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superpowers-zh",
3
- "version": "1.7.4",
3
+ "version": "1.7.6",
4
4
  "description": "AI 编程超能力中文增强版:头脑风暴、subagent 驱动开发、规划、TDD、调试、代码审查、收尾工作流,附 4 个中文 skills 沉淀。",
5
5
  "author": {
6
6
  "name": "jnMetaCode",
@@ -2,7 +2,7 @@
2
2
  "name": "superpowers-zh",
3
3
  "displayName": "Superpowers 中文版",
4
4
  "description": "AI 编程超能力中文增强版:20 个 skills(14 翻译 + 4 中国原创 + 2 上游历史保留),支持 Cursor / Claude Code / Hermes Agent / Claw Code / Qoder 等 22 款工具",
5
- "version": "1.7.4",
5
+ "version": "1.7.6",
6
6
  "author": {
7
7
  "name": "jnMetaCode",
8
8
  "url": "https://github.com/jnMetaCode"
package/README.md CHANGED
@@ -16,7 +16,10 @@ Chinese community edition of [superpowers](https://github.com/obra/superpowers)
16
16
  >
17
17
  > 🌍 Also available in [English](https://aiolaola.com/en?utm_source=github&utm_campaign=superpowers) · [日本語](https://aiolaola.com/ja?utm_source=github&utm_campaign=superpowers) · [Español](https://aiolaola.com/es?utm_source=github&utm_campaign=superpowers) · [한국어](https://aiolaola.com/ko?utm_source=github&utm_campaign=superpowers) · [繁體中文](https://aiolaola.com/zh-Hant?utm_source=github&utm_campaign=superpowers)
18
18
 
19
- > 🆕 **v1.7.4 更新亮点**([完整 Release Notes →](RELEASE-NOTES.zh.md))
19
+ > 🆕 **v1.7.6 更新亮点**([完整 Release Notes →](RELEASE-NOTES.zh.md))
20
+ > - 🎯 **上游 v6.2.0 对齐完成** —— audit 的结构漂移告警清零;C 块盘点时发现其中 3 项不是风格改动而是实质新规则
21
+ > - 🐛 **两个 worktree / Gemini 的真问题** —— 修掉 worktree 清理静默空转;更正「Gemini 不支持子智能体」的错误说法(原说法会让 3 个 skill 在 Gemini CLI 上瘸腿)
22
+ > - 🔄 **测试参考重构** —— `testing-anti-patterns` → `writing-good-tests`:从 5 个反模式清单改为两条原则 + 变异检查
20
23
  > - 🔄 **SDD 同步上游 v6.2.0** —— plan 作用域工作区(一份过期账本再也不会让控制者跳过整段任务)+ 五轮上限的唤回式修复循环与熔断裁定
21
24
  > - 🪟 **Windows bootstrap 修复** —— SessionStart hook 改经 Git Bash 分发(同步上游),hook 不加载 skill 就是死重
22
25
  > - 🧩 新增 **Cline** 与 **Kilo Code** 两款 VS Code 扩展(工具数 20 → 22)—— 按 rules 常驻开销做了专门设计,索引仅 4.5 KB
package/README.zh-Hant.md CHANGED
@@ -16,7 +16,10 @@ Chinese community edition of [superpowers](https://github.com/obra/superpowers)
16
16
 
17
17
  > 📖 **免費配套學習** → [從零學會 AI 編程](https://aiolaola.com/?utm_source=github&utm_campaign=superpowers):180 節免費實操課 + 《AI 編程實戰三卷書》線上閱讀 + 實戰社群 · superpowers 裝好後配上方法論效率翻倍 · 永久免費
18
18
 
19
- > 🆕 **v1.7.4 更新亮點**([完整 Release Notes →](RELEASE-NOTES.zh.md))
19
+ > 🆕 **v1.7.6 更新亮點**([完整 Release Notes →](RELEASE-NOTES.zh.md))
20
+ > - 🎯 **上游 v6.2.0 對齊完成** —— audit 的結構漂移告警清零;C 塊盤點時發現其中 3 項不是風格改動而是實質新規則
21
+ > - 🐛 **兩個 worktree / Gemini 的真問題** —— 修掉 worktree 清理靜默空轉;更正「Gemini 不支援子智能體」的錯誤說法(原說法會讓 3 個 skill 在 Gemini CLI 上瘸腿)
22
+ > - 🔄 **測試參考重構** —— `testing-anti-patterns` → `writing-good-tests`:從 5 個反模式清單改為兩條原則 + 變異檢查
20
23
  > - 🔄 **SDD 同步上游 v6.2.0** —— plan 作用域工作區(一份過期帳本再也不會讓控制者跳過整段任務)+ 五輪上限的喚回式修復循環與熔斷裁定
21
24
  > - 🪟 **Windows bootstrap 修復** —— SessionStart hook 改經 Git Bash 分發(同步上游),hook 不載入 skill 就是死重
22
25
  > - 🧩 新增 **Cline** 與 **Kilo Code** 兩款 VS Code 外掛(工具數 20 → 22)—— 針對 rules 常駐開銷做了專門設計,索引僅 4.5 KB
@@ -6,6 +6,94 @@
6
6
 
7
7
  ---
8
8
 
9
+ ## v1.7.6 (2026-08-08)
10
+
11
+ **上游 v6.2.0 对齐完成** —— [#19](https://github.com/jnMetaCode/superpowers-zh/issues/19) 的 C 块收尾,`scripts/audit.sh` 的上游结构漂移告警**清零**。
12
+
13
+ ### 🧾 盘点先行:其中 3 项不是风格性改动
14
+
15
+ C 块表面上是 14 个 `refactor(skills)` commit("drop social proof"、"drop The Bottom Line"、"fold into rationalization table"),看着像上游在统一自己的文风。开工前做了逐 commit 盘点,判定标准定为**「删掉的文字里有没有别处没写的规则」**——结论纠正了原本的假设:
16
+
17
+ - **`cfb6281`** 新增了一张 rationalization 表(2 行**全新规则**),替换掉「与工作流的集成」那份清单
18
+ - **`03147d2`** 给 `executing-plans` 加了「先确保隔离工作区」作为**步骤 1**(SDD 那一半已随 A 块完成)
19
+ - **`bc86802`** 把「常见错误」5 个小节 + 「红线」Never/Always 双清单压成 5 行表,**规则一条不少**——这也是此前唯一有客观漂移证据的 skill
20
+
21
+ ### ✂️ 其余各项逐条核实后才删
22
+
23
+ | skill | 删掉的 | 规则去哪了 |
24
+ |---|---|---|
25
+ | `receiving-code-review` | 「底线」 | 概述已有「核心原则:先验证再实施。先提问再假设」 |
26
+ | `writing-skills` | 「总结」 | 铁律节 + TDD 循环表已完整承载 |
27
+ | `writing-plans` | 「注意事项」 | 精确路径 / `Run:` / 预期输出 三条都**内建在任务结构模板**里——上游是把「告知」改成「示范」 |
28
+ | `brainstorming` | 「核心原则」6 条 | 5 条已在流程详述逐条体现;YAGNI 按上游移到「探索方案」的使用现场 |
29
+ | `systematic-debugging` | 「实际效果」+ 社会证明句 | 核心原则行保留;「相关技能」块折入第四阶段「验证修复」 |
30
+ | `dispatching-parallel-agents` | 「核心优势」「实际效果」 | 验证节保留 |
31
+ | `verification-before-completion` | 「为什么这很重要」「底线」 | 「证据先于宣称」核心原则行保留 |
32
+ | `executing-plans` | 质量宣称、「集成」 | 按上游改写为平铺平台清单 |
33
+
34
+ ### ✅ 验证
35
+
36
+ **结构**:10 个 skill 的 H2 数与上游逐一对齐(8 个完全相同、2 个差 1);`executing-plans` / `using-git-worktrees` / `requesting-code-review` 的 `superpowers:` 引用集与上游**完全一致**。
37
+
38
+ **行为 eval —— 两轮共 11 题全对。** 专门考被删段落里的规则是否仍生效:原生 worktree 工具 vs `git worktree add`(答出「第一大错误」与「幽灵状态」)、跳过 `check-ignore` 的后果、目录名优先级、基线失败能否继续、能否无证据宣称完成、审查建议有疑问时该照做还是反驳、能否先打补丁再查根因、能否自己读 diff 代替派审查者(命中 `cfb6281` 新增表行)、方案里的「以后可能用得上」怎么处理(命中 YAGNI 新落点)。
39
+
40
+ **回归**:`scripts/audit.sh` **150 pass / 0 warn / 0 fail**、`scripts/verify-release.sh` **82 pass / 0 fail**。
41
+
42
+ > audit PASS 由 152 降至 150 —— 上游有意删除的两个「集成」节里各有 `superpowers:` 引用,Category 4b 因此少 2 项检查;引用集已核对与上游一致。
43
+
44
+ ---
45
+
46
+ ## v1.7.5 (2026-08-07)
47
+
48
+ 对齐上游 v6.2.0 的 **B 块 + D 块**([#19](https://github.com/jnMetaCode/superpowers-zh/issues/19))。
49
+
50
+ ### 🐛 worktree 清理静默空转(真 bug,我们与上游同样存在)
51
+
52
+ `finishing-a-development-branch` 的步骤 6 在步骤 5 已经 `cd` 到主仓库根之后,才用 `git rev-parse --show-toplevel` 重算 `WORKTREE_PATH` —— 于是拿到主根路径,`.worktrees/` 溯源判断**永远匹配不上**,清理静默空转,随后分支删除还会因为 worktree 仍挂着而失败。上游记录说测试对象不得不偏离 skill 原文才能跑通。
53
+
54
+ 修法:步骤 2 趁还在工作区内就捕获,步骤 6 消费该值并加显式警告说明为何不能重算;去掉步骤 6 冗余的 `MAIN_ROOT` 推导与 `cd`;选项 2 补上菜单已声称的分离 HEAD 推送变体。
55
+
56
+ **已实际复现验证**(临时仓库 + `.worktrees/feature`):旧逻辑算得 `main` → 溯源未命中 → 清理空转;新逻辑捕获到 `main/.worktrees/feature` → 命中 → `worktree remove` 与 `branch -D` 均成功。
57
+
58
+ ### 🐛 我们把 Gemini 的子智能体支持写错了
59
+
60
+ `gemini-tools.md` 原文称 Gemini CLI 没有 Task 等价物、依赖子智能体的 skill「退化为 `executing-plans` 单会话执行」。**这是错的** —— Gemini CLI 通过 `invoke_agent`(`agent_name: "generalist"`,也可用 `@generalist` 聊天语法)支持子智能体,且支持同一响应内多调用并行分派。
61
+
62
+ 这个错误会让 Gemini CLI 用户的 `subagent-driven-development` / `dispatching-parallel-agents` / `requesting-code-review` 全部瘸腿。按上游重写(33 → 62 行),补齐指令文件层级加载、`~/.gemini/skills` 与 `~/.agents/skills` 优先级、模板填写、并行分派,以及此前缺失的 20 个工具名。已全仓扫描确认无别处重复该说法。
63
+
64
+ ### 🔄 `testing-anti-patterns.md` → `writing-good-tests.md`
65
+
66
+ 上游把 299 行的反模式枚举重写为 198 行的**两条原则**:
67
+
68
+ - **原则 1「点名它要抓的破坏」** —— 写测试体前先答"什么生产改动会让它失败,那是 bug 还是决定"。含镜像断言、变更探测器、测行为不测文本、测你的代码不测框架
69
+ - **原则 2「跑真东西」** —— mock 不配拥有断言、在正确层级 mock、替身要具体、完整镜像真实数据、生产类只承载生产方法
70
+ - 新增**变异检查**:收尾前在脑中变异生产代码,每种现实变异都应至少让一个测试失败
71
+ - 触发条件放宽到「编写或修改**任何**测试时」
72
+
73
+ TDD SKILL.md 同步:删掉「为什么顺序很重要」整节长散文(论点折进合理化借口表,5 行扩写)、删掉末尾已失效的「测试反模式」一节。
74
+
75
+ ### 🔧 audit 结构漂移度量修正(此前一直在虚报欠账)
76
+
77
+ `audit.sh` 用 `grep -cE '^#{1,4} '` 数标题,但这会把 ``` 围栏内的 shell 注释(`# 运行测试`)当成 markdown 标题 —— 多几行 bash 注释就能凭空造出「结构漂移」。
78
+
79
+ 用正确口径(awk 逐行跟踪围栏)重算 14 个 skill,3 条告警里 **2 条是假阳性**:
80
+
81
+ | skill | 旧口径 | 新口径 |
82
+ |---|---|---|
83
+ | `executing-plans` | 9/16 **WARN** | 9/11 pass |
84
+ | `finishing-a-development-branch` | 21/31 **WARN** | 14/17 pass |
85
+ | `using-git-worktrees` | 21/28 WARN | 14/21 **WARN(真漂移)** |
86
+
87
+ 双向验证:给 `brainstorming` 加 5 个真标题会触发告警,加 5 行围栏内 shell 注释不触发。
88
+
89
+ ### ✅ 验证
90
+
91
+ - 两个新/改文件章节均与上游一一对应;`writing-good-tests.md` 指标精确一致(12 bold 要点 / 11 行表格 / 11 条危险信号 / 14 项代码记号)
92
+ - **行为 eval 8 个判断场景:8/8 全对**。附带一个有价值的对照:agent 拿不到 `writing-good-tests.md`、只能退回 SKILL.md 四条摘要时得分 6/8 —— 错的恰好是只存在于参考文件里的两条规则(部分 mock 静默失败、琐碎转发 getter 不配有测试)。说明参考文件承载着摘要覆盖不到的承重规则。
93
+ - `scripts/audit.sh` **152 pass / 1 warn / 0 fail**(原 150/3)、`scripts/verify-release.sh` **82 pass / 0 fail**
94
+
95
+ ---
96
+
9
97
  ## v1.7.4 (2026-08-07)
10
98
 
11
99
  ### 🔄 SDD 同步上游 v6.2.0:plan 作用域工作区 + 基于唤回的修复循环(#19 A 块)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superpowers-zh",
3
3
  "description": "AI 编程超能力中文版 — TDD、调试、代码审查等经过实战验证的工作方法论",
4
- "version": "1.7.4",
4
+ "version": "1.7.6",
5
5
  "contextFileName": "GEMINI.md"
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superpowers-zh",
3
- "version": "1.7.4",
3
+ "version": "1.7.6",
4
4
  "engines": {
5
5
  "node": ">=20.0.0"
6
6
  },
@@ -87,6 +87,7 @@ digraph brainstorming {
87
87
  - 提出 2-3 种不同的方案及其权衡
88
88
  - 以对话的方式展示选项,附上你的推荐和理由
89
89
  - 先展示你推荐的方案并解释原因
90
+ - 严格遵循 YAGNI —— 从每个方案和设计里移除不必要的功能
90
91
 
91
92
  **展示设计:**
92
93
 
@@ -140,15 +141,6 @@ digraph brainstorming {
140
141
  - 调用 writing-plans 技能创建详细的实现计划
141
142
  - 不要调用任何其他技能。writing-plans 是下一步。
142
143
 
143
- ## 核心原则
144
-
145
- - **每次一个问题** — 不要同时抛出多个问题
146
- - **优先选择题** — 在可能的情况下比开放式问题更容易回答
147
- - **严格遵循 YAGNI** — 从所有设计中移除不必要的功能
148
- - **探索替代方案** — 在做决定之前始终提出 2-3 种方案
149
- - **增量验证** — 展示设计,获得批准后再继续
150
- - **保持灵活** — 有不明确的地方就回头澄清
151
-
152
144
  ## 视觉伴侣
153
145
 
154
146
  一个基于浏览器的伴侣工具,用于在头脑风暴过程中展示原型、图表和视觉选项。它是一个工具——不是一种模式。接受伴侣意味着它可用于适合视觉呈现的问题;并不意味着每个问题都要通过浏览器。
@@ -160,15 +160,6 @@ Task("修复 tool-approval-race-conditions.test.ts 的失败")
160
160
 
161
161
  **集成:** 所有修复互相独立,无冲突,完整测试套件全部通过
162
162
 
163
- **节省的时间:** 3 个问题并行解决 vs 顺序解决
164
-
165
- ## 核心优势
166
-
167
- 1. **并行化** - 多个排查同时进行
168
- 2. **聚焦** - 每个智能体范围窄,需要跟踪的上下文少
169
- 3. **独立性** - 智能体之间互不干扰
170
- 4. **速度** - 3 个问题在 1 个问题的时间内解决
171
-
172
163
  ## 验证
173
164
 
174
165
  智能体返回后:
@@ -177,11 +168,3 @@ Task("修复 tool-approval-race-conditions.test.ts 的失败")
177
168
  3. **运行完整套件** - 验证所有修复协同工作
178
169
  4. **抽查** - 智能体可能犯系统性错误
179
170
 
180
- ## 实际效果
181
-
182
- 来自调试会话(2025-10-03):
183
- - 3 个文件中 6 个失败
184
- - 并行分派 3 个智能体
185
- - 所有排查并发完成
186
- - 所有修复成功集成
187
- - 智能体之间的更改零冲突
@@ -16,16 +16,17 @@ metadata:
16
16
 
17
17
  **开始时宣布:** "我正在使用 executing-plans 技能来实现此计划。"
18
18
 
19
- **注意:** 告诉你的人类伙伴,Superpowers 在有子代理支持时效果好得多。如果在支持子代理的平台上运行(如 Claude Code Codex),其工作质量会显著提高。如果子代理可用,请使用 superpowers:subagent-driven-development 而非此技能。
19
+ **注意:** 告诉你的人类伙伴,Superpowers 在有子代理支持时效果好得多(Claude Code、Codex CLI、Codex App、Copilot CLI 与 Gemini CLI 都算;见 `../using-superpowers/references/` 下的各平台工具参考)。如果子代理可用,请使用 superpowers:subagent-driven-development 而非此技能。
20
20
 
21
21
  ## 流程
22
22
 
23
23
  ### 步骤 1:加载并审查计划
24
24
 
25
- 1. 读取计划文件
26
- 2. 批判性审查——识别计划中的任何问题或疑虑
27
- 3. 如果有疑虑:在开始之前向你的人类伙伴提出
28
- 4. 如果没有疑虑:创建 TodoWrite 并继续
25
+ 1. 确保有一个隔离的工作区:用 superpowers:using-git-worktrees 创建一个,或者核实已有的那个
26
+ 2. 读取计划文件
27
+ 3. 批判性审查——识别计划中的任何问题或疑虑
28
+ 4. 如果有疑虑:在开始之前向你的人类伙伴提出
29
+ 5. 如果没有疑虑:创建 TodoWrite 并继续
29
30
 
30
31
  **审查时重点检查:**
31
32
  - 步骤之间是否有依赖遗漏?(A 依赖 B,但 B 排在 A 之后)
@@ -172,9 +173,3 @@ $ git commit -m "feat: 添加用户输入验证(任务 2/5)"
172
173
  - 遇到阻塞时停下来,不要猜测
173
174
  - 未经用户明确同意,绝不在 main/master 分支上开始实现
174
175
 
175
- ## 集成
176
-
177
- **必需的工作流技能:**
178
- - **superpowers:using-git-worktrees** - 必需:开始前建立隔离的工作空间
179
- - **superpowers:writing-plans** - 创建此技能要执行的计划
180
- - **superpowers:finishing-a-development-branch** - 所有任务完成后收尾开发
@@ -50,6 +50,9 @@ npm test / cargo test / pytest / go test ./...
50
50
  ```bash
51
51
  GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
52
52
  GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
53
+ # 现在就捕获 —— 此刻还在工作区里面。步骤 5 会切换目录,
54
+ # 而清理(步骤 6)需要这个值
55
+ WORKTREE_PATH=$(git rev-parse --show-toplevel)
53
56
  ```
54
57
 
55
58
  这决定了展示哪种菜单、以及清理方式:
@@ -129,6 +132,8 @@ git branch -d <feature-branch>
129
132
  ```bash
130
133
  # 推送分支
131
134
  git push -u origin <feature-branch>
135
+ # 从分离 HEAD 出发时,在远端指定新分支名:
136
+ # git push origin HEAD:refs/heads/<new-branch>
132
137
 
133
138
  # 创建 PR
134
139
  gh pr create --title "<title>" --body "$(cat <<'EOF'
@@ -179,21 +184,15 @@ git branch -D <feature-branch>
179
184
 
180
185
  ### 步骤 6:清理工作区
181
186
 
182
- **只对选项 1 和 4 执行。** 选项 2 和 3 始终保留 worktree
187
+ **只对选项 1 和 4 执行。** 选项 2 和 3 始终保留 worktree。两个调用方都已经切到主仓库根目录了 —— 移除 worktree 必须从 worktree 外面执行 —— 因此这里使用**步骤 2 里捕获的** `GIT_DIR` / `GIT_COMMON` / `WORKTREE_PATH`,也就是那次目录切换之前的值。
183
188
 
184
- ```bash
185
- GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
186
- GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
187
- WORKTREE_PATH=$(git rev-parse --show-toplevel)
188
- ```
189
+ > ⚠️ **不要在这里重新计算这些值。** 此刻 `git rev-parse --show-toplevel` 返回的是主仓库根目录,不是 worktree 路径 —— 溯源判断会永远匹配不上,清理会静默空转,随后分支删除还会因为 worktree 仍挂着而失败。
189
190
 
190
191
  **如果 `GIT_DIR == GIT_COMMON`:** 普通仓库,无 worktree 可清理。结束。
191
192
 
192
- **如果 worktree 路径在 `.worktrees/` 或 `worktrees/` 之下:** 这是 Superpowers 创建的 worktree —— 我们负责清理。
193
+ **如果 `WORKTREE_PATH` `.worktrees/` 或 `worktrees/` 之下:** 这是 Superpowers 创建的 worktree —— 我们负责清理。
193
194
 
194
195
  ```bash
195
- MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
196
- cd "$MAIN_ROOT"
197
196
  git worktree remove "$WORKTREE_PATH"
198
197
  git worktree prune # 自愈:清理任何过期的注册记录
199
198
  ```
@@ -209,10 +209,3 @@ metadata:
209
209
 
210
210
  在 GitHub 上回复行内审查评论时,在评论线程中回复(`gh api repos/{owner}/{repo}/pulls/{pr}/comments/{id}/replies`),不要发顶层 PR 评论。
211
211
 
212
- ## 底线
213
-
214
- **外部反馈 = 待评估的建议,不是必须执行的命令。**
215
-
216
- 验证。质疑。然后实施。
217
-
218
- 不要敷衍附和。始终保持技术严谨。
@@ -10,7 +10,7 @@ metadata:
10
10
 
11
11
  # 请求代码审查
12
12
 
13
- 派遣代码审查子代理,在问题扩散之前发现它们。审查者获得的是精心组织的评估上下文——绝不是你的会话历史。这样可以让审查者专注于工作成果而非你的思考过程,同时保留你自己的上下文以便继续工作。
13
+ 派遣代码审查子代理,在问题扩散之前发现它们。审查者获得的是精心组织的评估上下文——绝不是你的会话历史。
14
14
 
15
15
  **核心原则:** 早审查,勤审查。
16
16
 
@@ -77,20 +77,12 @@ HEAD_SHA=$(git rev-parse HEAD)
77
77
  [继续任务 3]
78
78
  ```
79
79
 
80
- ## 与工作流的集成
80
+ ## 常见的合理化借口
81
81
 
82
- **子代理驱动开发:**
83
- - 每个任务完成后审查
84
- - 在问题叠加之前发现它们
85
- - 修复后再进入下一个任务
86
-
87
- **执行计划:**
88
- - 每个任务完成后或在自然 checkpoint 审查
89
- - 获取反馈,应用,继续
90
-
91
- **临时开发:**
92
- - 合并前审查
93
- - 卡住时审查
82
+ | 借口 | 现实 |
83
+ |------|------|
84
+ | "我自己看一下 diff 就行了,不用专门派审查者" | 你是协调者——在自己的会话里读 diff 会烧掉你继续推进工作所需的上下文窗口。派一个审查子智能体:diff 和评估过程都待在它的上下文里,只有结论回到你这里。 |
85
+ | "审查者需要我的全部会话历史才能理解这次改动" | 给它精心组织的上下文,绝不给会话历史。这样审查者才会盯着工作成果,而不是你的思考过程。 |
94
86
 
95
87
  ## 红线
96
88
 
@@ -12,8 +12,6 @@ metadata:
12
12
 
13
13
  ## 概述
14
14
 
15
- 随意修复既浪费时间又会引入新 bug。草率的补丁只会掩盖深层问题。
16
-
17
15
  **核心原则:** 在尝试修复之前,务必先找到根本原因。只修症状就是失败。
18
16
 
19
17
  **敷衍走流程等于违背调试的精神。**
@@ -193,6 +191,7 @@ metadata:
193
191
  - 测试现在通过了吗?
194
192
  - 其他测试没有被破坏吧?
195
193
  - 问题真的解决了吗?
194
+ - 宣称成功之前,使用 `superpowers:verification-before-completion` 技能
196
195
 
197
196
  4. **如果修复不起作用**
198
197
  - 停下来
@@ -288,14 +287,3 @@ metadata:
288
287
  - **`defense-in-depth.md`** - 找到根因后,在多个层级添加校验
289
288
  - **`condition-based-waiting.md`** - 用条件轮询替代硬编码等待时间
290
289
 
291
- **相关技能:**
292
- - **superpowers:test-driven-development** - 用于创建失败测试用例(第四阶段,第 1 步)
293
- - **superpowers:verification-before-completion** - 在宣称成功之前验证修复确实有效
294
-
295
- ## 实际效果
296
-
297
- 调试实践中的数据:
298
- - 系统化方法:15-30 分钟修复
299
- - 随意修复方法:2-3 小时反复折腾
300
- - 一次修复成功率:95% vs 40%
301
- - 引入新 bug:几乎为零 vs 经常发生
@@ -208,69 +208,25 @@ npm test path/to/test.test.ts
208
208
  | **清晰** | 名称描述行为 | `test('test1')` |
209
209
  | **展示意图** | 展示期望的 API | 掩盖了代码应该做什么 |
210
210
 
211
- ## 为什么顺序很重要
212
-
213
- **"我先写完再补测试来验证"**
214
-
215
- 后写的测试立即通过。立即通过什么也证明不了:
216
- - 可能测试了错误的东西
217
- - 可能测试的是实现而非行为
218
- - 可能遗漏了你忘掉的边界情况
219
- - 你从未看到它捕获 bug
220
-
221
- 先写测试迫使你看到测试失败,证明它确实在测试某些东西。
222
-
223
- **"我已经手动测试了所有边界情况"**
224
-
225
- 手动测试是临时的。你以为你测试了所有情况,但是:
226
- - 没有测试记录
227
- - 代码变更后无法重新运行
228
- - 在压力下容易遗忘
229
- - "我试过了能跑" 不等于 全面测试
230
-
231
- 自动化测试是系统性的。它们每次以相同方式运行。
232
-
233
- **"删除 X 小时的工作太浪费了"**
234
-
235
- 沉没成本谬误。时间已经花了。你现在的选择:
236
- - 删除并用 TDD 重写(再花 X 小时,高信心)
237
- - 保留并后补测试(30 分钟,低信心,可能有 bug)
238
-
239
- "浪费"的是保留你无法信任的代码。没有真正测试的可运行代码就是技术债。
240
-
241
- **"TDD 太教条了,务实意味着灵活变通"**
242
-
243
- TDD 就是务实的:
244
- - 在 commit 前发现 bug(比事后调试快)
245
- - 防止回归(测试立即发现破坏)
246
- - 记录行为(测试展示如何使用代码)
247
- - 支持重构(放心修改,测试捕获破坏)
248
-
249
- "务实的"捷径 = 在生产环境调试 = 更慢。
250
-
251
- **"后补测试也能达到相同目的——重要的是精神不是仪式"**
252
-
253
- 不对。后补测试回答"这段代码做了什么?"先写测试回答"这段代码应该做什么?"
254
-
255
- 后补测试受你实现的偏见影响。你测试的是你构建的东西,而非需求要求的。你验证的是你记得的边界情况,而非发现的。
256
-
257
- 先写测试迫使你在实现前发现边界情况。后补测试验证的是你记住了所有情况(你没有)。
258
-
259
- 30 分钟的后补测试 ≠ TDD。你得到了覆盖率,但失去了测试有效的证明。
211
+ 写任何测试、或修改任何测试时,阅读 [writing-good-tests.md](writing-good-tests.md),那里是让测试保持诚实的规则:
212
+ - 在动手写之前,先点名那个会让该测试失败的生产代码改动
213
+ - 断言真实行为,绝不断言 mock 行为
214
+ - 只有测试才用的代码放在测试工具里,不进生产类
215
+ - 在 mock 一个依赖之前,先搞清它的副作用
260
216
 
261
217
  ## 常见借口
262
218
 
263
219
  | 借口 | 现实 |
264
220
  |------|------|
265
221
  | "太简单了不用测" | 简单的代码也会出 bug。测试只需 30 秒。 |
266
- | "我之后补测试" | 立即通过的测试什么也证明不了。 |
267
- | "后补测试也能达到相同目的" | 后补测试 = "这做了什么?" 先写测试 = "这应该做什么?" |
268
- | "已经手动测试过了" | 临时测试系统测试。无记录,无法重现。 |
269
- | "删除 X 小时的工作太浪费" | 沉没成本谬误。保留未验证的代码就是技术债。 |
222
+ | "我之后补测试" | 后写的测试立即通过——而立即通过什么都证明不了。它可能测错了对象、测的是实现而不是行为、或者漏掉你忘了的那个边界情况。你从没看着它失败过,所以你从没证明它能抓住 bug。先写测试逼你看到那次失败。 |
223
+ | "后补测试也能达到相同目的(重的是精神不是仪式)" | 后补测试回答的是"这做了什么?";先写测试回答的是"这应该做什么?"后写的测试已经被你写好的代码带偏了——你验证的是你**记得**的那些情况,而不是你本该**发现**的那些。有覆盖率,没有测试有效的证明。 |
224
+ | "已经手动测试过了" | 手动测试是临时的:没有记录你覆盖了什么、代码一改就没法重跑、压力之下极易漏掉情况。"我试的时候是好的"全面。自动化测试每次都以同样的方式运行。 |
225
+ | "删除 X 小时的工作太浪费" | 沉没成本谬误——那些时间无论怎样都已经花掉了。真正的选择是:用 TDD 重写(高置信度)vs 留着它事后补测试(低置信度、很可能有 bug)。留着你无法信任的代码才是浪费。 |
270
226
  | "留作参考,然后先写测试" | 你会去改编它。那就是后补测试。删除就是删除。 |
271
227
  | "需要先探索一下" | 可以。探索完了扔掉,从 TDD 开始。 |
272
228
  | "测试难写 = 设计不清楚" | 听测试的。难以测试 = 难以使用。 |
273
- | "TDD 会拖慢我" | TDD 比调试快。务实 = 先写测试。 |
229
+ | "TDD 会拖慢我" | TDD **就是**务实的那条路:在提交前抓住 bug、防止回归、让你能无所畏惧地重构。所谓"务实"的抄近道,等于在生产环境里调试——更慢,不是更快。 |
274
230
  | "手动测试更快" | 手动测试无法证明边界情况。每次修改你都得重新测。 |
275
231
  | "现有代码没有测试" | 你在改进它。为现有代码补测试。 |
276
232
 
@@ -359,13 +315,6 @@ PASS
359
315
 
360
316
  绝不在没有测试的情况下修复 bug。
361
317
 
362
- ## 测试反模式
363
-
364
- 添加 mock 或测试工具时,阅读 @testing-anti-patterns.md 以避免常见陷阱:
365
- - 测试 mock 行为而非真实行为
366
- - 在生产类中添加仅测试用的方法
367
- - 在不理解依赖的情况下使用 mock
368
-
369
318
  ## 最终规则
370
319
 
371
320
  ```
@@ -0,0 +1,145 @@
1
+ # 写好测试
2
+
3
+ **在以下情况加载此参考:** 编写或修改测试、添加 mock、或为测试添加清理/辅助方法时。
4
+
5
+ ## 概述
6
+
7
+ 一个测试的存在是为了抓住某个**具体的**破坏。这里的一切都由两条原则统辖:
8
+
9
+ ```
10
+ 1. 每个测试都点名它要抓的破坏
11
+ 2. 每个测试都跑真东西
12
+ ```
13
+
14
+ 严格的 TDD 会自然产出这两点:一个先写、并且在真实代码上亲眼看着它失败过的测试,已经证明了自己**能**失败;而只有当真实依赖被证明缓慢或属于外部时,mock 才配被引入。
15
+
16
+ ## 原则 1:点名它要抓的破坏
17
+
18
+ 在写测试体之前,先回答:**什么样的生产代码改动应该让这个测试失败——而那个改动是 bug 还是一个决定?** 一个测试靠抓住走错的分支、缺失的副作用、传错的参数、边界情况或被破坏的契约来赢得它的位置。
19
+
20
+ **独立推导期望值。** 用字面量和手工核对过的 fixture;带字面量 `want` 值的表驱动测试是首选形态。一个由**被测代码本身**(或它的辅助函数)算出来的期望值,无论那段代码干了什么都会通过:
21
+
22
+ ```typescript
23
+ // ❌ 镜像断言:同一个 builder 算出了等式两边 —— 永远为真
24
+ const expected = buildSearchQuery({ tag: 'urgent' });
25
+ expect(buildSearchQuery({ tag: 'urgent' })).toBe(expected);
26
+
27
+ // ✅ 手工推导的字面量
28
+ expect(buildSearchQuery({ tag: 'urgent' })).toBe('tag:"urgent"');
29
+ ```
30
+
31
+ **不要写变更探测器。** 如果只有**有意为之的决定**才能让一个测试失败——某个常量的取值、某句消息的精确措辞、某个私有结构——那它会在重新设计时误报、却对真 bug 一路沉睡。要测那个**依赖于该决定的行为**:不是 `expect(MAX_RETRIES).toBe(5)`,而是"一次失败的调用会被重试 5 次,且第 6 次尝试永不发生"。
32
+
33
+ **测行为,不测文本。** 断言某个脚本、skill 或配置文件"包含某一行",只能证明源文件就是源文件。要拿受控输入去**跑**脚本,然后断言它的输出、副作用或退出码。用来指挥 agent 的文档,靠消费它的 agent 的行为来测(superpowers:writing-skills);写给人看的散文根本不该有测试。
34
+
35
+ **测你的代码,不测框架。** 测你的代码在其边界上所做的契约——你注册的那条路由、你发出的那条查询、你产出的那个 payload。上游的机制是它们维护者该写的测试(经典反例:断言你的 router 会调用一个已注册的 handler——那是框架的测试,不是你的)。当上游行为**确实**让你意外时,写一个窄窄的表征测试,把那个假设点名出来。同样的边界也适用于你代码内部:构造函数、getter、常量和琐碎的转发,只有当它们做校验、归一化、给默认值、做推导、做强制或产生副作用时才配有测试——否则就去断言第一个依赖于它们、且对消费者可见的结果。
36
+
37
+ ### 门控函数
38
+
39
+ ```
40
+ 在写测试体之前:
41
+ 点名那个会让这个测试失败的生产代码改动。
42
+
43
+ 点不出来 → 围绕一个可观察的行为重新设计
44
+ "源文本变了" → 去跑这个产物,断言它的效果
45
+ 只有有意为之的决定能让它失败 → 这是变更探测器;改测那个
46
+ 依赖于该决定的行为
47
+
48
+ 确认期望值的推导过程没有用到被测代码。
49
+ 如果它复用了被测代码的逻辑或辅助函数:
50
+ 换成字面量或手工核对过的 fixture
51
+ ```
52
+
53
+ ## 原则 2:跑真东西
54
+
55
+ **mock 不配拥有断言。** 一个针对 mock 的断言,在 mock 存在时通过、在 mock 缺席时失败——它对被测组件什么都没说。要断言**真实组件**的行为;如果你要检查的就是那个 mock,那就把它 unmock,或者把这条断言删掉。
56
+
57
+ ```typescript
58
+ // ✅ 真实行为
59
+ expect(screen.getByRole('navigation')).toBeInTheDocument();
60
+
61
+ // ❌ mock 是否存在
62
+ expect(screen.getByTestId('sidebar-mock')).toBeInTheDocument();
63
+ ```
64
+
65
+ **你的人类伙伴会这样纠正你:** "我们是在测一个 mock 的行为吗?"
66
+
67
+ **在正确的层级上 mock。** 在替换真实方法之前,先搞清它的每一个副作用;只 mock 掉慢的或外部的那一步操作,把测试真正依赖的东西保留为真实的。不确定时,先拿真实实现跑一遍测试,观察实际上必须发生什么。
68
+
69
+ ```typescript
70
+ // ❌ 这个 mock 吞掉了配置写入,而重复检测正是要读它
71
+ vi.mock('ToolCatalog', () => ({
72
+ discoverAndCacheTools: vi.fn().mockResolvedValue(undefined)
73
+ }));
74
+
75
+ // ✅ 只 mock 掉缓慢的服务器启动;配置写入保持真实
76
+ vi.mock('MCPServerManager');
77
+ ```
78
+
79
+ **让替身足够具体。** 当参数、调用次数或调用顺序本身就是契约的一部分时,就要断言它们——一个什么都接受的 fake 什么都没验证。给每个分支(成功、报错、格式错误)配它自己的 fixture 或 spy,这样走错的分支就无法满足期望。
80
+
81
+ **完整镜像真实数据。** 按现实中的**完整结构**来 mock——所有有文档的字段——而不是只 mock 你这个测试会读的那几个。部分 mock 会静默失败:下游代码读到一个被省略的字段时,测试通过、集成崩掉。
82
+
83
+ **生产类只承载生产方法。** 只有测试才需要的清理逻辑,放在测试工具里,绝不作为生产类上的 `destroy()`。自问:这个方法只被测试调用吗?这个类拥有这份资源的生命周期吗?答错了 → 挪进测试工具。
84
+
85
+ **宁可用真实组件,也不要复杂 mock。** 当 mock 的搭建代码超过测试逻辑本身、mock 漏掉了真实组件才有的方法、或者 mock 一改测试就崩时,改成用真实组件的集成测试。**你的人类伙伴会这样问:** "这里我们真的需要用 mock 吗?"
86
+
87
+ ### 门控函数
88
+
89
+ ```
90
+ 在添加 mock 或测试辅助函数之前:
91
+ 列出真实方法的副作用;测试所依赖的那些保持真实 ——
92
+ 只 mock 它们下面那一层「慢的/外部的」。
93
+
94
+ mock 的返回值要完整镜像真实结构。
95
+
96
+ 只被测试调用的方法,属于测试工具,不属于生产代码。
97
+
98
+ 正要对 mock 本身下断言?
99
+ 把它 unmock,或者删掉这条断言。
100
+ ```
101
+
102
+ ## 测试与实现一同交付
103
+
104
+ TDD 循环——失败的测试、最小实现、重构——就是"完成"的定义。交付这个行为**需要**的测试,且只交付这些:琐碎代码和给人看的散文都不配有测试,而一个为了满足流程而写的测试会永远付出维护代价。
105
+
106
+ ## 变异检查
107
+
108
+ 收尾之前,在脑子里对生产代码做变异;对每一种现实的变异,都应至少有一个测试失败:
109
+
110
+ - 常量或参数写错
111
+ - 分支处理写错
112
+ - 缺失状态变更或副作用
113
+ - 返回空值或默认值
114
+ - 缺失对零值、空值、nil、未授权或格式错误输入的校验
115
+
116
+ 一个没有任何测试能抓住的变异,标记出该行为无保护——或者那个测试是同义反复。
117
+
118
+ ## 快速参考
119
+
120
+ | 当你…… | 就这么做 |
121
+ |--------|---------|
122
+ | 写任何测试 | 点名它要抓的破坏——是 bug,不是决定 |
123
+ | 构造期望值 | 手工推导;绝不用被测代码去算 |
124
+ | 测一个脚本或文档 | 跑它 / 压测它的消费者;绝不 grep 它的文本 |
125
+ | 想给依赖写测试 | 测你的边界契约,不测它们有文档的机制 |
126
+ | 想对一个被 mock 的元素下断言 | 改测真实组件,或者把它 unmock |
127
+ | 正要 mock 某个方法 | 先搞清它的副作用;在慢的/外部的那一层上 mock |
128
+ | 构造一个 mock 返回值 | 完整镜像真实结构 |
129
+ | 需要只有测试才用的清理逻辑 | 放进测试工具 |
130
+ | 眼看 mock 搭建代码膨胀 | 改成用真实组件的集成测试 |
131
+ | 写完一个测试文件 | 跑一遍变异检查 |
132
+
133
+ ## 危险信号
134
+
135
+ - 搭建过程和断言共用同一个对象,等式必然成立
136
+ - 这个测试只可能因为 panic、崩溃或选择器缺失而失败
137
+ - 这个测试在每次有意改动时都失败,却从不在意外破坏时失败
138
+ - 期望值藏在循环、builder 或辅助函数背后
139
+ - 这个测试去 grep 源码文本,或者断言某个已删除的符号仍然是删除状态
140
+ - 就算只剩下框架,这个测试依然"成立"
141
+ - 这个测试是为覆盖率而存在的,不检查任何副作用或结果
142
+ - 某条断言检查的是 `*-mock` 这种 test ID,或者你把 mock 去掉它就失败
143
+ - 某个方法只被测试文件调用
144
+ - mock 搭建占了测试的一半以上,或者你说不出为什么需要这个 mock
145
+ - "为了安全起见"而 mock
@@ -164,62 +164,12 @@ npm test / cargo test / pytest / go test ./...
164
164
  | 基线测试失败 | 报告失败 + 询问 |
165
165
  | 无 package.json/Cargo.toml | 跳过依赖安装 |
166
166
 
167
- ## 常见错误
167
+ ## 常见的合理化借口
168
168
 
169
- ### harness 对抗
170
-
171
- - **问题:** 平台已经提供隔离的情况下还在用 `git worktree add`
172
- - **修复:** 步骤 0 检测现有隔离。步骤 1a 让位给原生工具。
173
-
174
- ### 跳过检测
175
-
176
- - **问题:** 在已有的 worktree 内嵌套创建另一个 worktree
177
- - **修复:** 创建任何东西之前都先跑步骤 0
178
-
179
- ### 跳过忽略验证
180
-
181
- - **问题:** worktree 内容被跟踪,污染 git status
182
- - **修复:** 创建项目本地 worktree 前始终使用 `git check-ignore`
183
-
184
- ### 假设目录位置
185
-
186
- - **问题:** 造成不一致、违反项目约定
187
- - **修复:** 遵循优先级:明确 instructions > 现有项目本地目录 > 默认
188
-
189
- ### 带着失败的测试继续
190
-
191
- - **问题:** 无法区分新 bug 和已有问题
192
- - **修复:** 报告失败,获得明确许可后再继续
193
-
194
- ## 红线
195
-
196
- **绝不:**
197
-
198
- - 步骤 0 已检测到现有隔离时还创建 worktree
199
- - 在已有原生 worktree 工具(如 `EnterWorktree`)的情况下还用 `git worktree add`。这是 #1 错误——有就用。
200
- - 跳过步骤 1a 直接跳到步骤 1b 的 git 命令
201
- - 不验证已忽略就创建项目本地 worktree
202
- - 跳过基线测试验证
203
- - 不询问就带着失败的测试继续
204
-
205
- **始终:**
206
-
207
- - 先跑步骤 0 检测
208
- - 优先原生工具,其次 git 回退
209
- - 遵循目录优先级:明确 instructions > 现有项目本地目录 > 默认
210
- - 项目本地目录验证已忽略
211
- - 自动检测并运行项目设置
212
- - 验证测试基线干净
213
-
214
- ## 集成
215
-
216
- **被以下技能调用:**
217
-
218
- - **brainstorming**(阶段 4)- 设计通过且需要实现时必需
219
- - **subagent-driven-development** - 执行任何任务前必需
220
- - **executing-plans** - 执行任何任务前必需
221
- - 任何需要隔离工作区的技能
222
-
223
- **配合使用:**
224
-
225
- - **finishing-a-development-branch** - 工作完成后清理时必需
169
+ | 借口 | 现实 |
170
+ |------|------|
171
+ | "我显然不在 worktree 里,不用检查" | 跑步骤 0。宿主环境创建的隔离和 submodule 都能骗过肉眼;只有检测命令能定论。 |
172
+ | "`git worktree add` 比去找原生工具快" | 原生工具(如 `EnterWorktree`)掌管位置、分支和清理。绕过它是**第一大错误** —— 会造出你的宿主环境看不见也管不了的幽灵状态。 |
173
+ | "这个 worktree 目录肯定已经被忽略了" | 跑 `git check-ignore`。一个没被忽略的 worktree 目录会把整棵树提交进仓库。 |
174
+ | "目录名随便取都行" | 明确指示 > 已存在的项目内目录 > `.worktrees/` 默认值。 |
175
+ | "工作区是全新的,基线测试可以先放放" | 基线不干净会让之后每一次失败都含义不明。现在就跑测试;越过失败继续是你人类伙伴的决定。 |
@@ -1,33 +1,63 @@
1
1
  # Gemini CLI 工具映射
2
2
 
3
- Skills 使用 Claude Code 的工具名称。在 Gemini CLI 中遇到这些名称时,请使用对应的平台等价工具:
4
-
5
- | Skill 中的引用 | Gemini CLI 等价工具 |
6
- |---------------|-------------------|
7
- | `Read`(读取文件) | `read_file` |
8
- | `Write`(创建文件) | `write_file` |
9
- | `Edit`(编辑文件) | `replace` |
10
- | `Bash`(执行命令) | `run_shell_command` |
11
- | `Grep`(搜索文件内容) | `grep_search` |
12
- | `Glob`(按名称搜索文件) | `glob` |
13
- | `TodoWrite`(任务跟踪) | `write_todos` |
14
- | `Skill` 工具(调用 skill) | `activate_skill` |
15
- | `WebSearch` | `google_web_search` |
16
- | `WebFetch` | `web_fetch` |
17
- | `Task` 工具(派遣子 agent) | 无等价工具——Gemini CLI 不支持子 agent |
18
-
19
- ## 不支持子 Agent
20
-
21
- Gemini CLI 没有 Claude Code `Task` 工具的等价物。依赖子 agent 派遣的 skills(`subagent-driven-development`、`dispatching-parallel-agents`)将退化为通过 `executing-plans` 进行单会话执行。
3
+ Skills 说的是动作("分派一个子智能体"、"建一条待办"、"读一个文件")。在 Gemini CLI 上,这些动作对应下面这些工具。
4
+
5
+ | Skill 请求的动作 | Gemini CLI 等价工具 |
6
+ |----------------|-------------------|
7
+ | 读取一个文件 | `read_file` |
8
+ | 一次读取多个文件 | `read_many_files` |
9
+ | 创建新文件 | `write_file` |
10
+ | 编辑文件 | `replace` |
11
+ | 执行 shell 命令 | `run_shell_command` |
12
+ | 搜索文件内容 | `grep_search` |
13
+ | 按名称查找文件 | `glob` |
14
+ | 列出文件和子目录 | `list_directory` |
15
+ | 抓取 URL | `web_fetch` |
16
+ | 搜索网页 | `google_web_search` |
17
+ | 调用一个 skill | `activate_skill` |
18
+ | 分派子智能体(`Subagent (general-purpose):` 模板) | `invoke_agent`,`agent_name: "generalist"`(也可用 `@generalist` 聊天语法调用——见[子智能体支持](#子智能体支持)) |
19
+ | 多个并行分派 | 同一条响应里发多个 `invoke_agent` 调用 |
20
+ | 任务跟踪("建一条待办"、"标记完成") | `write_todos`(状态:pending、in_progress、completed、cancelled、blocked) |
21
+
22
+ ## 指令文件
23
+
24
+ 当某个 skill 提到"你的指令文件"时,在 Gemini CLI 上指的是 **`GEMINI.md`**。Gemini CLI 按层级加载 `GEMINI.md`:全局的在 `~/.gemini/GEMINI.md`,项目级的在工作区目录及其各级父目录里,另外当某个工具访问子目录中的文件时,该子目录下的 `GEMINI.md` 也会被加载。
25
+
26
+ ## 个人 skills 目录
27
+
28
+ 用户级 skills 放在 **`~/.gemini/skills/`**,**`~/.agents/skills/`** 是跨运行时的别名目录(与 Codex、Copilot CLI 共用)。当同一层级下两个目录都存在时,`.agents/skills/` 优先。每个 skill 是一个子目录,里面有一份带 `name` 和 `description` frontmatter 的 `SKILL.md`。
29
+
30
+ ## 子智能体支持
31
+
32
+ Gemini CLI 通过 `invoke_agent` 工具分派子智能体,该工具接收 `agent_name` 和 `prompt` 两个参数。同一个分派动作也有聊天语法快捷方式:输入 `@generalist <prompt>` 等价于以 `agent_name: "generalist"` 调用 `invoke_agent`。内置的 agent 名包括 `generalist`、`cli_help`、`codebase_investigator`,以及(启用浏览器工具后的)`browser_agent`。
33
+
34
+ Skills 用 `Subagent (general-purpose):` 来分派,并且要么引用一个提示词模板文件(例如 `superpowers:subagent-driven-development` 的 `./implementer-prompt.md`),要么直接给出内联提示词。在 Gemini CLI 上:
35
+
36
+ | Skill 里的分派形式 | Gemini CLI 等价做法 |
37
+ |------------------|-------------------|
38
+ | 引用某个 `*-prompt.md` 模板(implementer、task-reviewer、code-reviewer 等) | 把模板填好,然后以 `agent_name: "generalist"` 和填好的提示词调用 `invoke_agent` |
39
+ | 引用 `superpowers:requesting-code-review` 的 `./code-reviewer.md` | 以 `agent_name: "generalist"` 和填好的审查模板调用 `invoke_agent` |
40
+ | 内联提示词(没有引用模板) | 以 `agent_name: "generalist"` 和你的内联提示词调用 `invoke_agent` |
41
+
42
+ ### 填写提示词
43
+
44
+ Skills 提供的提示词模板里有 `{WHAT_WAS_IMPLEMENTED}` 或 `[FULL TEXT of task]` 这类占位符。把所有占位符都填好,再把完整提示词交给 `invoke_agent`。模板本身就包含了该 agent 的角色、审查标准和期望的输出格式——子智能体会照着它执行。
45
+
46
+ ### 并行分派
47
+
48
+ Gemini CLI 支持并行分派子智能体。在同一条响应里发出多个 `invoke_agent` 调用(或在一个提示词里写多个 `@generalist` 调用),即可让相互独立的子智能体工作并行跑。有依赖关系的任务保持串行,但**不要**为了让历史记录简单一点就把相互独立的子智能体任务串起来。
22
49
 
23
50
  ## Gemini CLI 额外工具
24
51
 
25
- 以下工具在 Gemini CLI 中可用,但 Claude Code 中没有对应工具:
52
+ 以下工具是 Gemini CLI 独有的:
26
53
 
27
54
  | 工具 | 用途 |
28
55
  |------|------|
29
- | `list_directory` | 列出文件和子目录 |
30
- | `save_memory` | 将信息持久化到 GEMINI.md,跨会话保留 |
31
- | `ask_user` | 向用户请求结构化输入 |
32
- | `tracker_create_task` | 丰富的任务管理(创建、更新、列表、可视化) |
33
- | `enter_plan_mode` / `exit_plan_mode` | 切换到只读研究模式,在修改前先调研 |
56
+ | `save_memory`(旧版) | `experimental.memoryV2 = false` 时,跨会话持久化事实 |
57
+ | `get_internal_docs` | 查阅 Gemini CLI 自带的文档 |
58
+ | `ask_user` | 向用户提出结构化问题(文本 / 单选 / 多选) |
59
+ | `enter_plan_mode` / `exit_plan_mode` | 进入和退出只读的计划模式 |
60
+ | `update_topic` | 更新当前会话的主题 / 战略意图元数据 |
61
+ | `complete_task` | 表示某个 Gemini 子智能体已完成,并把结果返回给父 agent |
62
+ | `tracker_create_task`、`tracker_update_task`、`tracker_get_task`、`tracker_list_tasks`、`tracker_add_dependency`、`tracker_visualize` | 功能完整的任务跟踪器,支持依赖关系与可视化 |
63
+ | `read_mcp_resource`、`list_mcp_resources` | 访问 MCP 资源 |
@@ -12,8 +12,6 @@ metadata:
12
12
 
13
13
  ## 概述
14
14
 
15
- 在没有验证的情况下宣称工作完成,这不是高效,而是不诚实。
16
-
17
15
  **核心原则:** 始终用证据支撑结论。
18
16
 
19
17
  **对这条规则敷衍了事,就等于违背了它的精神。**
@@ -110,15 +108,6 @@ metadata:
110
108
  ❌ 信任代理报告
111
109
  ```
112
110
 
113
- ## 为什么这很重要
114
-
115
- 来自 24 次失败记录:
116
- - 搭档说"我不信你"——信任被破坏
117
- - 未定义的函数被交付——会直接崩溃
118
- - 遗漏需求被交付——功能不完整
119
- - 虚假完成浪费的时间 → 返工 → 重做
120
- - 违反原则:"诚实是核心价值。如果你说谎,就会被替换。"
121
-
122
111
  ## 何时使用
123
112
 
124
113
  **以下情况之前必须使用:**
@@ -135,10 +124,3 @@ metadata:
135
124
  - 暗示成功
136
125
  - 任何传达完成/正确性的沟通
137
126
 
138
- ## 底线
139
-
140
- **验证没有捷径。**
141
-
142
- 运行命令。阅读输出。然后才能宣称结果。
143
-
144
- 这没有商量余地。
@@ -118,12 +118,6 @@ git commit -m "feat: add specific feature"
118
118
  - 只描述做什么而不展示怎么做的步骤(代码步骤必须有代码块)
119
119
  - 引用了未在任何任务中定义的类型、函数或方法
120
120
 
121
- ## 注意事项
122
- - 始终使用精确的文件路径
123
- - 每个步骤都包含完整代码——如果步骤涉及代码变更,就展示代码
124
- - 精确的命令和预期输出
125
- - DRY、YAGNI、TDD、频繁 commit
126
-
127
121
  ## 自检
128
122
 
129
123
  编写完整计划后,以全新视角审视规格并对照检查计划。这是你自己执行的检查清单——不是子代理调度。
@@ -648,12 +648,3 @@ helper1、helper2、step3、pattern4
648
648
 
649
649
  **为此流程优化** - 把可搜索的术语放在前面和各处。
650
650
 
651
- ## 总结
652
-
653
- **创建技能就是流程文档的 TDD。**
654
-
655
- 同样的铁律:没有失败的测试就不写技能。
656
- 同样的循环:红(基线)→ 绿(写技能)→ 重构(堵漏洞)。
657
- 同样的好处:更高的质量、更少的意外、无懈可击的结果。
658
-
659
- 如果你对代码遵循 TDD,对技能也应如此。这是同样的纪律应用于文档。
@@ -1,299 +0,0 @@
1
- # 测试反模式
2
-
3
- **在以下情况加载此参考:** 编写或修改测试、添加 mock、或想在生产代码中添加仅测试用方法时。
4
-
5
- ## 概述
6
-
7
- 测试必须验证真实行为,而非 mock 行为。Mock 是隔离的手段,不是被测试的对象。
8
-
9
- **核心原则:** 测试代码做了什么,而非 mock 做了什么。
10
-
11
- **严格遵循 TDD 可以防止这些反模式。**
12
-
13
- ## 铁律
14
-
15
- ```
16
- 1. 绝不测试 mock 行为
17
- 2. 绝不在生产类中添加仅测试用的方法
18
- 3. 绝不在不理解依赖的情况下使用 mock
19
- ```
20
-
21
- ## 反模式 1:测试 Mock 行为
22
-
23
- **违规做法:**
24
- ```typescript
25
- // ❌ 差:测试 mock 是否存在
26
- test('renders sidebar', () => {
27
- render(<Page />);
28
- expect(screen.getByTestId('sidebar-mock')).toBeInTheDocument();
29
- });
30
- ```
31
-
32
- **为什么这是错误的:**
33
- - 你在验证 mock 能工作,而非组件能工作
34
- - mock 存在时测试通过,不存在时失败
35
- - 对真实行为一无所知
36
-
37
- **你的人类伙伴的纠正:** "我们是在测试 mock 的行为吗?"
38
-
39
- **正确做法:**
40
- ```typescript
41
- // ✅ 好:测试真实组件或不要 mock 它
42
- test('renders sidebar', () => {
43
- render(<Page />); // 不要 mock sidebar
44
- expect(screen.getByRole('navigation')).toBeInTheDocument();
45
- });
46
-
47
- // 或者如果必须 mock sidebar 来隔离:
48
- // 不要对 mock 做断言——测试 Page 在 sidebar 存在时的行为
49
- ```
50
-
51
- ### 门控函数
52
-
53
- ```
54
- 在对任何 mock 元素做断言之前:
55
- 问:"我是在测试真实组件行为还是仅仅测试 mock 的存在?"
56
-
57
- 如果是测试 mock 的存在:
58
- 停下——删除断言或取消 mock
59
-
60
- 改为测试真实行为
61
- ```
62
-
63
- ## 反模式 2:在生产代码中添加仅测试用方法
64
-
65
- **违规做法:**
66
- ```typescript
67
- // ❌ 差:destroy() 仅在测试中使用
68
- class Session {
69
- async destroy() { // 看起来像生产 API!
70
- await this._workspaceManager?.destroyWorkspace(this.id);
71
- // ... 清理
72
- }
73
- }
74
-
75
- // 在测试中
76
- afterEach(() => session.destroy());
77
- ```
78
-
79
- **为什么这是错误的:**
80
- - 生产类被仅测试用的代码污染
81
- - 如果在生产环境中意外调用会很危险
82
- - 违反 YAGNI 和关注点分离
83
- - 混淆了对象生命周期和实体生命周期
84
-
85
- **正确做法:**
86
- ```typescript
87
- // ✅ 好:测试工具处理测试清理
88
- // Session 没有 destroy()——它在生产中是无状态的
89
-
90
- // 在 test-utils/ 中
91
- export async function cleanupSession(session: Session) {
92
- const workspace = session.getWorkspaceInfo();
93
- if (workspace) {
94
- await workspaceManager.destroyWorkspace(workspace.id);
95
- }
96
- }
97
-
98
- // 在测试中
99
- afterEach(() => cleanupSession(session));
100
- ```
101
-
102
- ### 门控函数
103
-
104
- ```
105
- 在向生产类添加任何方法之前:
106
- 问:"这只被测试使用吗?"
107
-
108
- 如果是:
109
- 停下——不要添加
110
- 放到测试工具中
111
-
112
- 问:"这个类是否拥有此资源的生命周期?"
113
-
114
- 如果否:
115
- 停下——这个方法不属于这个类
116
- ```
117
-
118
- ## 反模式 3:不理解依赖就使用 Mock
119
-
120
- **违规做法:**
121
- ```typescript
122
- // ❌ 差:Mock 破坏了测试逻辑
123
- test('detects duplicate server', () => {
124
- // Mock 阻止了测试依赖的配置写入!
125
- vi.mock('ToolCatalog', () => ({
126
- discoverAndCacheTools: vi.fn().mockResolvedValue(undefined)
127
- }));
128
-
129
- await addServer(config);
130
- await addServer(config); // 应该抛异常——但不会!
131
- });
132
- ```
133
-
134
- **为什么这是错误的:**
135
- - 被 mock 的方法有测试依赖的副作用(写入配置)
136
- - "保险起见"过度 mock 破坏了实际行为
137
- - 测试因错误的原因通过或莫名其妙地失败
138
-
139
- **正确做法:**
140
- ```typescript
141
- // ✅ 好:在正确的层级 mock
142
- test('detects duplicate server', () => {
143
- // Mock 慢的部分,保留测试需要的行为
144
- vi.mock('MCPServerManager'); // 只 mock 慢的服务器启动
145
-
146
- await addServer(config); // 配置被写入
147
- await addServer(config); // 检测到重复 ✓
148
- });
149
- ```
150
-
151
- ### 门控函数
152
-
153
- ```
154
- 在 mock 任何方法之前:
155
- 停下——先不要 mock
156
-
157
- 1. 问:"真实方法有什么副作用?"
158
- 2. 问:"这个测试是否依赖这些副作用?"
159
- 3. 问:"我完全理解这个测试需要什么吗?"
160
-
161
- 如果依赖副作用:
162
- 在更底层 mock(实际的慢操作/外部操作)
163
- 或使用保留必要行为的测试替身
164
- 而非测试依赖的高层方法
165
-
166
- 如果不确定测试依赖什么:
167
- 先用真实实现运行测试
168
- 观察实际需要发生什么
169
- 然后在正确的层级添加最少的 mock
170
-
171
- 危险信号:
172
- - "我 mock 一下保险"
173
- - "这可能慢,还是 mock 掉吧"
174
- - 不理解依赖链就 mock
175
- ```
176
-
177
- ## 反模式 4:不完整的 Mock
178
-
179
- **违规做法:**
180
- ```typescript
181
- // ❌ 差:部分 mock——只包含你认为需要的字段
182
- const mockResponse = {
183
- status: 'success',
184
- data: { userId: '123', name: 'Alice' }
185
- // 缺失:下游代码使用的 metadata
186
- };
187
-
188
- // 之后:代码访问 response.metadata.requestId 时崩溃
189
- ```
190
-
191
- **为什么这是错误的:**
192
- - **部分 mock 隐藏了结构假设** — 你只 mock 了你知道的字段
193
- - **下游代码可能依赖你没包含的字段** — 静默失败
194
- - **测试通过但集成失败** — mock 不完整,真实 API 完整
195
- - **虚假的信心** — 测试对真实行为什么也没证明
196
-
197
- **铁律:** Mock 真实存在的完整数据结构,而非只包含你当前测试用到的字段。
198
-
199
- **正确做法:**
200
- ```typescript
201
- // ✅ 好:镜像真实 API 的完整性
202
- const mockResponse = {
203
- status: 'success',
204
- data: { userId: '123', name: 'Alice' },
205
- metadata: { requestId: 'req-789', timestamp: 1234567890 }
206
- // 真实 API 返回的所有字段
207
- };
208
- ```
209
-
210
- ### 门控函数
211
-
212
- ```
213
- 在创建 mock 响应之前:
214
- 检查:"真实 API 响应包含哪些字段?"
215
-
216
- 操作:
217
- 1. 从文档/示例中查看实际 API 响应
218
- 2. 包含系统下游可能消费的所有字段
219
- 3. 验证 mock 完全匹配真实响应的结构
220
-
221
- 关键:
222
- 如果你在创建 mock,你必须理解完整的结构
223
- 部分 mock 在代码依赖遗漏字段时会静默失败
224
-
225
- 不确定时:包含所有文档记录的字段
226
- ```
227
-
228
- ## 反模式 5:集成测试作为事后补充
229
-
230
- **违规做法:**
231
- ```
232
- ✅ 实现完成
233
- ❌ 没写测试
234
- "准备好测试了"
235
- ```
236
-
237
- **为什么这是错误的:**
238
- - 测试是实现的一部分,不是可选的后续
239
- - TDD 本可以防止这种情况
240
- - 没有测试就不能声称完成
241
-
242
- **正确做法:**
243
- ```
244
- TDD 循环:
245
- 1. 编写失败的测试
246
- 2. 实现使其通过
247
- 3. 重构
248
- 4. 然后才声称完成
249
- ```
250
-
251
- ## 当 Mock 变得过于复杂时
252
-
253
- **警告信号:**
254
- - Mock 的 setup 比测试逻辑还长
255
- - 为了让测试通过而 mock 一切
256
- - Mock 缺少真实组件拥有的方法
257
- - Mock 变更时测试就坏了
258
-
259
- **你的人类伙伴的问题:** "我们这里真的需要用 mock 吗?"
260
-
261
- **考虑:** 使用真实组件的集成测试往往比复杂的 mock 更简单
262
-
263
- ## TDD 如何防止这些反模式
264
-
265
- **TDD 有帮助的原因:**
266
- 1. **先写测试** → 迫使你思考你到底在测什么
267
- 2. **看它失败** → 确认测试测的是真实行为,不是 mock
268
- 3. **最少实现** → 仅测试用方法不会混入
269
- 4. **真实依赖** → 你在 mock 之前看到测试实际需要什么
270
-
271
- **如果你在测试 mock 行为,你违反了 TDD** — 你在没有先用真实代码让测试失败的情况下就加了 mock。
272
-
273
- ## 快速参考
274
-
275
- | 反模式 | 修复方式 |
276
- |--------|----------|
277
- | 对 mock 元素做断言 | 测试真实组件或取消 mock |
278
- | 生产代码中的仅测试用方法 | 移到测试工具中 |
279
- | 不理解就 mock | 先理解依赖,最少 mock |
280
- | 不完整的 mock | 完整镜像真实 API |
281
- | 测试作为事后补充 | TDD——先写测试 |
282
- | 过于复杂的 mock | 考虑集成测试 |
283
-
284
- ## 危险信号
285
-
286
- - 断言检查 `*-mock` test ID
287
- - 方法仅在测试文件中被调用
288
- - Mock setup 占测试的 >50%
289
- - 移除 mock 测试就失败
290
- - 无法解释为什么需要 mock
291
- - "保险起见" mock 掉
292
-
293
- ## 底线
294
-
295
- **Mock 是隔离的工具,不是被测试的对象。**
296
-
297
- 如果 TDD 揭示你在测试 mock 行为,你已经走偏了。
298
-
299
- 修复方法:测试真实行为,或质疑为什么要 mock。