@wenaixi/dsh-superpower 6.3.1 → 7.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/README.md +30 -24
- package/lib/superpowers.d.ts +3 -2
- package/lib/superpowers.d.ts.map +1 -1
- package/lib/superpowers.js +6 -3
- package/lib/superpowers.js.map +1 -1
- package/package.json +4 -4
- package/skills/{superpower-brainstorming → brainstorming}/SKILL.md +51 -35
- package/skills/{superpower-brainstorming → brainstorming}/spec-document-reviewer-prompt.md +3 -3
- package/skills/{superpower-brainstorming → brainstorming}/visual-companion.md +6 -6
- package/skills/diagnosing-superpowers/SKILL.md +58 -0
- package/skills/diagnosing-superpowers/prompts/analyst-common.md +24 -0
- package/skills/diagnosing-superpowers/prompts/cost-and-time.md +12 -0
- package/skills/diagnosing-superpowers/prompts/plan-adherence.md +15 -0
- package/skills/diagnosing-superpowers/prompts/quality-evidence.md +11 -0
- package/skills/diagnosing-superpowers/prompts/repeated-work.md +19 -0
- package/skills/diagnosing-superpowers/prompts/request-conflicts.md +11 -0
- package/skills/diagnosing-superpowers/prompts/scrub-audit.md +20 -0
- package/skills/diagnosing-superpowers/prompts/scrub.md +16 -0
- package/skills/diagnosing-superpowers/prompts/similar-session.md +30 -0
- package/skills/diagnosing-superpowers/prompts/skill-timeline.md +16 -0
- package/skills/diagnosing-superpowers/prompts/stumbles.md +16 -0
- package/skills/diagnosing-superpowers/references/context-safety.md +14 -0
- package/skills/diagnosing-superpowers/references/github-issues.md +39 -0
- package/skills/diagnosing-superpowers/references/redaction-policy.md +22 -0
- package/skills/diagnosing-superpowers/references/session-discovery.md +20 -0
- package/skills/diagnosing-superpowers/templates/bundle-README.md +51 -0
- package/skills/diagnosing-superpowers/templates/case.md +57 -0
- package/skills/diagnosing-superpowers/templates/issue.md +45 -0
- package/skills/diagnosing-superpowers/templates/report.md +76 -0
- package/skills/{superpower-dispatching-parallel-agents → dispatching-parallel-agents}/SKILL.md +30 -30
- package/skills/executing-plans/SKILL.md +227 -0
- package/skills/executing-plans/scripts/task-done +52 -0
- package/skills/executing-plans/scripts/task-start +28 -0
- package/skills/{superpower-finishing-a-development-branch → finishing-a-development-branch}/SKILL.md +14 -14
- package/skills/{superpower-receiving-code-review → receiving-code-review}/SKILL.md +39 -39
- package/skills/{superpower-requesting-code-review → requesting-code-review}/SKILL.md +11 -11
- package/skills/{superpower-requesting-code-review → requesting-code-review}/code-reviewer.md +14 -6
- package/skills/subagent-driven-development/SKILL.md +355 -0
- package/skills/{superpower-subagent-driven-development → subagent-driven-development}/implementer-prompt.md +10 -10
- package/skills/subagent-driven-development/re-review-prompt.md +83 -0
- package/skills/{superpower-subagent-driven-development → subagent-driven-development}/scripts/review-package +8 -1
- package/skills/subagent-driven-development/scripts/sdd-workspace +82 -0
- package/skills/{superpower-subagent-driven-development → subagent-driven-development}/scripts/task-brief +3 -1
- package/skills/{superpower-subagent-driven-development → subagent-driven-development}/task-reviewer-prompt.md +27 -27
- package/skills/{superpower-systematic-debugging → systematic-debugging}/CREATION-LOG.md +7 -7
- package/skills/{superpower-systematic-debugging → systematic-debugging}/SKILL.md +7 -7
- package/skills/{superpower-systematic-debugging → systematic-debugging}/condition-based-waiting.md +8 -8
- package/skills/{superpower-systematic-debugging → systematic-debugging}/find-polluter.sh +4 -4
- package/skills/{superpower-systematic-debugging → systematic-debugging}/root-cause-tracing.md +1 -1
- package/skills/{superpower-systematic-debugging → systematic-debugging}/test-pressure-1.md +1 -1
- package/skills/{superpower-test-driven-development → test-driven-development}/SKILL.md +16 -14
- package/skills/{superpower-test-driven-development → test-driven-development}/writing-good-tests.md +28 -28
- package/skills/{superpower-using-git-worktrees → using-git-worktrees}/SKILL.md +12 -12
- package/skills/{superpower-using-superpowers → using-superpowers}/SKILL.md +8 -6
- package/skills/using-superpowers/references/claude-code-tools.md +11 -0
- package/skills/{superpower-using-superpowers → using-superpowers}/references/codex-tools.md +2 -2
- package/skills/{superpower-using-superpowers → using-superpowers}/references/dsh-tools.md +5 -5
- package/skills/{superpower-using-superpowers → using-superpowers}/references/gemini-tools.md +2 -2
- package/skills/{superpower-using-superpowers → using-superpowers}/references/hermes-tools.md +2 -2
- package/skills/using-superpowers/references/muse-tools.md +35 -0
- package/skills/{superpower-verification-before-completion → verification-before-completion}/SKILL.md +17 -17
- package/skills/writing-plans/SKILL.md +167 -0
- package/skills/{superpower-writing-skills → writing-skills}/SKILL.md +73 -71
- package/skills/{superpower-writing-skills → writing-skills}/anthropic-best-practices.md +2 -2
- package/skills/{superpower-writing-skills → writing-skills}/examples/CLAUDE_MD_TESTING.md +4 -4
- package/skills/{superpower-writing-skills → writing-skills}/persuasion-principles.md +10 -10
- package/skills/{superpower-writing-skills → writing-skills}/testing-skills-with-subagents.md +52 -52
- package/skills/superpower-executing-plans/SKILL.md +0 -64
- package/skills/superpower-subagent-driven-development/SKILL.md +0 -347
- package/skills/superpower-subagent-driven-development/re-review-prompt.md +0 -83
- package/skills/superpower-subagent-driven-development/scripts/sdd-workspace +0 -40
- package/skills/superpower-writing-plans/SKILL.md +0 -160
- package/skills/superpower-writing-plans/plan-document-reviewer-prompt.md +0 -49
- /package/skills/{superpower-brainstorming → brainstorming}/scripts/frame-template.html +0 -0
- /package/skills/{superpower-brainstorming → brainstorming}/scripts/helper.js +0 -0
- /package/skills/{superpower-brainstorming → brainstorming}/scripts/server.cjs +0 -0
- /package/skills/{superpower-brainstorming → brainstorming}/scripts/start-server.sh +0 -0
- /package/skills/{superpower-brainstorming → brainstorming}/scripts/stop-server.sh +0 -0
- /package/skills/{superpower-systematic-debugging → systematic-debugging}/condition-based-waiting-example.ts +0 -0
- /package/skills/{superpower-systematic-debugging → systematic-debugging}/defense-in-depth.md +0 -0
- /package/skills/{superpower-systematic-debugging → systematic-debugging}/test-academic.md +0 -0
- /package/skills/{superpower-systematic-debugging → systematic-debugging}/test-pressure-2.md +0 -0
- /package/skills/{superpower-systematic-debugging → systematic-debugging}/test-pressure-3.md +0 -0
- /package/skills/{superpower-using-superpowers → using-superpowers}/references/antigravity-tools.md +0 -0
- /package/skills/{superpower-using-superpowers → using-superpowers}/references/pi-tools.md +0 -0
- /package/skills/{superpower-writing-skills → writing-skills}/graphviz-conventions.dot +0 -0
- /package/skills/{superpower-writing-skills → writing-skills}/render-graphs.js +0 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Resolve and ensure the working-tree directory SDD uses for one plan's
|
|
3
|
+
# short-lived artifacts: task briefs, implementer reports, review packages,
|
|
4
|
+
# and the progress ledger. Print the plan directory's absolute path.
|
|
5
|
+
#
|
|
6
|
+
# One directory per plan (.superpowers/sdd/<plan-basename>/) so a follow-up
|
|
7
|
+
# plan in the same working tree can never read or overwrite another plan's
|
|
8
|
+
# artifacts. A stale ledger misread as current progress makes controllers
|
|
9
|
+
# skip whole task sequences — plan-scoping removes that failure structurally.
|
|
10
|
+
#
|
|
11
|
+
# Basename slugs collide when two plans share a filename (docs/alpha/plan.md
|
|
12
|
+
# vs docs/beta/plan.md), so each workspace records its owning plan's path in
|
|
13
|
+
# a plan-path marker (repo-relative in-repo, absolute outside). A workspace
|
|
14
|
+
# owned by a different plan is skipped and the slug disambiguated with the
|
|
15
|
+
# plan's parent-directory name, then a counter. A workspace with no marker
|
|
16
|
+
# predates the marker scheme and is adopted for the current plan so in-flight
|
|
17
|
+
# workspaces keep resolving — which means the first collision on such a
|
|
18
|
+
# legacy workspace adopts instead of detecting; acceptable, marker-less
|
|
19
|
+
# workspaces age out as plans finish.
|
|
20
|
+
#
|
|
21
|
+
# The workspace lives in the working tree (not under .git/) because Claude Code
|
|
22
|
+
# treats .git/ as a protected path and denies agent writes there — which blocks
|
|
23
|
+
# an implementer subagent from writing its report file. A self-ignoring
|
|
24
|
+
# .gitignore at .superpowers/sdd/ keeps every plan's workspace out of
|
|
25
|
+
# `git status` and out of accidental commits without modifying any tracked file.
|
|
26
|
+
#
|
|
27
|
+
# Single source of truth for the workspace location, so task-brief and
|
|
28
|
+
# review-package cannot drift to different directories.
|
|
29
|
+
#
|
|
30
|
+
# Usage: sdd-workspace PLAN_FILE
|
|
31
|
+
set -euo pipefail
|
|
32
|
+
|
|
33
|
+
if [ $# -ne 1 ]; then
|
|
34
|
+
echo "usage: sdd-workspace PLAN_FILE" >&2
|
|
35
|
+
exit 2
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
plan=$1
|
|
39
|
+
[ -f "$plan" ] || { echo "no such plan file: $plan" >&2; exit 2; }
|
|
40
|
+
|
|
41
|
+
slug=$(basename "$plan" .md)
|
|
42
|
+
[ -n "$slug" ] && [ "$slug" != "." ] && [ "$slug" != ".." ] \
|
|
43
|
+
|| { echo "cannot derive a workspace name from: $plan" >&2; exit 2; }
|
|
44
|
+
|
|
45
|
+
root=$(git rev-parse --show-toplevel)
|
|
46
|
+
base="$root/.superpowers/sdd"
|
|
47
|
+
|
|
48
|
+
# Normalize the plan path (physical directory, so relative/absolute/../
|
|
49
|
+
# spellings of one plan compare equal) and express it as the marker value:
|
|
50
|
+
# repo-relative when the plan lives under the repo root, absolute otherwise.
|
|
51
|
+
plan_dir=$(CDPATH= cd -- "$(dirname "$plan")" && pwd -P)
|
|
52
|
+
plan_abs="$plan_dir/$(basename "$plan")"
|
|
53
|
+
case "$plan_abs" in
|
|
54
|
+
"$root"/*) plan_id=${plan_abs#"$root"/} ;;
|
|
55
|
+
*) plan_id=$plan_abs ;;
|
|
56
|
+
esac
|
|
57
|
+
|
|
58
|
+
# True when the workspace at $1 is (or becomes) this plan's: an existing
|
|
59
|
+
# marker must name this plan; a missing marker means a new workspace or a
|
|
60
|
+
# pre-marker legacy one, and either way the plan claims it by writing one.
|
|
61
|
+
owns() {
|
|
62
|
+
if [ -e "$1/plan-path" ]; then
|
|
63
|
+
[ "$(cat "$1/plan-path")" = "$plan_id" ]
|
|
64
|
+
else
|
|
65
|
+
mkdir -p "$1"
|
|
66
|
+
printf '%s\n' "$plan_id" > "$1/plan-path"
|
|
67
|
+
fi
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
dir="$base/$slug"
|
|
71
|
+
if ! owns "$dir"; then
|
|
72
|
+
parent=$(basename "$plan_dir")
|
|
73
|
+
dir="$base/$slug-$parent"
|
|
74
|
+
if ! owns "$dir"; then
|
|
75
|
+
n=2
|
|
76
|
+
while ! owns "$base/$slug-$parent-$n"; do n=$((n + 1)); done
|
|
77
|
+
dir="$base/$slug-$parent-$n"
|
|
78
|
+
fi
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
printf '*\n' > "$base/.gitignore"
|
|
82
|
+
CDPATH= cd -- "$dir" && pwd
|
|
@@ -21,7 +21,9 @@ n=$2
|
|
|
21
21
|
if [ $# -eq 3 ]; then
|
|
22
22
|
out=$3
|
|
23
23
|
else
|
|
24
|
-
|
|
24
|
+
# Invoke via bash rather than direct exec: some extractors (Python zipfile)
|
|
25
|
+
# strip Unix exec bits when unpacking marketplace packages (#2040).
|
|
26
|
+
dir=$("${BASH:-bash}" "$(cd "$(dirname "$0")" && pwd)/sdd-workspace" "$plan")
|
|
25
27
|
out="$dir/task-${n}-brief.md"
|
|
26
28
|
fi
|
|
27
29
|
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 任务 reviewer 提示词模板
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
在派发任务评审 subagent 时使用本模板。reviewer 只读取一次任务的 diff,并返回两项裁决:规格符合度与代码质量。
|
|
4
4
|
|
|
5
5
|
**目的:** 校验单个任务的实现是否完全贴合需求(不多不少),且构建良好(清晰、已测试、易维护)
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
Subagent (general-purpose):
|
|
9
|
-
description: "
|
|
9
|
+
description: "评审任务 N(规格 + 质量)"
|
|
10
10
|
model: [MODEL — 必填:按 SKILL.md 的模型选择规则选择;若省略则静默继承会话中最昂贵的模型]
|
|
11
11
|
prompt: |
|
|
12
12
|
你正在评审单个任务的实现:先判断是否符合需求,再判断是否构建良好。这是一个任务级别的门禁,而非合并评审——所有任务完成后的全分支广度评审会另行进行。
|
|
13
13
|
|
|
14
14
|
## 需求内容
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
阅读 task brief:[BRIEF_FILE]
|
|
17
17
|
|
|
18
18
|
来自规格/设计且约束本任务的全局约束:
|
|
19
19
|
[GLOBAL_CONSTRAINTS]
|
|
@@ -22,7 +22,7 @@ Subagent (general-purpose):
|
|
|
22
22
|
|
|
23
23
|
阅读实现者的报告:[REPORT_FILE]
|
|
24
24
|
|
|
25
|
-
## 待评审的
|
|
25
|
+
## 待评审的 diff
|
|
26
26
|
|
|
27
27
|
**Base:** [BASE_SHA]
|
|
28
28
|
**Head:** [HEAD_SHA]
|
|
@@ -32,21 +32,21 @@ Subagent (general-purpose):
|
|
|
32
32
|
`git diff --stat [BASE_SHA]..[HEAD_SHA]` 和 `git diff [BASE_SHA]..[HEAD_SHA]`。
|
|
33
33
|
不要遍历更广的代码库。仅在你能明确指出具体风险时,才去检查 diff 之外的代码——每个已命名的风险只做一次聚焦检查,并在报告中同时写明风险是什么以及你检查了什么。跨切面变更属于合理的已命名风险:如果 diff 改动了锁顺序、函数或 API 契约、或共享可变状态,检查调用点就是正确的做法。
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
本次评审在当前检出上为只读。不要以任何方式修改 working tree、暂存区、HEAD 或分支状态。
|
|
36
36
|
|
|
37
|
-
##
|
|
37
|
+
## 禁止分发 subagent
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
由你独立完成全部评审。不要衍生 subagent 来分担 diff 的部分评审,也不要为二次意见再派一个 reviewer。本流程已提供了该工作所需的所有评审席位;你衍生的 reviewer 会以全量成本重复其中一个席位,且其裁决不计入结果。如果 diff 过大、单次难以看完,请自行分多遍评审,并在报告中说明。
|
|
40
40
|
|
|
41
41
|
## 不要信任报告
|
|
42
42
|
|
|
43
|
-
将实现者的报告视为未经核实的陈述。它可能不完整、不准确或过于乐观。请以 diff 为准核实其声明。报告中的设计理由同样是陈述:“按 YAGNI
|
|
43
|
+
将实现者的报告视为未经核实的陈述。它可能不完整、不准确或过于乐观。请以 diff 为准核实其声明。报告中的设计理由同样是陈述:“按 YAGNI 保留”、“有意保持简单”或任何其他解释,都是实现者在给自己的工作打分。请按代码本身的优劣来评判——陈述的理由永远不会降低 finding 的严重级别。
|
|
44
44
|
|
|
45
45
|
## 测试
|
|
46
46
|
|
|
47
47
|
实现者已运行测试,并针对当前代码按 TDD 要求报告了结果与证据。不要为核实其报告而重新运行整个测试套件。仅在阅读代码后产生具体疑点、且现有运行结果无法解答时,才运行测试——此时也只运行聚焦的单项测试,绝不要运行包级别全量套件、竞态检测或重复/高频循环。如果认为有必要做重量级验证,请在报告中建议,而不是直接执行。如果当前环境无法执行命令,请写明你会运行哪条测试。
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
实现者报告的测试输出中的警告或其他噪音即为 finding——测试输出应当是干净的。
|
|
50
50
|
|
|
51
51
|
你看不到的证据不代表不存在。如果报告或其中的测试证据看起来被截断,或你找不到其声称的结果,请按其标注的路径重新读取该文件——如果确实缺失或格式错乱,请作为面向控制器的缺口上报。重新运行套件来补全你没读到的内容不叫验证;证据不可读不等于证据无效。
|
|
52
52
|
|
|
@@ -58,9 +58,9 @@ Subagent (general-purpose):
|
|
|
58
58
|
- **多余:** 未被要求的功能、过度设计、不必要的“锦上添花”
|
|
59
59
|
- **误解:** 功能方向正确但实现方式错误,或解决了错误的问题
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
如果 brief 中列出了多个文件且每个文件各有改动(批量派发),请逐文件对照 diff 检查:每个列出的文件都必须有对应的 hunk。brief 中列出但 diff 始终未触及的文件,即为“缺失”finding,无论批次中其余部分看起来多么干净。
|
|
62
62
|
|
|
63
|
-
如果某项需求仅凭本 diff 无法验证(它位于未变更的代码中或跨多个任务),请将其记为
|
|
63
|
+
如果某项需求仅凭本 diff 无法验证(它位于未变更的代码中或跨多个任务),请将其记为 [WARN] 项,而不是扩大检索范围。
|
|
64
64
|
|
|
65
65
|
## 第二部分:代码质量
|
|
66
66
|
|
|
@@ -80,49 +80,49 @@ Subagent (general-purpose):
|
|
|
80
80
|
- 实现是否遵循了计划中的文件结构?
|
|
81
81
|
- 本次变更是否产生了已经很大的新文件,或显著增大了现有文件?(不要对变更前已有的文件体积做评价——只关注本次变更带来的增量。)
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
报告应当指向证据:每条 finding 以及所有本可用一句“是”带过的检查,都需给出 file:line 引用。一份精炼且带行号引用的报告,能让控制器获得所需的一切信息。
|
|
84
84
|
|
|
85
|
-
你的最终消息即为报告本身:直接以规格符合度裁决开头。每一行都应是裁决、带 file:line
|
|
85
|
+
你的最终消息即为报告本身:直接以规格符合度裁决开头。每一行都应是裁决、带 file:line 的 finding、或你已执行的检查——不要写前言、过程叙述或收尾总结。
|
|
86
86
|
|
|
87
87
|
## 评级校准
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
按实际严重程度对 finding 分级。并非所有问题都是 Critical。
|
|
90
|
+
Important 表示该任务在修复前不可信:错误或脆弱的行为、遗漏的需求、或足以阻断合并的可维护性损伤——例如逻辑块的逐字重复、被吞掉的错误、断言空洞的测试。“覆盖可以更广”和打磨类建议属于 Minor。
|
|
91
|
+
如果计划或 brief 明确要求了按本标准应判为缺陷的内容(例如断言空洞的测试、逻辑块的逐字重复),这依然算 finding——请按 Important 级别上报,并标注为 plan-mandated。计划的作者身份不为其自身打分;最终由人来定夺。
|
|
92
92
|
在列出问题前,先肯定做得好的地方——准确的表扬有助于实现者信任后续的反馈。
|
|
93
93
|
|
|
94
94
|
## 输出格式
|
|
95
95
|
|
|
96
96
|
### 规格符合度
|
|
97
97
|
|
|
98
|
-
-
|
|
99
|
-
-
|
|
98
|
+
- [OK] 符合规格 | [FAIL] 发现问题:[缺失/多余/误解的内容,并附 file:line 引用]
|
|
99
|
+
- [WARN] 无法仅凭 diff 验证:[仅凭 diff 无法验证的需求,以及控制器应如何检查——需与上述 [OK]/[FAIL] 裁决一并报告,针对已可验证的部分给出结论]
|
|
100
100
|
|
|
101
101
|
### 优点
|
|
102
102
|
[做得好的地方?请具体说明。]
|
|
103
103
|
|
|
104
104
|
### 问题
|
|
105
105
|
|
|
106
|
-
####
|
|
107
|
-
####
|
|
108
|
-
####
|
|
106
|
+
#### Critical(必须修复)
|
|
107
|
+
#### Important(建议修复)
|
|
108
|
+
#### Minor(可选优化)
|
|
109
109
|
|
|
110
110
|
每个问题需包含:file:line、问题是什么、为什么重要、如何修复(若不明显)。
|
|
111
111
|
|
|
112
112
|
### 评估
|
|
113
113
|
|
|
114
|
-
**任务质量:** [
|
|
114
|
+
**任务质量:** [Approved | Needs fixes]
|
|
115
115
|
|
|
116
116
|
**理由:** [1-2 句技术性评估]
|
|
117
117
|
```
|
|
118
118
|
|
|
119
119
|
**占位符说明:**
|
|
120
|
-
- `[MODEL]` —
|
|
121
|
-
- `[BRIEF_FILE]` —
|
|
120
|
+
- `[MODEL]` — 必填:reviewer 模型,按 SKILL.md 的模型选择规则选择
|
|
121
|
+
- `[BRIEF_FILE]` — 必填:task brief 文件(执行 `bash scripts/task-brief PLAN N` 可打印路径;与实现者所依据的文件为同一份)
|
|
122
122
|
- `[GLOBAL_CONSTRAINTS]` — 原样抄录计划中 Global Constraints 小节或规格中的约束性需求:精确的取值、格式以及组件之间的既定关系(不含流程类规则——那些已包含在本模板中)
|
|
123
123
|
- `[REPORT_FILE]` — 必填:实现者写入详细报告的文件
|
|
124
124
|
- `[BASE_SHA]` — 任务开始前的提交
|
|
125
125
|
- `[HEAD_SHA]` — 当前提交
|
|
126
|
-
- `[DIFF_FILE]` —
|
|
126
|
+
- `[DIFF_FILE]` — 必填:控制器写入review package的路径(执行 `bash scripts/review-package PLAN_FILE BASE HEAD` 会打印其写入的唯一路径;该包不会进入控制器的上下文)
|
|
127
127
|
|
|
128
|
-
|
|
128
|
+
**reviewer 返回:** 规格符合度裁决([OK]/[FAIL]/[WARN])、优点、问题(Critical/Important/Minor)、任务质量裁决
|
|
@@ -89,13 +89,13 @@
|
|
|
89
89
|
## 最终成果
|
|
90
90
|
|
|
91
91
|
具备以下能力的加固技能:
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
-
|
|
92
|
+
- [OK] 明确要求开展根因调查
|
|
93
|
+
- [OK] 抵御时间压力下的合理化
|
|
94
|
+
- [OK] 为每个阶段提供具体步骤
|
|
95
|
+
- [OK] 显式展示反模式
|
|
96
|
+
- [OK] 在多种压力场景下完成测试
|
|
97
|
+
- [OK] 澄清与 TDD 的关系
|
|
98
|
+
- [OK] 可直接投入使用
|
|
99
99
|
|
|
100
100
|
## 关键洞察
|
|
101
101
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: "
|
|
2
|
+
name: systematic-debugging
|
|
3
|
+
description: "Superpower Skill(最高优先级):遇到缺陷、测试失败或异常行为时使用,要求先完成根因分析再提出修复,确保系统化调试。"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# 系统化调试
|
|
@@ -103,7 +103,7 @@ description: "遇到缺陷、测试失败或异常行为时使用,要求先完
|
|
|
103
103
|
codesign --sign "$IDENTITY" --verbose=4 "$APP"
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
-
**由此可得:** 哪一层失败(secrets → workflow
|
|
106
|
+
**由此可得:** 哪一层失败(secrets → workflow [OK],workflow → build [FAIL])
|
|
107
107
|
|
|
108
108
|
5. **追踪数据流**
|
|
109
109
|
|
|
@@ -174,7 +174,7 @@ description: "遇到缺陷、测试失败或异常行为时使用,要求先完
|
|
|
174
174
|
- 如有测试框架则编写自动化测试
|
|
175
175
|
- 若无框架则编写一次性复现脚本
|
|
176
176
|
- 修复前必须具备该用例
|
|
177
|
-
- 编写规范的失败测试请使用 `
|
|
177
|
+
- 编写规范的失败测试请使用 `test-driven-development` 技能
|
|
178
178
|
|
|
179
179
|
2. **实施单一修复**
|
|
180
180
|
- 针对已确认的根因
|
|
@@ -186,7 +186,7 @@ description: "遇到缺陷、测试失败或异常行为时使用,要求先完
|
|
|
186
186
|
- 用例现在通过了吗?
|
|
187
187
|
- 是否破坏了其他测试?
|
|
188
188
|
- 问题是否真正解决?
|
|
189
|
-
- 在宣称成功前,请使用 `
|
|
189
|
+
- 在宣称成功前,请使用 `verification-before-completion` 技能进行校验
|
|
190
190
|
|
|
191
191
|
4. **若修复未生效**
|
|
192
192
|
- 停下来
|
|
@@ -207,7 +207,7 @@ description: "遇到缺陷、测试失败或异常行为时使用,要求先完
|
|
|
207
207
|
- 是否只是“靠惯性硬撑”?
|
|
208
208
|
- 应该重构架构,还是继续修补表象?
|
|
209
209
|
|
|
210
|
-
|
|
210
|
+
**在尝试更多修复前,先与 human partner 讨论**
|
|
211
211
|
|
|
212
212
|
这不是假设失败——这是架构错误。
|
|
213
213
|
|
|
@@ -230,7 +230,7 @@ description: "遇到缺陷、测试失败或异常行为时使用,要求先完
|
|
|
230
230
|
|
|
231
231
|
**若已失败 3 次以上:** 质疑架构(见阶段四第 5 步)
|
|
232
232
|
|
|
233
|
-
##
|
|
233
|
+
## human partner 提示你做错了的信号
|
|
234
234
|
|
|
235
235
|
**留意这些提醒:**
|
|
236
236
|
- “这不是没生效吗?”——你在未验证的情况下做了假设
|
package/skills/{superpower-systematic-debugging → systematic-debugging}/condition-based-waiting.md
RENAMED
|
@@ -34,12 +34,12 @@ digraph when_to_use {
|
|
|
34
34
|
## 核心模式
|
|
35
35
|
|
|
36
36
|
```typescript
|
|
37
|
-
//
|
|
37
|
+
// [FAIL] 修改前:猜测时机
|
|
38
38
|
await new Promise(r => setTimeout(r, 50));
|
|
39
39
|
const result = getResult();
|
|
40
40
|
expect(result).toBeDefined();
|
|
41
41
|
|
|
42
|
-
//
|
|
42
|
+
// [OK] 修改后:等待条件满足
|
|
43
43
|
await waitFor(() => getResult() !== undefined);
|
|
44
44
|
const result = getResult();
|
|
45
45
|
expect(result).toBeDefined();
|
|
@@ -84,14 +84,14 @@ async function waitFor<T>(
|
|
|
84
84
|
|
|
85
85
|
## 常见错误
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
**[FAIL] 轮询过快:** `setTimeout(check, 1)` - 浪费 CPU
|
|
88
|
+
**[OK] 修正:** 每 10ms 轮询一次
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
**[FAIL] 无超时:** 条件始终不满足时会无限循环
|
|
91
|
+
**[OK] 修正:** 始终设置超时,并给出清晰的错误信息
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
**[FAIL] 数据过期:** 在循环前缓存状态
|
|
94
|
+
**[OK] 修正:** 在循环内调用 getter 获取最新数据
|
|
95
95
|
|
|
96
96
|
## 何时应该使用任意延时
|
|
97
97
|
|
|
@@ -14,7 +14,7 @@ fi
|
|
|
14
14
|
POLLUTION_CHECK="$1"
|
|
15
15
|
TEST_PATTERN="$2"
|
|
16
16
|
|
|
17
|
-
echo "
|
|
17
|
+
echo "[INFO] Searching for test that creates: $POLLUTION_CHECK"
|
|
18
18
|
echo "Test pattern: $TEST_PATTERN"
|
|
19
19
|
echo ""
|
|
20
20
|
|
|
@@ -40,7 +40,7 @@ for TEST_FILE in $TEST_FILES; do
|
|
|
40
40
|
|
|
41
41
|
# Skip if pollution already exists
|
|
42
42
|
if [ -e "$POLLUTION_CHECK" ]; then
|
|
43
|
-
echo "
|
|
43
|
+
echo "[WARN] Pollution already exists before test $COUNT/$TOTAL"
|
|
44
44
|
echo " Skipping: $TEST_FILE"
|
|
45
45
|
continue
|
|
46
46
|
fi
|
|
@@ -53,7 +53,7 @@ for TEST_FILE in $TEST_FILES; do
|
|
|
53
53
|
# Check if pollution appeared
|
|
54
54
|
if [ -e "$POLLUTION_CHECK" ]; then
|
|
55
55
|
echo ""
|
|
56
|
-
echo "
|
|
56
|
+
echo "[HIT] FOUND POLLUTER!"
|
|
57
57
|
echo " Test: $TEST_FILE"
|
|
58
58
|
echo " Created: $POLLUTION_CHECK"
|
|
59
59
|
echo ""
|
|
@@ -68,5 +68,5 @@ for TEST_FILE in $TEST_FILES; do
|
|
|
68
68
|
done
|
|
69
69
|
|
|
70
70
|
echo ""
|
|
71
|
-
echo "
|
|
71
|
+
echo "[OK] No polluter found - all tests clean!"
|
|
72
72
|
exit 0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: "
|
|
2
|
+
name: test-driven-development
|
|
3
|
+
description: "Superpower Skill(最高优先级):实现新功能或修复缺陷时,编写实现代码前先写测试的测试驱动开发完整指南与流程约束规范。"
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# 测试驱动开发(TDD)
|
|
@@ -21,7 +21,7 @@ description: "实现新功能或修复缺陷时,编写实现代码前先写测
|
|
|
21
21
|
- 重构
|
|
22
22
|
- 行为变更
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
**例外情况(需征得 human partner 同意):**
|
|
25
25
|
- 一次性原型
|
|
26
26
|
- 生成的代码
|
|
27
27
|
- 配置文件
|
|
@@ -46,16 +46,16 @@ NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST
|
|
|
46
46
|
|
|
47
47
|
完全基于测试重新实现,没有例外。
|
|
48
48
|
|
|
49
|
-
##
|
|
49
|
+
## RED-GREEN-REFACTOR(红-绿-重构)
|
|
50
50
|
|
|
51
51
|
```dot
|
|
52
52
|
digraph tdd_cycle {
|
|
53
53
|
rankdir=LR;
|
|
54
|
-
red [label="
|
|
54
|
+
red [label="RED\n编写失败的测试", shape=box, style=filled, fillcolor="#ffcccc"];
|
|
55
55
|
verify_red [label="验证是否\n按预期失败", shape=diamond];
|
|
56
|
-
green [label="
|
|
56
|
+
green [label="GREEN\n最小化实现", shape=box, style=filled, fillcolor="#ccffcc"];
|
|
57
57
|
verify_green [label="验证是否通过\n全部通过", shape=diamond];
|
|
58
|
-
refactor [label="
|
|
58
|
+
refactor [label="REFACTOR\n清理优化", shape=box, style=filled, fillcolor="#ccccff"];
|
|
59
59
|
next [label="下一项", shape=ellipse];
|
|
60
60
|
|
|
61
61
|
red -> verify_red;
|
|
@@ -70,7 +70,7 @@ digraph tdd_cycle {
|
|
|
70
70
|
}
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
###
|
|
73
|
+
### RED - 编写失败的测试
|
|
74
74
|
|
|
75
75
|
写一个最小化的测试,展示应该发生什么。
|
|
76
76
|
|
|
@@ -112,7 +112,7 @@ test('retry works', async () => {
|
|
|
112
112
|
- 命名清晰
|
|
113
113
|
- 使用真实代码(除非不得不 mock)
|
|
114
114
|
|
|
115
|
-
###
|
|
115
|
+
### Verify RED - 观察失败
|
|
116
116
|
|
|
117
117
|
**强制要求,切勿跳过。**
|
|
118
118
|
|
|
@@ -129,7 +129,7 @@ npm test path/to/test.test.ts
|
|
|
129
129
|
|
|
130
130
|
**测试报错了?** 修复错误,直到它以正确的方式失败为止。
|
|
131
131
|
|
|
132
|
-
###
|
|
132
|
+
### GREEN - 最小化实现
|
|
133
133
|
|
|
134
134
|
编写刚好能让测试通过的最简代码。
|
|
135
135
|
|
|
@@ -167,7 +167,7 @@ async function retryOperation<T>(
|
|
|
167
167
|
|
|
168
168
|
不要添加测试未要求的功能,不要顺手重构其他代码,也不要做超出测试范围的“优化”。
|
|
169
169
|
|
|
170
|
-
###
|
|
170
|
+
### Verify GREEN - 观察通过
|
|
171
171
|
|
|
172
172
|
**强制要求。**
|
|
173
173
|
|
|
@@ -184,7 +184,9 @@ npm test path/to/test.test.ts
|
|
|
184
184
|
|
|
185
185
|
**其他测试失败?** 立即修复。
|
|
186
186
|
|
|
187
|
-
|
|
187
|
+
**“其他测试”指项目的整个测试套件,而不只是你的文件。** 你自己写的测试通过,不代表套件变绿。在把改动宣布完成之前,请运行项目的测试命令(裸 `pytest`、`npm test`、`cargo test`——仓库用什么就用什么),即使你的任务只点名了一个测试文件。任务中的范围说明约束的是交付物,不是你的验证。这次运行暴露的任何失败——包括并非由你造成的失败——都要按名称写进你的报告;一个你眼睁睁看着滚过去却没提的红色测试,是一份因遗漏而伪造的报告。
|
|
188
|
+
|
|
189
|
+
### REFACTOR - 清理优化
|
|
188
190
|
|
|
189
191
|
仅在变绿之后:
|
|
190
192
|
- 消除重复
|
|
@@ -301,7 +303,7 @@ PASS
|
|
|
301
303
|
|
|
302
304
|
| 问题 | 解决方案 |
|
|
303
305
|
|---------|----------|
|
|
304
|
-
| 不知道怎么测 | 写出你期望的 API
|
|
306
|
+
| 不知道怎么测 | 写出你期望的 API,先写断言,找 human partner 讨论。 |
|
|
305
307
|
| 测试太复杂 | 设计太复杂,简化接口。 |
|
|
306
308
|
| 必须 mock 所有东西 | 代码耦合过重,使用依赖注入。 |
|
|
307
309
|
| 测试准备工作过于庞大 | 抽取辅助函数,依然复杂?简化设计。 |
|
|
@@ -319,4 +321,4 @@ PASS
|
|
|
319
321
|
否则 → 就不是 TDD
|
|
320
322
|
```
|
|
321
323
|
|
|
322
|
-
|
|
324
|
+
未经 human partner 许可,没有例外。
|
package/skills/{superpower-test-driven-development → test-driven-development}/writing-good-tests.md
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 编写高质量测试
|
|
2
2
|
|
|
3
|
-
**何时加载本文档:** 编写或修改测试、添加
|
|
3
|
+
**何时加载本文档:** 编写或修改测试、添加 mock,或为测试添加清理/辅助方法时。
|
|
4
4
|
|
|
5
5
|
## 概述
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
2. 每个测试都要验证真实对象
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
严格的 TDD 能自然地满足这两点:先写测试并观察其在真实代码上失败,就已经证明了它具备失败能力;只有当真实依赖被证明缓慢或涉及外部系统时,才引入
|
|
14
|
+
严格的 TDD 能自然地满足这两点:先写测试并观察其在真实代码上失败,就已经证明了它具备失败能力;只有当真实依赖被证明缓慢或涉及外部系统时,才引入 mock。
|
|
15
15
|
|
|
16
16
|
## 原则一:明确测试要捕获的缺陷
|
|
17
17
|
|
|
@@ -20,19 +20,19 @@
|
|
|
20
20
|
**独立推导期望值。** 使用字面量和人工校验的固件;表格驱动测试中 `want` 使用字面量是首选形式。由被测代码(或其辅助函数)计算出的期望值,无论代码做什么都能通过:
|
|
21
21
|
|
|
22
22
|
```typescript
|
|
23
|
-
//
|
|
23
|
+
// [FAIL] 镜像断言:同一个构造器算出两侧——永远为真
|
|
24
24
|
const expected = buildSearchQuery({ tag: 'urgent' });
|
|
25
25
|
expect(buildSearchQuery({ tag: 'urgent' })).toBe(expected);
|
|
26
26
|
|
|
27
|
-
//
|
|
27
|
+
// [OK] 手工推导的字面量
|
|
28
28
|
expect(buildSearchQuery({ tag: 'urgent' })).toBe('tag:"urgent"');
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
**不要写变更探测器。**
|
|
31
|
+
**不要写变更探测器。** 如果只有有意决策才能让测试失败——如常量的取值、精确的措辞、内部结构——那么它只会在重新设计时触发,却在真正的缺陷面前保持沉默。应测试依赖于该决策的行为:不要写 `expect(MAX_RETRIES).toBe(5)`,而要验证“失败调用会被重试 5 次,且第 6 次绝不会发生”。
|
|
32
32
|
|
|
33
|
-
**测行为,而非文本。** 断言脚本、技能或配置包含某一行,只能证明源码就是源码本身。应在受控输入下运行脚本,并断言其输出、副作用或退出码。面向
|
|
33
|
+
**测行为,而非文本。** 断言脚本、技能或配置包含某一行,只能证明源码就是源码本身。应在受控输入下运行脚本,并断言其输出、副作用或退出码。面向 agent 的指令性文档,应通过消费方 agent 的行为来测试(writing-skills);面向人的 prose 则完全不需要测试。
|
|
34
34
|
|
|
35
|
-
**测你的代码,而非框架。** 测试你的代码在其边界上做出的契约——你注册的路由、你发出的查询、你生成的负载。上游的实现机制应由其维护者来测试(典型反例:断言你的路由会调用已注册的处理器——那是框架的测试,不是你的)。当上游行为确实出乎意料时,针对该假设写一个窄范围的特征测试(characterization test
|
|
35
|
+
**测你的代码,而非框架。** 测试你的代码在其边界上做出的契约——你注册的路由、你发出的查询、你生成的负载。上游的实现机制应由其维护者来测试(典型反例:断言你的路由会调用已注册的处理器——那是框架的测试,不是你的)。当上游行为确实出乎意料时,针对该假设写一个窄范围的特征测试(characterization test),并命名该假设。同样的边界也适用于你的内部代码:构造函数、getter、常量和简单透传,只有在它们承担校验、归一化、默认值、推导、约束或副作用时才值得测试——否则应断言首个依赖于它们的、消费者可见的结果。
|
|
36
36
|
|
|
37
37
|
### 门禁检查
|
|
38
38
|
|
|
@@ -52,51 +52,51 @@ expect(buildSearchQuery({ tag: 'urgent' })).toBe('tag:"urgent"');
|
|
|
52
52
|
|
|
53
53
|
## 原则二:使用真实对象
|
|
54
54
|
|
|
55
|
-
**
|
|
55
|
+
**mock 本身不值得断言。** 对 mock 的断言,只在 mock 存在时通过、不存在时失败——它对组件本身一无所言。应断言真实组件的行为;如果你发现自己在检查 mock,那就去掉 mock 或删掉该断言。
|
|
56
56
|
|
|
57
57
|
```typescript
|
|
58
|
-
//
|
|
58
|
+
// [OK] 真实行为
|
|
59
59
|
expect(screen.getByRole('navigation')).toBeInTheDocument();
|
|
60
60
|
|
|
61
|
-
//
|
|
61
|
+
// [FAIL] mock 的存在性
|
|
62
62
|
expect(screen.getByTestId('sidebar-mock')).toBeInTheDocument();
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
**你的 human partner 的提醒:**“我们在测试 mock 的行为吗?”
|
|
66
66
|
|
|
67
|
-
**在正确的层级
|
|
67
|
+
**在正确的层级 mock。** 在替换真实方法前,先了解它的所有副作用;只 mock 缓慢或外部的操作,保留测试所依赖的部分为真实实现。不确定时,先让测试跑在真实实现上,观察究竟需要发生什么。
|
|
68
68
|
|
|
69
69
|
```typescript
|
|
70
|
-
//
|
|
70
|
+
// [FAIL] mock 吞掉了重复检测所读取的配置写入
|
|
71
71
|
vi.mock('ToolCatalog', () => ({
|
|
72
72
|
discoverAndCacheTools: vi.fn().mockResolvedValue(undefined)
|
|
73
73
|
}));
|
|
74
74
|
|
|
75
|
-
//
|
|
75
|
+
// [OK] 只 mock 缓慢的服务器启动;配置写入保持真实
|
|
76
76
|
vi.mock('MCPServerManager');
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
**让替身足够具体。** 当参数、调用次数或顺序属于契约的一部分时,就要断言它们——一个接受任意参数的假对象什么也验证不了。为每个分支(成功、失败、畸形输入)提供独立的固件或 spy,这样错误的分支就无法满足期望。
|
|
80
80
|
|
|
81
|
-
**完整镜像真实数据。** 按真实存在的完整结构来
|
|
81
|
+
**完整镜像真实数据。** 按真实存在的完整结构来 mock——包含所有已文档化的字段——而不仅仅是你测试中读取的字段。部分 mock 会在下游代码读取缺失字段时静默失败:测试通过,而集成已损坏。
|
|
82
82
|
|
|
83
83
|
**生产类只承载生产方法。** 仅测试需要的清理逻辑应放在测试工具中,绝不要以 `destroy()` 的形式出现在生产类上。自问:这个方法是否只被测试调用?这个类是否拥有该资源的生命周期?答案有误 → 放到测试工具里。
|
|
84
84
|
|
|
85
|
-
**复杂
|
|
85
|
+
**复杂 mock 不如真实组件。** 当 mock 的搭建超过测试逻辑本身、mock 缺少真实组件拥有的方法、或测试因 mock 变更而崩溃时,改用基于真实组件的集成测试。**你的 human partner 的提问:**“这里真的需要用 mock 吗?”
|
|
86
86
|
|
|
87
87
|
### 门禁检查
|
|
88
88
|
|
|
89
89
|
```
|
|
90
|
-
添加
|
|
90
|
+
添加 mock 或测试辅助方法之前:
|
|
91
91
|
列出真实方法的所有副作用;测试所依赖的保持真实——
|
|
92
|
-
只在更底层的缓慢/外部层级进行
|
|
92
|
+
只在更底层的缓慢/外部层级进行 mock。
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
mock 的响应需完整镜像真实结构。
|
|
95
95
|
|
|
96
96
|
仅被测试调用的方法归属于测试工具,而非生产代码。
|
|
97
97
|
|
|
98
|
-
正要对
|
|
99
|
-
去掉
|
|
98
|
+
正要对 mock 本身做断言?
|
|
99
|
+
去掉 mock 或删掉该断言。
|
|
100
100
|
```
|
|
101
101
|
|
|
102
102
|
## 测试与实现一同交付
|
|
@@ -123,11 +123,11 @@ TDD 循环——失败的测试、最小实现、重构——才是“完成”
|
|
|
123
123
|
| 构造期望值 | 手工推导;绝不要用被测代码来计算 |
|
|
124
124
|
| 测试脚本或文档 | 运行它 / 对其消费者做压力测试;不要 grep 文本 |
|
|
125
125
|
| 想测试依赖 | 测试你的边界契约,而非对方已文档化的实现机制 |
|
|
126
|
-
| 想对
|
|
127
|
-
| 准备
|
|
128
|
-
| 构造
|
|
126
|
+
| 想对 mock 元素做断言 | 测试真实组件,或去掉 mock |
|
|
127
|
+
| 准备 mock 方法 | 了解其副作用;在缓慢/外部层级 mock |
|
|
128
|
+
| 构造 mock 响应 | 完整镜像真实结构 |
|
|
129
129
|
| 需要仅测试使用的清理逻辑 | 放到测试工具中 |
|
|
130
|
-
|
|
|
130
|
+
| mock 搭建急剧膨胀 | 改用基于真实组件的集成测试 |
|
|
131
131
|
| 完成测试文件 | 执行变异检查 |
|
|
132
132
|
|
|
133
133
|
## 警示信号
|
|
@@ -139,7 +139,7 @@ TDD 循环——失败的测试、最小实现、重构——才是“完成”
|
|
|
139
139
|
- 测试 grep 源码文本,或断言已移除的符号保持移除
|
|
140
140
|
- 即使只剩下框架,该测试依然“有意义”
|
|
141
141
|
- 测试仅为覆盖率而存在,未检查任何副作用或结果
|
|
142
|
-
- 断言检查 `*-mock` 测试 ID,或在移除
|
|
142
|
+
- 断言检查 `*-mock` 测试 ID,或在移除 mock 后失败
|
|
143
143
|
- 某个方法只被测试文件调用
|
|
144
|
-
-
|
|
145
|
-
- “为了保险”而
|
|
144
|
+
- mock 搭建超过测试的一半,或你无法解释为何需要 mock
|
|
145
|
+
- “为了保险”而 mock
|