日期: 2025-11-28 状态: 草稿 来源: 两个 Claude 实例在真实开发场景中使用 superpowers
两个 Claude 实例提供了来自实际开发会话的详细反馈。他们的反馈揭示了当前技能中的系统性缺口,这些缺口使得本可预防的 bug 即使在遵循技能的情况下仍然被交付。
关键洞察: 这些是问题报告,而不仅仅是解决方案提议。问题是真实存在的;解决方案需要仔细评估。
关键主题:
- 验证缺口 - 我们验证操作成功,但没有验证它们是否实现了预期结果
- 流程卫生 - 后台进程会累积,并在子代理之间相互干扰
- 上下文优化 - 子代理获得了太多无关信息
- 缺少自我反思 - 在交接前没有提示批判自己的工作
- Mock 安全 - Mock 可能在未被检测到的情况下偏离接口
- 技能激活 - 技能存在,但没有被读取/使用
已识别的问题
Section titled “已识别的问题”问题 1:配置变更验证缺口
Section titled “问题 1:配置变更验证缺口”发生了什么:
- 子代理测试“OpenAI 集成”
- 设置了
OPENAI_API_KEY环境变量 - 收到状态码 200 响应
- 报告“OpenAI 集成正常工作”
- 但是 响应包含
"model": "claude-sonnet-4-20250514"- 实际上正在使用 Anthropic
根本原因:
verification-before-completion 检查操作成功,但没有检查结果是否反映了预期的配置变更。
影响: 高 - 对集成测试产生错误信心,bug 被发布到生产环境
示例失败模式:
- 切换 LLM 提供商 → 验证状态码 200,但不检查模型名称
- 启用功能标志 → 验证没有错误,但不检查功能是否已激活
- 更改环境 → 验证部署成功,但不检查环境变量
问题 2:后台进程累积
Section titled “问题 2:后台进程累积”发生了什么:
- 会话期间分派了多个子代理
- 每个子代理都启动了后台服务器进程
- 进程累积(4+ 个服务器在运行)
- 陈旧进程仍然绑定到端口
- 后续 E2E 测试命中了配置错误的陈旧服务器
- 测试结果令人困惑/不正确
根本原因: 子代理是无状态的 - 不知道先前子代理启动的进程。没有清理协议。
影响: 中高 - 测试命中错误服务器,产生误报/误失败,调试混乱
问题 3:子代理提示中的上下文膨胀
Section titled “问题 3:子代理提示中的上下文膨胀”发生了什么:
- 标准做法:给子代理完整计划文件阅读
- 实验做法:只给任务 + 模式 + 文件 + 验证命令
- 结果:更快、更聚焦,更常见一次尝试完成
根本原因: 子代理在无关的计划章节上浪费 token 和注意力。
影响: 中 - 执行更慢,失败尝试更多
有效做法:
你正在向 packnplay 的测试套件添加一个单独的 E2E 测试。
**你的任务:** 将 `TestE2E_FeaturePrivilegedMode` 添加到 `pkg/runner/e2e_test.go`
**要测试什么:** 一个在其元数据中请求 `"privileged": true`的本地 devcontainer feature 应该导致容器以 `--privileged` 标志运行。
**严格遵循 TestE2E_FeatureOptionValidation 的模式**(在文件末尾)
**编写后运行:** `go test -v ./pkg/runner -run TestE2E_FeaturePrivilegedMode -timeout 5m`问题 4:交接前没有自我反思
Section titled “问题 4:交接前没有自我反思”发生了什么:
- 添加了自我反思提示:“用新鲜的眼光看你的工作 - 有什么可以做得更好?”
- 任务 5 的实现者识别出失败测试是由实现 bug 导致的,而不是测试 bug
- 追踪到第 99 行:
strings.Join(metadata.Entrypoint, " ")创建了无效的 Docker 语法 - 如果没有自我反思,本来只会报告“测试失败”,而没有根本原因
根本原因: 实现者不会自然地退后一步,在报告完成前批判自己的工作。
影响: 中 - 本可由实现者发现的 bug 被交接给审查者
问题 5:Mock-接口漂移
Section titled “问题 5:Mock-接口漂移”发生了什么:
// 接口定义 close()interface PlatformAdapter { close(): Promise<void>;}
// 代码(有 BUG)调用 cleanup()await adapter.cleanup();
// Mock(匹配 BUG)定义 cleanup()vi.mock('web-adapter', () => ({ WebAdapter: vi.fn().mockImplementation(() => ({ cleanup: vi.fn().mockResolvedValue(undefined), // 错误! })),}));- 测试通过
- 运行时崩溃:“adapter.cleanup is not a function”
根本原因: Mock 来源于有 bug 的代码调用内容,而不是接口定义。TypeScript 无法捕获方法名错误的内联 mock。
影响: 高 - 测试给出错误信心,运行时崩溃
为什么 testing-anti-patterns 没有阻止这一点: 该技能涵盖了测试 mock 行为和在不理解的情况下进行 mock,但没有涵盖“从接口派生 mock,而不是从实现派生”的具体模式。
问题 6:代码审查者文件访问
Section titled “问题 6:代码审查者文件访问”发生了什么:
- 分派了代码审查者子代理
- 无法找到测试文件:“该文件似乎不存在于仓库中”
- 文件实际上存在
- 审查者不知道要先显式读取它
根本原因: 审查者提示中没有包含显式的文件读取指令。
影响: 低中 - 审查失败或不完整
问题 7:修复工作流延迟
Section titled “问题 7:修复工作流延迟”发生了什么:
- 实现者在自我反思期间识别出 bug
- 实现者知道修复方法
- 当前工作流:报告 → 我分派修复者 → 修复者修复 → 我验证
- 额外往返增加了延迟,却没有增加价值
根本原因: 当实现者已经诊断出问题时,实现者和修复者角色之间仍然存在僵硬分离。
影响: 低 - 有延迟,但没有正确性问题
问题 8:技能没有被读取
Section titled “问题 8:技能没有被读取”发生了什么:
testing-anti-patterns技能存在- 人类和子代理在编写测试前都没有读取它
- 本可以防止一些问题(虽然不是全部 - 见问题 5)
根本原因: 没有强制要求子代理读取相关技能。没有提示包含技能读取。
影响: 中 - 如果不使用,技能投资就被浪费
1. verification-before-completion:添加配置变更验证
Section titled “1. verification-before-completion:添加配置变更验证”添加新章节:
## 验证配置变更
在测试配置、提供商、功能标志或环境的变更时:
**不要只验证操作成功。要验证输出反映了预期变更。**
### 常见失败模式
操作成功是因为存在*某个*有效配置,但它不是你想要测试的配置。
### 示例
| 变更 | 不充分 | 必需 ||--------|-------------|----------|| 切换 LLM 提供商 | 状态码 200 | 响应包含预期模型名称 || 启用功能标志 | 没有错误 | 功能行为实际处于激活状态 || 更改环境 | 部署成功 | 日志/变量引用新环境 || 设置凭据 | 认证成功 | 已认证用户/上下文正确 |
### 门控函数在声明配置变更有效之前:
- 识别:这次变更后应该有什么不同?
- 定位:在哪里可以观察到该差异?
- 响应字段(模型名称、用户 ID)
- 日志行(环境、提供商)
- 行为(功能激活/未激活)
- 运行:显示该可观察差异的命令
- 验证:输出包含预期差异
- 只有这时:声明配置变更有效
危险信号:
- “请求成功”,但没有检查内容
- 检查状态码但不检查响应体
- 验证没有错误但没有正向确认
**为什么这有效:**强制验证意图,而不仅仅是操作成功。
---
### 2. subagent-driven-development:为 E2E 测试添加进程卫生
**添加新章节:**
```markdown## E2E 测试的进程卫生
当分派会启动服务(服务器、数据库、消息队列)的子代理时:
### 问题
子代理是无状态的 - 它们不知道先前子代理启动的进程。后台进程会持续存在,并可能干扰后续测试。
### 解决方案
**在分派 E2E 测试子代理前,在提示中包含清理:**在启动任何服务之前:
- 杀掉现有进程:pkill -f "
" 2>/dev/null || true - 等待清理:sleep 1
- 验证端口空闲:lsof -i :
&& echo “ERROR: Port still in use” || echo “Port free”
测试完成之后:
- 杀掉你启动的进程
- 验证清理:pgrep -f "
" || echo “Cleanup successful”
### 示例任务:运行 API 服务器的 E2E 测试
提示包含: “在启动服务器之前:
- 杀掉任何现有服务器:pkill -f ‘node.*server.js’ 2>/dev/null || true
- 验证端口 3001 空闲:lsof -i :3001 && exit 1 || echo ‘Port available’
测试后:
- 杀掉你启动的服务器
- 验证:pgrep -f ‘node.*server.js’ || echo ‘Cleanup verified’”
### 为什么这很重要
- 陈旧进程使用错误配置提供请求- 端口冲突导致静默失败- 进程累积拖慢系统- 测试结果令人困惑(命中错误服务器)权衡分析:
- 给提示增加样板内容
- 但能防止非常令人困惑的调试
- 对 E2E 测试子代理来说值得
3. subagent-driven-development:添加精简上下文选项
Section titled “3. subagent-driven-development:添加精简上下文选项”修改步骤 2:用子代理执行任务
之前:
仔细阅读 [plan-file] 中的那个任务。之后:
## 上下文方法
**完整计划(默认):**当任务复杂或有依赖时使用:仔细阅读 [plan-file] 中的任务 N。
**精简上下文(用于独立任务):**当任务是独立且基于模式时使用:你正在实现:[1-2 句话的任务描述]
要修改的文件:[确切路径] 要遵循的模式:[对现有函数/测试的引用] 要实现的内容:[具体要求] 验证:[要运行的确切命令]
[不要包含完整计划文件]
**在以下情况使用精简上下文:**- 任务遵循现有模式(添加类似测试,实现类似功能)- 任务是自包含的(不需要其他任务的上下文)- 模式引用足够(例如,“遵循 TestE2E_FeatureOptionValidation”)
**在以下情况使用完整计划:**- 任务依赖其他任务- 需要理解整体架构- 复杂逻辑需要上下文示例:
精简上下文提示:
"你正在为 devcontainer features 中的 privileged mode 添加测试。
文件:pkg/runner/e2e_test.go模式:遵循 TestE2E_FeatureOptionValidation(在文件末尾)测试:元数据中带有 `"privileged": true` 的 Feature 会产生 `--privileged` 标志验证:go test -v ./pkg/runner -run TestE2E_FeaturePrivilegedMode -timeout 5m
报告:实现、测试结果、任何问题。"为什么这有效: 减少 token 使用,提高专注度,在适用时更快完成。
4. subagent-driven-development:添加自我反思步骤
Section titled “4. subagent-driven-development:添加自我反思步骤”修改步骤 2:用子代理执行任务
添加到提示模板:
完成后,在报告之前:
退后一步,用新鲜的眼光审查你的工作。
问自己:- 这是否真的按规范解决了任务?- 是否有我没有考虑的边界情况?- 我是否正确遵循了模式?- 如果测试失败,根本原因是什么(实现 bug 还是测试 bug)?- 这个实现有什么可以做得更好?
如果你在反思期间识别出问题,现在就修复它们。
然后报告:- 你实现了什么- 自我反思发现(如果有)- 测试结果- 变更的文件为什么这有效: 在交接前捕获实现者自己可以发现的 bug。已有案例记录:通过自我反思识别出 entrypoint bug。
权衡: 每个任务增加约 30 秒,但能在审查前捕获问题。
5. requesting-code-review:添加显式文件读取
Section titled “5. requesting-code-review:添加显式文件读取”修改 code-reviewer 模板:
在开头添加:
## 要审查的文件
在分析之前,读取这些文件:
1. [列出 diff 中变更的具体文件]2. [被变更引用但未修改的文件]
使用 Read 工具加载每个文件。
如果你找不到某个文件:- 检查 diff 中的确切路径- 尝试替代位置- 报告:"Cannot locate [path] - please verify file exists"
在你读取实际代码之前,不要继续审查。为什么这有效: 显式指令防止“文件未找到”问题。
6. testing-anti-patterns:添加 Mock-接口漂移反模式
Section titled “6. testing-anti-patterns:添加 Mock-接口漂移反模式”添加新的反模式 6:
## 反模式 6:从实现派生的 Mock
**违规:**```typescript// 代码(有 BUG)调用 cleanup()await adapter.cleanup();
// Mock(匹配 BUG)有 cleanup()const mock = { cleanup: vi.fn().mockResolvedValue(undefined)};
// 接口(正确)定义 close()interface PlatformAdapter { close(): Promise<void>;}为什么这是错误的:
- Mock 将 bug 编码进测试
- TypeScript 无法捕获方法名错误的内联 mock
- 测试通过,因为代码和 mock 都是错的
- 使用真实对象时运行时崩溃
修复:
// ✅ 好:从接口派生 mock
// 步骤 1:打开接口定义(PlatformAdapter)// 步骤 2:列出其中定义的方法(close、initialize 等)// 步骤 3:精确 mock 这些方法
const mock = { initialize: vi.fn().mockResolvedValue(undefined), close: vi.fn().mockResolvedValue(undefined), // 来自接口!};
// 现在测试会失败,因为代码调用了不存在的 cleanup()// 该失败会在运行时之前暴露 bug在编写任何 mock 之前:
1. 停止 - 先不要查看被测代码 2. 查找:依赖项的接口/类型定义 3. 读取:接口文件 4. 列出:接口中定义的方法 5. MOCK:只 mock 这些方法,并且名称完全一致 6. 不要:查看你的代码调用了什么
如果你的测试因为代码调用了 mock 中不存在的内容而失败: ✅ 好 - 测试发现了代码中的 bug 修复代码,使其调用正确的接口方法 而不是修复 mock
危险信号: - “我会 mock 代码调用的内容” - 从实现中复制方法名 - 没有读取接口就编写 mock - “测试失败了,所以我会把这个方法加到 mock 里”检测:
当你看到运行时错误 “X is not a function” 而测试通过时:
- 检查 X 是否被 mock
- 将 mock 方法与接口方法进行比较
- 查找方法名不匹配
**为什么这有效:**直接解决反馈中的失败模式。
---
### 7. subagent-driven-development:要求测试子代理读取技能
**当任务涉及测试时,添加到提示模板:**
```markdown在编写任何测试之前:
1. 读取 testing-anti-patterns 技能: 使用 Skill 工具:superpowers:testing-anti-patterns
2. 在以下情况应用该技能中的门控函数: - 编写 mock - 向生产类添加方法 - mock 依赖项
这不是可选项。违反反模式的测试会在审查中被拒绝。为什么这有效: 确保技能被实际使用,而不是仅仅存在。
权衡: 为每个任务增加时间,但防止整类 bug。
8. subagent-driven-development:允许实现者修复自我识别的问题
Section titled “8. subagent-driven-development:允许实现者修复自我识别的问题”修改步骤 2:
当前:
子代理报告工作总结。提议:
子代理执行自我反思,然后:
如果自我反思识别出可修复的问题: 1. 修复这些问题 2. 重新运行验证 3. 报告:“初始实现 + 自我反思修复”
否则: 报告:“实现完成”
在报告中包含:- 自我反思发现- 是否应用了修复- 最终验证结果为什么这有效: 当实现者已经知道修复方式时,减少延迟。已有案例记录:本可以为 entrypoint bug 节省一次往返。
权衡: 提示稍微更复杂,但端到端更快。
阶段 1:高影响、低风险(先做)
Section titled “阶段 1:高影响、低风险(先做)”- verification-before-completion:配置变更验证
- 清晰的新增内容,不改变现有内容
- 解决高影响问题(对测试产生错误信心)
- 文件:
skills/verification-before-completion/SKILL.md
- testing-anti-patterns:Mock-接口漂移
- 添加新的反模式,不修改现有内容
- 解决高影响问题(运行时崩溃)
- 文件:
skills/testing-anti-patterns/SKILL.md
- requesting-code-review:显式文件读取
- 对模板的简单补充
- 修复具体问题(审查者找不到文件)
- 文件:
skills/requesting-code-review/SKILL.md
阶段 2:中等变更(仔细测试)
Section titled “阶段 2:中等变更(仔细测试)”- subagent-driven-development:进程卫生
- 添加新章节,不改变工作流
- 解决中高影响问题(测试可靠性)
- 文件:
skills/subagent-driven-development/SKILL.md
- subagent-driven-development:自我反思
- 更改提示模板(风险更高)
- 但已有记录表明可捕获 bug
- 文件:
skills/subagent-driven-development/SKILL.md
- subagent-driven-development:技能读取要求
- 增加提示开销
- 但确保技能被实际使用
- 文件:
skills/subagent-driven-development/SKILL.md
阶段 3:优化(先验证)
Section titled “阶段 3:优化(先验证)”- subagent-driven-development:精简上下文选项
- 增加复杂性(两种方法)
- 需要验证它不会造成混乱
- 文件:
skills/subagent-driven-development/SKILL.md
- subagent-driven-development:允许实现者修复
- 更改工作流(风险更高)
- 优化,而不是 bug 修复
- 文件:
skills/subagent-driven-development/SKILL.md
- 精简上下文方法:
- 我们是否应该将其作为基于模式任务的默认方式?
- 我们如何决定使用哪种方法?
- 是否存在过于精简而遗漏重要上下文的风险?
- 自我反思:
- 这会显著拖慢简单任务吗?
- 它是否应该只适用于复杂任务?
- 我们如何防止“反思疲劳”,即它变成机械流程?
- 进程卫生:
- 它应该放在 subagent-driven-development 中,还是作为单独技能?
- 它是否适用于 E2E 测试之外的其他工作流?
- 我们如何处理进程应该持续存在的情况(开发服务器)?
- 技能读取强制:
- 我们是否应该要求所有子代理读取相关技能?
- 我们如何防止提示变得过长?
- 是否存在过度文档化而失去焦点的风险?
我们如何知道这些改进有效?
- 配置验证:
- “测试通过但使用了错误配置”的情况为零
- Jesse 不会说“那实际上并没有测试你以为自己在测试的东西”
- 进程卫生:
- “测试命中错误服务器”的情况为零
- E2E 测试运行期间没有端口冲突错误
- Mock-接口漂移:
- “测试通过但运行时因缺失方法崩溃”的情况为零
- mock 与接口之间没有方法名不匹配
- 自我反思:
- 可衡量:实现者报告是否包含自我反思发现?
- 定性:进入代码审查的 bug 是否更少?
- 技能读取:
- 子代理报告引用技能门控函数
- 代码审查中的反模式违规更少
风险:提示膨胀
Section titled “风险:提示膨胀”问题: 添加所有这些要求会让提示变得难以承受 缓解:
- 分阶段实施(不要一次添加所有内容)
- 让一些新增项成为条件性内容(E2E 卫生只用于 E2E 测试)
- 考虑为不同任务类型创建模板
风险:分析瘫痪
Section titled “风险:分析瘫痪”问题: 过多反思/验证会拖慢执行 缓解:
- 保持门控函数快速(几秒,而不是几分钟)
- 初始阶段让精简上下文作为可选项
- 监控任务完成时间
风险:错误安全感
Section titled “风险:错误安全感”问题: 遵循清单并不能保证正确性 缓解:
- 强调门控函数是最低要求,而不是最高要求
- 在技能中保留“使用判断”的语言
- 说明技能能捕获常见失败,而不是所有失败
风险:技能分歧
Section titled “风险:技能分歧”问题: 不同技能给出相互冲突的建议 缓解:
- 跨所有技能审查变更以保持一致性
- 记录技能如何交互(集成章节)
- 部署前用真实场景测试
立即推进阶段 1:
- verification-before-completion:配置变更验证
- testing-anti-patterns:Mock-接口漂移
- requesting-code-review:显式文件读取
在最终确定前与 Jesse 测试阶段 2:
- 获取关于自我反思影响的反馈
- 验证进程卫生方法
- 确认技能读取要求值得其开销
暂缓阶段 3,等待验证:
- 精简上下文需要真实世界测试
- 实现者修复工作流变更需要仔细评估
这些变更解决了用户记录的真实问题,同时最大限度降低让技能变得更糟的风险。