diff --git a/zh-CN/CHANGELOG.md b/zh-CN/CHANGELOG.md new file mode 100644 index 0000000000..5f290069df --- /dev/null +++ b/zh-CN/CHANGELOG.md @@ -0,0 +1,13 @@ +# 更新日志 + +## \[5.0.5] - 2026-03-17 + +### 修复 + +* **Brainstorm 服务器 ESM 修复**:将 `server.js` 重命名为 `server.cjs`,以便 Brainstorm 服务器在 Node.js 22+ 上正确启动,因为在 Node.js 22+ 中,根目录的 `package.json` `"type": "module"` 会导致 `require()` 失败。([PR #784](https://github.com/obra/superpowers/pull/784) 由 @sarbojitrana 提交,修复了 [#774](https://github.com/obra/superpowers/issues/774), [#780](https://github.com/obra/superpowers/issues/780), [#783](https://github.com/obra/superpowers/issues/783)) +* **Brainstorm 在 Windows 上的所有者进程 PID**:在 Windows/MSYS2 上跳过 `BRAINSTORM_OWNER_PID` 生命周期监控,因为其 PID 命名空间对 Node.js 不可见。防止服务器在 60 秒后自行终止。30 分钟的空闲超时仍作为安全网保留。([#770](https://github.com/obra/superpowers/issues/770),文档来自 [PR #768](https://github.com/obra/superpowers/pull/768) 由 @lucasyhzhu-debug 提交) +* **stop-server.sh 可靠性**:在报告成功之前,验证服务器进程是否确实已终止。等待最多 2 秒以进行正常关闭,然后升级到 `SIGKILL`,如果进程仍然存活则报告失败。([#723](https://github.com/obra/superpowers/issues/723)) + +### 变更 + +* **执行交接**:恢复用户在计划编写后,在子代理驱动开发和执行计划之间的选择。子代理驱动是推荐的,但不再是强制性的。(撤销 `5e51c3e`) diff --git a/zh-CN/CODE_OF_CONDUCT.md b/zh-CN/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..e24ac17dfa --- /dev/null +++ b/zh-CN/CODE_OF_CONDUCT.md @@ -0,0 +1,84 @@ +# 贡献者公约行为准则 + +## 我们的承诺 + +我们作为成员、贡献者和领导者承诺,无论年龄、体型、可见或不可见的残疾、民族、性别特征、性别认同与表达、经验水平、教育程度、社会经济地位、国籍、个人外貌、种族、宗教信仰或性取向与性认同如何,都将使参与我们社区成为对所有人无骚扰的体验。 + +我们承诺以促进开放、友善、多元、包容和健康社区的方式行事和互动。 + +## 我们的标准 + +有助于为我们社区创造积极环境的行为示例包括: + +* 对他人表现出同理心和善意 +* 尊重不同的意见、观点和经验 +* 给予并优雅地接受建设性反馈 +* 承担责任,向受我们错误影响的人道歉,并从经验中学习 +* 关注不仅对我们个人,而且对整个社区最有利的事情 + +不可接受的行为示例包括: + +* 使用带有性暗示的语言或图像,以及任何形式的性关注或性挑逗 +* 挑衅、侮辱或贬损性评论,以及个人或政治攻击 +* 公开或私下的骚扰 +* 未经他人明确许可,发布他人的私人信息,例如物理地址或电子邮件地址 +* 其他在专业环境中可能被视为不当的行为 + +## 执行责任 + +社区领导者有责任澄清和执行我们的可接受行为标准,并将对他们认为不当、威胁、冒犯或有害的任何行为采取适当且公平的纠正措施。 + +社区领导者有权且有责任删除、编辑或拒绝与行为准则不符的评论、提交、代码、维基编辑、问题和其他贡献,并将在适当时沟通审核决定的原因。 + +## 适用范围 + +本行为准则适用于所有社区空间,也适用于个人在公共空间正式代表社区的情况。代表我们社区的示例包括使用官方电子邮件地址、通过官方社交媒体账户发帖,或在线上或线下活动中担任指定代表。 + +## 执行 + +虐待、骚扰或其他不可接受行为的实例可以向负责执行的社区领导者报告,邮箱为 jesse@primeradiant.com。 +所有投诉都将得到及时和公平的审查和调查。 + +所有社区领导者都有义务尊重任何事件报告者的隐私和安全。 + +## 执行指南 + +社区领导者将遵循以下社区影响指南,确定他们认为违反本行为准则的任何行为的后果: + +### 1. 纠正 + +**社区影响**:使用不当语言或其他在社区中被视为不专业或不受欢迎的行为。 + +**后果**:社区领导者发出私人的书面警告,明确说明违规性质,并解释为何该行为不当。可能会要求公开道歉。 + +### 2. 警告 + +**社区影响**:通过单个事件或一系列行为造成的违规。 + +**后果**:带有持续行为后果的警告。在规定时间内,不得与相关人员互动,包括与行为准则执行者进行未经请求的互动。这包括避免在社区空间以及社交媒体等外部渠道的互动。违反这些条款可能导致暂时或永久封禁。 + +### 3. 暂时封禁 + +**社区影响**:严重违反社区标准,包括持续的不当行为。 + +**后果**:在规定时间内,禁止与社区进行任何形式的互动或公开交流。在此期间,不允许与相关人员(包括行为准则执行者)进行公开或私下的互动。违反这些条款可能导致永久封禁。 + +### 4. 永久封禁 + +**社区影响**:表现出违反社区标准的模式,包括持续的不当行为、对个人的骚扰,或对某类人群的攻击或贬低。 + +**后果**:永久禁止在社区内进行任何形式的公开互动。 + +## 致谢 + +本行为准则改编自 \[Contributor Covenant]\[homepage], +版本 2.0,可在 +https://www.contributor-covenant.org/version/2/0/code\_of\_conduct.html 获取。 + +社区影响指南的灵感来自 [Mozilla 的行为准则执行阶梯](https://github.com/mozilla/diversity)。 + +[homepage]: https://www.contributor-covenant.org + +有关本行为准则常见问题的解答,请参阅常见问题解答页面: +https://www.contributor-covenant.org/faq。翻译版本可在 +https://www.contributor-covenant.org/translations 获取。 diff --git a/zh-CN/GEMINI.md b/zh-CN/GEMINI.md new file mode 100644 index 0000000000..0dd2f585ec --- /dev/null +++ b/zh-CN/GEMINI.md @@ -0,0 +1,2 @@ +@./skills/using-superpowers/SKILL.md +@./skills/using-superpowers/references/gemini-tools.md diff --git a/zh-CN/README.md b/zh-CN/README.md new file mode 100644 index 0000000000..ec6276c08d --- /dev/null +++ b/zh-CN/README.md @@ -0,0 +1,189 @@ +# Superpowers + +Superpowers 是一个为您的编程智能体构建的完整软件开发工作流,它建立在一组可组合的“技能”和一些初始指令之上,确保您的智能体能够正确使用它们。 + +## 工作原理 + +它从您启动编程智能体的那一刻开始。一旦它发现您正在构建某些东西,它*不会*直接跳入尝试编写代码。相反,它会退一步,询问您真正想要实现的目标。 + +一旦它从对话中梳理出需求规格,它会以足够简短、便于您实际阅读和消化的块状形式展示给您。 + +在您确认设计之后,您的智能体会制定一个足够清晰的实施计划,即使是一个品味不佳、缺乏判断力、没有项目背景且厌恶测试的热心初级工程师也能遵循。它强调真正的红/绿测试驱动开发、YAGNI(您不会需要它)和 DRY 原则。 + +接下来,一旦您说“开始”,它会启动一个*子智能体驱动开发*过程,让智能体们处理每个工程任务,检查和评审他们的工作,并持续推进。Claude 通常能够自主工作数小时而不偏离您制定的计划。 + +其中还有更多内容,但这是系统的核心。由于技能会自动触发,您无需做任何特殊操作。您的编程智能体就拥有了 Superpowers。 + +## 赞助 + +如果 Superpowers 帮助您完成了能赚钱的事情,并且您有意愿,如果您能考虑[赞助我的开源工作](https://github.com/sponsors/obra),我将不胜感激。 + +谢谢! + +* Jesse + +## 安装 + +**注意:** 安装方式因平台而异。Claude Code 或 Cursor 有内置的插件市场。Codex 和 OpenCode 需要手动设置。 + +### Claude Code 官方市场 + +Superpowers 可通过[官方 Claude 插件市场](https://claude.com/plugins/superpowers)获取 + +从 Claude 市场安装插件: + +```bash +/plugin install superpowers@claude-plugins-official +``` + +### Claude Code(通过插件市场) + +在 Claude Code 中,首先注册市场: + +```bash +/plugin marketplace add obra/superpowers-marketplace +``` + +然后从此市场安装插件: + +```bash +/plugin install superpowers@superpowers-marketplace +``` + +### Cursor(通过插件市场) + +在 Cursor Agent 聊天中,从市场安装: + +```text +/add-plugin superpowers +``` + +或在插件市场中搜索“superpowers”。 + +### Codex + +告诉 Codex: + +``` +从 https://raw.githubusercontent.com/obra/superpowers/refs/heads/main/.codex/INSTALL.md 获取并遵循说明。 +``` + +**详细文档:** [docs/README.codex.md](docs/README.codex.md) + +### OpenCode + +告诉 OpenCode: + +``` +从 https://raw.githubusercontent.com/obra/superpowers/refs/heads/main/.opencode/INSTALL.md 获取并遵循说明。 +``` + +**详细文档:** [docs/README.opencode.md](docs/README.opencode.md) + +### Gemini CLI + +```bash +gemini extensions install https://github.com/obra/superpowers +``` + +要更新: + +```bash +gemini extensions update superpowers +``` + +### 验证安装 + +在您选择的平台中启动一个新会话,并询问一些应该触发技能的事情(例如,“帮我规划这个功能”或“我们来调试这个问题”)。智能体应该会自动调用相关的 superpowers 技能。 + +## 基本工作流程 + +1. **头脑风暴** - 在编写代码前激活。通过提问完善粗略想法,探索替代方案,分部分呈现设计以供验证。保存设计文档。 + +2. **使用 Git 工作树** - 在设计批准后激活。在新分支上创建隔离的工作区,运行项目设置,验证干净的测试基线。 + +3. **编写计划** - 在批准设计后激活。将工作分解成小块任务(每个 2-5 分钟)。每个任务都有确切的文件路径、完整代码、验证步骤。 + +4. **子智能体驱动开发** 或 **执行计划** - 在计划制定后激活。为每个任务派遣新的子智能体,进行两阶段评审(规范符合性,然后是代码质量),或者分批执行并设置人工检查点。 + +5. **测试驱动开发** - 在实施过程中激活。强制执行 RED-GREEN-REFACTOR 循环:编写失败测试,观察其失败,编写最小化代码,观察其通过,提交。删除在测试之前编写的代码。 + +6. **请求代码审查** - 在任务之间激活。对照计划进行审查,按严重程度报告问题。关键问题会阻止进展。 + +7. **完成开发分支** - 在任务完成时激活。验证测试,呈现选项(合并/PR/保留/丢弃),清理工作树。 + +**智能体在任何任务前都会检查相关技能。** 这是强制性的工作流程,而非建议。 + +## 包含内容 + +### 技能库 + +**测试** + +* **测试驱动开发** - RED-GREEN-REFACTOR 循环(包含测试反模式参考) + +**调试** + +* **系统化调试** - 4 阶段根本原因分析过程(包含根本原因追溯、深度防御、条件等待技术) +* **完成前验证** - 确保问题真正解决 + +**协作** + +* **头脑风暴** - 苏格拉底式设计完善 +* **编写计划** - 详细的实施计划 +* **执行计划** - 带检查点的批量执行 +* **派遣并行智能体** - 并发子智能体工作流 +* **请求代码审查** - 预审查清单 +* **接收代码审查** - 响应反馈 +* **使用 Git 工作树** - 并行开发分支 +* **完成开发分支** - 合并/PR 决策工作流 +* **子智能体驱动开发** - 带两阶段评审(规范符合性,然后是代码质量)的快速迭代 + +**元技能** + +* **编写技能** - 遵循最佳实践创建新技能(包含测试方法) +* **使用 superpowers** - 技能系统介绍 + +## 理念 + +* **测试驱动开发** - 始终先写测试 +* **系统化优于临时性** - 流程优于猜测 +* **降低复杂性** - 以简洁为主要目标 +* **证据优于断言** - 在宣布成功前进行验证 + +阅读更多:[适用于 Claude Code 的 Superpowers](https://blog.fsck.com/2025/10/09/superpowers/) + +## 贡献 + +技能直接存放在此代码库中。要贡献: + +1. 分叉此代码库 +2. 为您的技能创建一个分支 +3. 遵循 `writing-skills` 技能来创建和测试新技能 +4. 提交 PR + +查看 `skills/writing-skills/SKILL.md` 获取完整指南。 + +## 更新 + +当您更新插件时,技能会自动更新: + +```bash +/plugin update superpowers +``` + +## 许可证 + +MIT 许可证 - 详见 LICENSE 文件 + +## 社区 + +Superpowers 由 [Jesse Vincent](https://blog.fsck.com) 和 [Prime Radiant](https://primeradiant.com) 的其他成员共同构建。 + +如需社区支持、问题咨询,或分享您使用 Superpowers 构建的项目,欢迎加入我们的 [Discord](https://discord.gg/Jd8Vphy9jq)。 + +## 支持 + +* **Discord**:[加入我们的 Discord](https://discord.gg/Jd8Vphy9jq) +* **问题反馈**:https://github.com/obra/superpowers/issues +* **市场**:https://github.com/obra/superpowers-marketplace diff --git a/zh-CN/RELEASE-NOTES.md b/zh-CN/RELEASE-NOTES.md new file mode 100644 index 0000000000..8456b3b1fc --- /dev/null +++ b/zh-CN/RELEASE-NOTES.md @@ -0,0 +1,1102 @@ +# Superpowers 发布说明 + +## v5.0.5 (2026-03-17) + +### 错误修复 + +* **Brainstorm 服务器 ESM 修复** — 将 `server.js` 重命名为 `server.cjs`,使得 Brainstorming 服务器能在 Node.js 22+ 上正确启动,在这些版本中,根目录的 `package.json` `"type": "module"` 会导致 `require()` 失败。(PR #784 by @sarbojitrana,修复 #774, #780, #783) +* **Brainstorm 在 Windows 上的所有者 PID** — 在 Windows/MSYS2 上跳过 PID 生命周期监控,因为 Node.js 无法看到其 PID 命名空间,从而防止服务器在 60 秒后自行终止。(#770,文档来自 PR #768 by @lucasyhzlu-debug) +* **stop-server.sh 可靠性提升** — 在报告成功之前,验证服务器进程确实已终止。采用 SIGTERM + 等待 2 秒 + SIGKILL 备选方案。(#723) + +### 已更改 + +* **执行移交** — 在计划编写后,恢复用户在子代理驱动执行和内联执行之间的选择。推荐使用子代理驱动,但不再是强制性的。 + +## v5.0.4 (2026-03-16) + +### 审查循环优化 + +通过消除不必要的审查轮次和收紧审查者关注点,显著减少了令牌使用量,并加速了规范和计划的审查。 + +* **单次完整计划审查** — 计划审查者现在一次性审查完整计划,而不是分块审查。移除了所有与分块相关的概念(`## Chunk N:` 标题、1000 行分块限制、每块调度)。 +* **提高了阻塞问题的门槛** — 规范和计划审查者的提示现在都包含一个“校准”部分:仅标记那些会在实施过程中导致实际问题的项目。轻微的措辞、风格偏好和格式上的吹毛求疵不应阻止批准。 +* **减少了最大审查迭代次数** — 规范和计划审查循环都从 5 次减少到 3 次。如果审查者校准正确,3 轮就足够了。 +* **精简了审查者清单** — 规范审查者从 7 个类别精简到 5 个;计划审查者从 7 个精简到 4 个。移除了以格式为重点的检查(任务语法、分块大小),转而关注实质内容(可构建性、规范一致性)。 + +### OpenCode + +* **单行插件安装** — OpenCode 插件现在通过一个 `config` 钩子自动注册技能目录。不再需要符号链接或 `skills.paths` 配置。安装只需在 `opencode.json` 中添加一行。(PR #753) +* **添加了 `package.json`**,以便 OpenCode 可以从 git 安装 superpowers 作为 npm 包。 + +### 错误修复 + +* **验证服务器确实已停止** — `stop-server.sh` 现在会在报告成功之前确认进程已终止。采用 SIGTERM + 等待 2 秒 + SIGKILL 备选方案。如果进程存活,则报告失败。(PR #751) +* **通用代理语言** — brainstorm 伴侣等待页面现在说“代理”而不是“Claude”。 + +## v5.0.3 (2026-03-15) + +### Cursor 支持 + +* **Cursor 钩子** — 添加了 `hooks/hooks-cursor.json`,采用 Cursor 的驼峰命名格式(`sessionStart`,`version: 1`),并更新了 `.cursor-plugin/plugin.json` 以引用它。修复了 `session-start` 中的平台检测,优先检查 `CURSOR_PLUGIN_ROOT`(Cursor 也可能设置 `CLAUDE_PLUGIN_ROOT`)。(基于 PR #709) + +### 错误修复 + +* **停止在 `--resume` 时触发 SessionStart 钩子** — 启动钩子会在恢复的会话中重新注入上下文,而这些会话的对话历史中已经包含了上下文。该钩子现在仅在 `startup`、`clear` 和 `compact` 时触发。 +* **Bash 5.3+ 钩子挂起** — 在 `hooks/session-start` 中用 `printf` 替换了 heredoc(`cat <` + +### 子代理上下文隔离 + +* 所有委派技能(头脑风暴、并行代理调度、请求代码审查、子代理驱动开发、编写计划)现在都包含上下文隔离原则 +* 子代理仅接收它们所需的上下文,防止上下文窗口污染 + +## v5.0.1 (2026-03-10) + +### Agentskills 合规性 + +**Brainstorm-server 移至技能目录** + +* 根据 [agentskills.io](https://agentskills.io) 规范,将 `lib/brainstorm-server/` 移至 `skills/brainstorming/scripts/` +* 所有 `${CLAUDE_PLUGIN_ROOT}/lib/brainstorm-server/` 引用替换为相对的 `scripts/` 路径 +* 技能现在完全跨平台可移植 — 无需平台特定的环境变量来定位脚本 +* 删除了 `lib/` 目录(这是最后剩余的内容) + +### 新功能 + +**Gemini CLI 扩展** + +* 通过仓库根目录的 `gemini-extension.json` 和 `GEMINI.md` 实现原生的 Gemini CLI 扩展支持 +* `GEMINI.md` 在会话开始时 @imports `using-superpowers` 技能和工具映射表 +* Gemini CLI 工具映射参考(`skills/using-superpowers/references/gemini-tools.md`)— 将 Claude Code 工具名称(Read、Write、Edit、Bash 等)翻译为 Gemini CLI 等效项(read\_file、write\_file、replace 等) +* 记录了 Gemini CLI 的限制:无子代理支持,技能回退到 `executing-plans` +* 扩展根目录位于仓库根目录以实现跨平台兼容性(避免 Windows 符号链接问题) +* 安装说明已添加到 README + +### 改进 + +**多平台头脑风暴服务器启动** + +* visual-companion.md 中的每平台启动说明:Claude Code(默认模式)、Codex(通过 `CODEX_CI` 自动前台运行)、Gemini CLI(带有 `--foreground` 的 `is_background`)以及其他环境的回退方案 +* 服务器现在将启动 JSON 写入 `$SCREEN_DIR/.server-info`,以便代理即使在后台执行隐藏了 stdout 时也能找到 URL 和端口 + +**头脑风暴服务器依赖项打包** + +* `node_modules` 已打包到仓库中,这样头脑风暴服务器在全新插件安装后无需运行时执行 `npm` 即可立即工作 +* 从打包的依赖项中移除了 `fsevents`(仅限 macOS 的原生二进制文件;chokidar 在缺少它时会优雅地回退) +* 如果缺少 `node_modules`,则通过 `npm install` 进行回退自动安装 + +**OpenCode 工具映射修复** + +* `TodoWrite` → `todowrite`(之前错误地映射到 `update_plan`);已根据 OpenCode 源代码验证 + +### 错误修复 + +**Windows/Linux:单引号破坏 SessionStart 钩子** (#577, #529, #644, PR #585) + +* hooks.json 中 `${CLAUDE_PLUGIN_ROOT}` 周围的单引号在 Windows 上失败(cmd.exe 不将单引号识别为路径分隔符)以及在 Linux 上失败(单引号阻止变量扩展) +* 修复:将单引号替换为转义的双引号 — 在 macOS bash、Windows cmd.exe、Windows Git Bash 和 Linux 上均可工作,无论路径中是否包含空格 +* 已在 Windows 11(NT 10.0.26200.0)上使用 Claude Code 2.1.72 和 Git for Windows 验证 + +**头脑风暴规范审查循环被跳过** (#677) + +* 规范审查循环(调度 spec-document-reviewer 子代理,迭代直到批准)存在于散文“设计之后”部分,但在检查清单和流程图中缺失 +* 由于代理遵循图表和检查清单比散文更可靠,规范审查步骤被完全跳过 +* 已将步骤 7(规范审查循环)添加到检查清单,并将相应的节点添加到点图 +* 使用 `claude --plugin-dir` 和 `claude-session-driver` 测试:worker 现在能正确调度审查者 + +**Cursor 安装命令** (PR #676) + +* 修复了 README 中的 Cursor 安装命令:`/plugin-add` → `/add-plugin`(通过 Cursor 2.5 发布公告确认) + +**头脑风暴中的用户审查关口** (#565) + +* 在规范完成和编写计划交接之间添加了明确的用户审查步骤 +* 用户必须在实施计划开始前批准规范 +* 检查清单、流程图和散文已更新,包含新的关口 + +**会话启动钩子每个平台仅发出一次上下文** + +* 钩子现在检测它是在 Claude Code 还是其他平台中运行 +* 为 Claude Code 发出 `hookSpecificOutput`,为其他平台发出 `additional_context` — 防止双重上下文注入 + +**令牌分析脚本中的代码风格修复** + +* `except:` → `except Exception:`,位于 `tests/claude-code/analyze-token-usage.py` + +### 维护 + +**移除死代码** + +* 删除了 `lib/skills-core.js` 及其测试(`tests/opencode/test-skills-core.js`)— 自 2026 年 2 月起未使用 +* 从 `tests/opencode/test-plugin-loading.sh` 中移除了 skills-core 存在性检查 + +### 社区 + +* @karuturi — Claude Code 官方市场安装说明(PR #610) +* @mvanhorn — 会话启动钩子双重发出修复,OpenCode 工具映射修复 +* @daniel-graham — 裸异常捕获的代码风格修复 +* PR #585 作者 — Windows/Linux 钩子引号修复 + +*** + +## v5.0.0 (2026-03-09) + +### 破坏性变更 + +**规范和计划目录结构调整** + +* 规范(头脑风暴输出)现在保存到 `docs/superpowers/specs/YYYY-MM-DD--design.md` +* 计划(编写计划输出)现在保存到 `docs/superpowers/plans/YYYY-MM-DD-.md` +* 用户对规范/计划位置的偏好会覆盖这些默认值 +* 所有内部技能引用、测试文件和示例路径都已更新以匹配新结构 +* 迁移:如果需要,将现有文件从 `docs/plans/` 移动到新位置 + +**在支持的子代理平台上强制使用子代理驱动开发** + +编写计划不再提供在子代理驱动和执行计划之间的选择。在具有子代理支持的平台(Claude Code、Codex)上,子代理驱动开发是必需的。执行计划保留给没有子代理能力的平台,并且现在会告知用户 Superpowers 在支持子代理的平台上效果更好。 + +**执行计划不再分批执行** + +移除了“执行 3 个任务后停止审查”的模式。计划现在连续执行,仅在遇到阻塞时停止。 + +**斜杠命令已弃用** + +`/brainstorm`、`/write-plan` 和 `/execute-plan` 现在显示弃用通知,引导用户使用相应的技能。命令将在下一个主要版本中移除。 + +### 新功能 + +**可视化头脑风暴伴侣** + +头脑风暴会话的可选浏览器伴侣。当主题受益于可视化时,头脑风暴技能会提供在浏览器窗口中显示与终端对话并行的线框图、图表、比较和其他内容。 + +* `lib/brainstorm-server/` — 包含浏览器助手库、会话管理脚本和深色/浅色主题框架模板(“Superpowers Brainstorming” 带 GitHub 链接)的 WebSocket 服务器 +* `skills/brainstorming/visual-companion.md` — 服务器工作流程、屏幕创作和反馈收集的渐进式指南 +* 头脑风暴技能在其流程中添加了一个可视化伴侣决策点:在探索项目上下文后,技能评估即将到来的问题是否涉及可视化内容,并在其自己的消息中提供伴侣 +* 按问题决策:即使在接受后,每个问题都会评估浏览器还是终端更合适 +* `tests/brainstorm-server/` 中的集成测试 + +**文档审查系统** + +使用子代理调度的规范和计划文档的自动化审查循环: + +* `skills/brainstorming/spec-document-reviewer-prompt.md` — 审查者检查完整性、一致性、架构和 YAGNI +* `skills/writing-plans/plan-document-reviewer-prompt.md` — 审查者检查规范对齐、任务分解、文件结构和文件大小 +* 头脑风暴在编写设计文档后调度规范审查者 +* 编写计划在每个部分后包含基于块的计划审查循环 +* 审查循环重复直到批准或在 5 次迭代后升级 +* `tests/claude-code/test-document-review-system.sh` 中的端到端测试 +* `docs/superpowers/` 中的设计规范和实施计划 + +**贯穿技能管道的架构指导** + +设计隔离和文件大小感知指导已添加到头脑风暴、编写计划和子代理驱动开发中: + +* **头脑风暴** — 新章节:“为隔离和清晰度而设计”(清晰的边界、定义良好的接口、独立可测试的单元)和“在现有代码库中工作”(遵循现有模式,仅进行有针对性的改进) +* **编写计划** — 新的“文件结构”部分:在定义任务前规划文件和职责。新的“范围检查”后备机制:捕获应在头脑风暴期间分解的多子系统规范 +* **SDD 实施者** — 新的“代码组织”部分(遵循计划的文件结构,报告对文件增长的担忧)和“当您力不从心时”的升级指导 +* **SDD 代码质量审查者** — 现在检查架构、单元分解、计划符合性和文件增长 +* **规范/计划审查者** — 架构和文件大小已添加到审查标准中 +* **范围评估** — 头脑风暴现在评估项目是否对单个规范来说太大。多子系统请求会及早标记,并分解为子项目,每个子项目都有自己的规范 → 计划 → 实施周期 + +**子代理驱动开发的改进** + +* **模型选择** — 按任务类型选择模型能力的指导:廉价模型用于机械实施,标准模型用于集成,能力强模型用于架构和审查 +* **实施者状态协议** — 子代理现在报告 DONE、DONE\_WITH\_CONCERNS、BLOCKED 或 NEEDS\_CONTEXT。控制器适当地处理每个状态:用更多上下文重新调度、升级模型能力、分解任务或升级给人类 + +### 改进 + +**指令优先级层次结构** + +向 using-superpowers 添加了明确的优先级排序: + +1. 用户的明确指令(CLAUDE.md、AGENTS.md、直接请求)— 最高优先级 +2. Superpowers 技能 — 覆盖默认系统行为 +3. 默认系统提示 — 最低优先级 + +如果 CLAUDE.md 或 AGENTS.md 说“不要使用 TDD”而一个技能说“始终使用 TDD”,那么用户的指令胜出。 + +**SUBAGENT-STOP 关口** + +向 using-superpowers 添加了 `` 块。为特定任务调度的子代理现在跳过该技能,而不是激活 1% 规则并调用完整的技能工作流。 + +**多平台改进** + +* Codex 工具映射移至渐进式参考文件(`references/codex-tools.md`) +* 添加了平台适配指针,以便非 Claude-Code 平台可以找到工具等效项 +* 计划头部现在针对“代理工作者”而不是特定的“Claude” +* 协作功能要求在 `docs/README.codex.md` 中记录 + +**编写计划模板更新** + +* 计划步骤现在使用复选框语法(`- [ ] **Step N:**`)进行进度跟踪 +* 计划头部引用子代理驱动开发和执行计划,并具有平台感知的路由 + +*** + +## v4.3.1 (2026-02-21) + +### 新增 + +**Cursor 支持** + +Superpowers 现在可与 Cursor 的插件系统协同工作。包含一个 `.cursor-plugin/plugin.json` 清单,以及 README 中的 Cursor 特定安装说明。SessionStart 钩子的输出现在包含一个 `additional_context` 字段,与现有的 `hookSpecificOutput.additionalContext` 并列,以实现 Cursor 钩子的兼容性。 + +### 已修复 + +**Windows:恢复了多语言包装器以确保钩子可靠执行 (#518, #504, #491, #487, #466, #440)** + +Claude Code 在 Windows 上的 `.sh` 自动检测功能,会在钩子命令前添加 `bash`,从而破坏执行。修复方法如下: + +* 将 `session-start.sh` 重命名为 `session-start`(无扩展名),这样自动检测就不会干扰 +* 恢复了 `run-hook.cmd` 多语言包装器,包含多位置 bash 发现(标准的 Git for Windows 路径,然后是 PATH 回退) +* 如果未找到 bash,则静默退出,而不是报错 +* 在 Unix 上,包装器通过 `exec bash` 直接运行脚本 +* 使用符合 POSIX 标准的 `dirname "$0"` 路径解析(适用于 dash/sh,不仅仅是 bash) + +这修复了 Windows 上因路径包含空格、缺少 WSL、MSYS 上 `set -euo pipefail` 的脆弱性以及反斜杠处理错误导致的 SessionStart 失败。 + +## v4.3.0 (2026-02-12) + +此修复应能显著提高 superpowers 技能合规性,并应降低 Claude 意外进入其原生计划模式的可能性。 + +### 已更改 + +**头脑风暴技能现在强制执行其工作流程,而非仅描述它** + +模型曾跳过设计阶段,直接跳转到实现技能(如前端设计),或将整个头脑风暴过程压缩到单个文本块中。该技能现在使用硬性关卡、强制检查清单和 graphviz 流程来确保合规: + +* ``:在展示设计并获得用户批准之前,不得使用实现技能、编写代码或进行脚手架搭建 +* 明确的检查清单(6项),必须创建为任务并按顺序完成 +* 包含 `writing-plans` 作为唯一有效终止状态的 Graphviz 流程图 +* 对“这太简单了,不需要设计”这种反模式提出警告——这正是模型用来跳过流程的合理化说辞 +* 设计部分的大小基于部分复杂性,而非项目复杂性 + +**使用-superpowers 工作流图拦截 EnterPlanMode** + +在技能流程图中添加了 `EnterPlanMode` 拦截。当模型即将进入 Claude 的原生计划模式时,它会检查是否已进行头脑风暴,并改为路由到头脑风暴技能。计划模式永远不会被进入。 + +### 已修复 + +**SessionStart 钩子现在同步运行** + +将 hooks.json 中的 `async: true` 更改为 `async: false`。异步运行时,钩子可能在模型的第一个回合之前无法完成,这意味着使用-superpowers 指令在第一条消息时未处于上下文中。 + +## v4.2.0 (2026-02-05) + +### 破坏性变更 + +**Codex:用原生技能发现替换了引导 CLI** + +移除了 `superpowers-codex` 引导 CLI、Windows `.cmd` 包装器以及相关的引导内容文件。Codex 现在通过 `~/.agents/skills/superpowers/` 符号链接使用原生技能发现,因此不再需要旧的 `use_skill`/`find_skills` CLI 工具。 + +现在安装只需克隆 + 创建符号链接(在 INSTALL.md 中有记录)。不需要 Node.js 依赖。旧的 `~/.codex/skills/` 路径已被弃用。 + +### 修复 + +**Windows:修复了 Claude Code 2.1.x 的钩子执行 (#331)** + +Claude Code 2.1.x 更改了 Windows 上钩子的执行方式:现在它会自动检测命令中的 `.sh` 文件,并在前面添加 `bash`。这破坏了多语言包装器模式,因为 `bash "run-hook.cmd" session-start.sh` 试图将 `.cmd` 文件作为 bash 脚本执行。 + +修复方法:hooks.json 现在直接调用 session-start.sh。Claude Code 2.1.x 会自动处理 bash 调用。同时添加了 .gitattributes 来为 shell 脚本强制执行 LF 行尾(修复了 Windows 检出时的 CRLF 问题)。 + +**Windows:SessionStart 钩子异步运行以防止终端冻结 (#404, #413, #414, #419)** + +同步的 SessionStart 钩子在 Windows 上会阻止 TUI 进入原始模式,冻结所有键盘输入。异步运行钩子可以防止冻结,同时仍能注入 superpowers 上下文。 + +**Windows:修复了 O(n^2) 的 `escape_for_json` 性能** + +使用 `${input:$i:1}` 的逐字符循环,由于子字符串复制开销,在 bash 中是 O(n^2) 复杂度。在 Windows Git Bash 上,这需要 60 多秒。已替换为 bash 参数替换(`${s//old/new}`),它将每个模式作为一次 C 语言级别的遍历运行——在 macOS 上快 7 倍,在 Windows 上显著加快。 + +**Codex:修复了 Windows/PowerShell 调用 (#285, #243)** + +* Windows 不遵循 shebang,因此直接调用无扩展名的 `superpowers-codex` 脚本会触发“打开方式”对话框。所有调用现在都加上了 `node` 前缀。 +* 修复了 Windows 上的 `~/` 路径扩展问题——PowerShell 在将 `~` 作为参数传递给 `node` 时不会扩展它。已更改为 `$HOME`,它在 bash 和 PowerShell 中都能正确扩展。 + +**Codex:修复了安装程序中的路径解析** + +使用 `fileURLToPath()` 替代手动 URL 路径名解析,以在所有平台上正确处理包含空格和特殊字符的路径。 + +**Codex:修复了 writing-skills 中过时的技能路径** + +将 `~/.codex/skills/` 引用(已弃用)更新为 `~/.agents/skills/`,以支持原生发现。 + +### 改进 + +**在实现之前现在需要工作树隔离** + +为 `subagent-driven-development` 和 `executing-plans` 添加了 `using-git-worktrees` 作为必需技能。实现工作流现在明确要求在开始工作之前设置一个隔离的工作树,防止直接在 main 分支上意外工作。 + +**Main 分支保护放宽为需要明确同意** + +技能不再完全禁止在 main 分支上工作,而是允许在获得用户明确同意后进行。这样更灵活,同时仍能确保用户了解其影响。 + +**简化了安装验证** + +从验证步骤中移除了 `/help` 命令检查和特定的斜杠命令列表。技能主要通过描述你想要做的事情来调用,而不是通过运行特定命令。 + +**Codex:在引导程序中澄清了子代理工具映射** + +改进了关于 Codex 工具如何映射到 Claude Code 等效工具以实现子代理工作流的文档。 + +### 测试 + +* 为 subagent-driven-development 添加了工作树要求测试 +* 添加了 main 分支危险警告测试 +* 修复了技能识别测试断言中的大小写敏感性 + +*** + +## v4.1.1 (2026-01-23) + +### 修复 + +**OpenCode:根据官方文档标准化为 `plugins/` 目录 (#343)** + +OpenCode 的官方文档使用 `~/.config/opencode/plugins/`(复数形式)。我们的文档之前使用 `plugin/`(单数形式)。虽然 OpenCode 接受两种形式,但我们已经标准化为官方约定,以避免混淆。 + +更改: + +* 在仓库结构中,将 `.opencode/plugin/` 重命名为 `.opencode/plugins/` +* 更新了所有平台上的所有安装文档(INSTALL.md、README.opencode.md) +* 更新了测试脚本以匹配 + +**OpenCode:修复了符号链接说明 (#339, #342)** + +* 在 `ln -s` 之前添加了明确的 `rm`(修复重新安装时的“文件已存在”错误) +* 添加了 INSTALL.md 中缺失的技能符号链接步骤 +* 更新了已弃用的 `use_skill`/`find_skills` 引用,改为原生的 `skill` 工具引用 + +*** + +## v4.1.0 (2026-01-23) + +### 破坏性变更 + +**OpenCode:切换到原生技能系统** + +用于 OpenCode 的 Superpowers 现在使用 OpenCode 的原生 `skill` 工具,而不是自定义的 `use_skill`/`find_skills` 工具。这是一个更简洁的集成,可与 OpenCode 内置的技能发现协同工作。 + +**需要迁移:** 技能必须符号链接到 `~/.config/opencode/skills/superpowers/`(请参阅更新的安装文档)。 + +### 修复 + +**OpenCode:修复了会话开始时的代理重置问题 (#226)** + +之前使用 `session.prompt({ noReply: true })` 的引导注入方法导致 OpenCode 在第一条消息时将所选代理重置为“build”。现在使用 `experimental.chat.system.transform` 钩子,它直接修改系统提示,没有副作用。 + +**OpenCode:修复了 Windows 安装问题 (#232)** + +* 移除了对 `skills-core.js` 的依赖(消除了文件被复制而非符号链接时出现的损坏的相对导入问题) +* 为 cmd.exe、PowerShell 和 Git Bash 添加了全面的 Windows 安装文档 +* 记录了每个平台正确的符号链接与连接点用法 + +**Claude Code:修复了 Claude Code 2.1.x 在 Windows 上的钩子执行问题** + +Claude Code 2.1.x 更改了 Windows 上钩子的执行方式:现在它会自动检测命令中的 `.sh` 文件,并在前面添加 `bash `。这破坏了多语言包装器模式,因为 `bash "run-hook.cmd" session-start.sh` 试图将 .cmd 文件作为 bash 脚本执行。 + +修复方法:hooks.json 现在直接调用 session-start.sh。Claude Code 2.1.x 会自动处理 bash 调用。同时添加了 .gitattributes 来为 shell 脚本强制执行 LF 行尾(修复了 Windows 检出时的 CRLF 问题)。 + +*** + +## v4.0.3 (2025-12-26) + +### 改进 + +**增强了使用-superpowers 技能以应对明确的技能请求** + +解决了一个故障模式,即使用户明确按名称请求技能(例如,“请使用 subagent-driven-development”),Claude 也会跳过调用该技能。Claude 会认为“我知道那是什么意思”,然后直接开始工作,而不是加载技能。 + +更改: + +* 更新了“规则”,将“检查技能”改为“调用相关或请求的技能”——强调主动调用而非被动检查 +* 添加了“在任何响应或行动之前”——原始措辞只提到了“响应”,但 Claude 有时会在不先响应的情况下采取行动 +* 添加了保证:调用错误的技能也没关系——减少犹豫 +* 添加了新的危险信号:“我知道那是什么意思”→ 知道概念 ≠ 使用技能 + +**添加了明确的技能请求测试** + +在 `tests/explicit-skill-requests/` 中添加了新的测试套件,用于验证当用户按名称请求技能时,Claude 是否正确调用技能。包括单回合和多回合测试场景。 + +## v4.0.2 (2025-12-23) + +### 修复 + +**斜杠命令现在仅供用户使用** + +为所有三个斜杠命令(`/brainstorm`、`/execute-plan`、`/write-plan`)添加了 `disable-model-invocation: true`。Claude 不能再通过 Skill 工具调用这些命令——它们仅限于手动用户调用。 + +底层技能(`superpowers:brainstorming`、`superpowers:executing-plans`、`superpowers:writing-plans`)仍然可供 Claude 自主调用。此更改防止了当 Claude 调用一个只是重定向到技能的指令时产生的混淆。 + +## v4.0.1 (2025-12-23) + +### 修复 + +**阐明了如何在 Claude Code 中访问技能** + +修复了一个令人困惑的模式:Claude 通过 Skill 工具调用技能后,会尝试单独读取技能文件。`using-superpowers` 技能现在明确指出,Skill 工具会直接加载技能内容——无需读取文件。 + +* 向 `using-superpowers` 添加了“如何访问技能”部分 +* 在说明中将“读取技能”改为“调用技能” +* 更新了斜杠命令以使用完全限定的技能名称(例如,`superpowers:brainstorming`) + +**向 receiving-code-review 添加了 GitHub 线程回复指南**(感谢 @ralphbean) + +添加了关于在原始线程中回复内联评论,而不是作为顶级 PR 评论的说明。 + +**向 writing-skills 添加了自动化优于文档的指南**(感谢 @EthanJStark) + +添加了指南:机械性约束应自动化,而非文档化——将技能留给判断性决策。 + +## v4.0.0 (2025-12-17) + +### 新功能 + +**subagent-driven-development 中的两阶段代码审查** + +子代理工作流现在在每个任务后使用两个独立的审查阶段: + +1. **规范符合性审查** - 持怀疑态度的审查者验证实现是否完全符合规范。捕捉缺失的需求**和**过度构建。不信任实施者的报告——阅读实际代码。 +2. **代码质量审查** - 仅在规范符合性通过后运行。审查代码整洁度、测试覆盖率、可维护性。 + +这捕捉了代码编写良好但与请求不符的常见失败模式。评审是循环而非单次操作:若评审者发现问题,实施者修复后,评审者会再次检查。 + +其他子代理工作流改进: + +* 控制器向工作者提供完整任务文本(而非文件引用) +* 工作者可在工作开始前及工作中提出澄清问题 +* 报告完成前进行自我评审检查清单 +* 计划仅在开始时读取一次,并提取到TodoWrite + +`skills/subagent-driven-development/`中的新提示模板: + +* `implementer-prompt.md` - 包含自我评审检查清单,鼓励提问 +* `spec-reviewer-prompt.md` - 针对需求进行怀疑性验证 +* `code-quality-reviewer-prompt.md` - 标准代码评审 + +**调试技术与工具整合** + +`systematic-debugging`现已捆绑支持技术和工具: + +* `root-cause-tracing.md` - 通过调用栈反向追踪错误 +* `defense-in-depth.md` - 在多个层级添加验证 +* `condition-based-waiting.md` - 用条件轮询替代任意超时 +* `find-polluter.sh` - 二分查找脚本定位产生污染的测试 +* `condition-based-waiting-example.ts` - 来自实际调试会话的完整实现 + +**测试反模式参考** + +`test-driven-development`现包含`testing-anti-patterns.md`,涵盖: + +* 测试模拟行为而非真实行为 +* 向生产类添加仅用于测试的方法 +* 在不理解依赖关系的情况下进行模拟 +* 隐藏结构假设的不完整模拟 + +**技能测试基础设施** + +用于验证技能行为的三个新测试框架: + +`tests/skill-triggering/` - 验证技能能否通过朴素提示触发而无需显式命名。测试6项技能以确保仅凭描述即可触发。 + +`tests/claude-code/` - 使用`claude -p`进行无头测试的集成测试。通过会话转录(JSONL)分析验证技能使用情况。包含用于成本跟踪的`analyze-token-usage.py`。 + +`tests/subagent-driven-dev/` - 包含两个完整测试项目的端到端工作流验证: + +* `go-fractals/` - 包含Sierpinski/Mandelbrot的CLI工具(10项任务) +* `svelte-todo/` - 包含localStorage和Playwright的CRUD应用(12项任务) + +### 主要变更 + +**将DOT流程图作为可执行规范** + +使用DOT/GraphViz流程图作为权威流程定义重写了关键技能。文本内容变为辅助性材料。 + +**描述陷阱**(记录于`writing-skills`):发现当技能描述包含工作流摘要时,技能描述会覆盖流程图内容。Claude会遵循简短描述而非阅读详细的流程图。修复方法:描述必须仅为触发用途("在X情况下使用"),不包含流程细节。 + +**using-superpowers中的技能优先级** + +当多个技能适用时,流程技能(头脑风暴、调试)现在明确优先于实现技能。"构建X"会先触发头脑风暴,然后是领域技能。 + +**头脑风暴触发机制强化** + +描述改为命令式:"在进行任何创造性工作前——创建功能、构建组件、添加功能或修改行为时,你必须使用此技能。" + +### 破坏性变更 + +**技能整合** - 六项独立技能已合并: + +* `root-cause-tracing`、`defense-in-depth`、`condition-based-waiting` → 捆绑于`systematic-debugging/` +* `testing-skills-with-subagents` → 捆绑于`writing-skills/` +* `testing-anti-patterns` → 捆绑于`test-driven-development/` +* `sharing-skills`已移除(已过时) + +### 其他改进 + +* **render-graphs.js** - 从技能中提取DOT图表并渲染为SVG的工具 +* **using-superpowers中的合理化表格** - 可扫描格式,包含新条目:"我需要更多上下文"、"让我先探索"、"这感觉很有成效" +* **docs/testing.md** - 使用Claude Code集成测试测试技能的指南 + +*** + +## v3.6.2 (2025-12-03) + +### 已修复 + +* **Linux兼容性**:修复了多语言钩子包装器(`run-hook.cmd`)以使用符合POSIX标准的语法 + * 第16行将bash特定的`${BASH_SOURCE[0]:-$0}`替换为标准`$0` + * 解决了在Ubuntu/Debian系统上(其中`/bin/sh`为dash)出现的"Bad substitution"错误 + * 修复了#141 + +*** + +## v3.5.1 (2025-11-24) + +### 已更改 + +* **OpenCode引导程序重构**:从`chat.message`钩子切换到`session.created`事件进行引导程序注入 + * 引导程序现通过`session.prompt()`在会话创建时注入,使用`noReply: true` + * 明确告知模型using-superpowers已加载,防止冗余技能加载 + * 将引导程序内容生成整合到共享的`getBootstrapContent()`辅助函数中 + * 更简洁的单实现方法(移除了回退模式) + +*** + +## v3.5.0 (2025-11-23) + +### 新增 + +* **OpenCode支持**:OpenCode.ai的原生JavaScript插件 + * 自定义工具:`use_skill`和`find_skills` + * 用于在上下文压缩后保持技能持久性的消息插入模式 + * 通过chat.message钩子自动注入上下文 + * 在session.compacted事件上自动重新注入 + * 三层技能优先级:项目 > 个人 > superpowers + * 项目本地技能支持(`.opencode/skills/`) + * 用于与Codex代码重用的共享核心模块(`lib/skills-core.js`) + * 具有适当隔离的自动化测试套件(`tests/opencode/`) + * 平台特定文档(`docs/README.opencode.md`、`docs/README.codex.md`) + +### 已更改 + +* **重构的Codex实现**:现在使用共享的`lib/skills-core.js` ES模块 + * 消除了Codex和OpenCode之间的代码重复 + * 技能发现和解析的单一真实来源 + * Codex通过Node.js互操作成功加载ES模块 + +* **改进的文档**:重写README以清晰解释问题/解决方案 + * 移除了重复部分和冲突信息 + * 添加了完整的工作流描述(头脑风暴 → 计划 → 执行 → 完成) + * 简化了平台安装说明 + * 强调技能检查协议而非自动激活声明 + +*** + +## v3.4.1 (2025-10-31) + +### 改进 + +* 优化了superpowers引导程序以消除冗余技能执行。`using-superpowers`技能内容现在直接在会话上下文中提供,并附有明确指导,仅将Skill工具用于其他技能。这减少了开销,并防止了代理尽管在会话开始时已获得内容但仍手动执行`using-superpowers`的混乱循环。 + +## v3.4.0 (2025-10-30) + +### 改进 + +* 简化了`brainstorming`技能,回归到原始的对话式愿景。移除了带有正式检查清单的重型6阶段流程,转而采用自然对话:一次提出一个问题,然后以200-300字的部分呈现设计并进行验证。保留了文档和实现交接功能。 + +## v3.3.1 (2025-10-28) + +### 改进 + +* 更新了`brainstorming`技能,要求在提问前进行自主侦察,鼓励基于推荐的决策,并防止代理将优先级决定权交还给人类。 +* 应用了写作清晰度改进至`brainstorming`技能,遵循Strunk的"Elements of Style"原则(省略不必要的词语,将否定形式转换为肯定形式,改进平行结构)。 + +### 错误修复 + +* 澄清了`writing-skills`指导,使其指向正确的代理特定个人技能目录(Claude Code的`~/.claude/skills`,Codex的`~/.codex/skills`)。 + +## v3.3.0 (2025-10-28) + +### 新功能 + +**实验性Codex支持** + +* 添加了统一的`superpowers-codex`脚本,包含引导程序/使用技能/查找技能命令 +* 跨平台Node.js实现(适用于Windows、macOS、Linux) +* 命名空间技能:superpowers技能的`superpowers:skill-name`,个人技能的`skill-name` +* 名称匹配时,个人技能覆盖superpowers技能 +* 清晰的技能显示:显示名称/描述,不含原始frontmatter +* 有帮助的上下文:显示每项技能的支持文件目录 +* Codex的工具映射:TodoWrite→update\_plan、subagents→手动回退等 +* 与最小AGENTS.md集成的引导程序,用于自动启动 +* 特定于Codex的完整安装指南和引导程序说明 + +**与Claude Code集成的关键区别:** + +* 单个统一脚本而非独立工具 +* 用于Codex特定等效工具的工具替换系统 +* 简化的子代理处理(手动工作而非委派) +* 更新的术语:"Superpowers技能"替代"核心技能" + +### 新增文件 + +* `.codex/INSTALL.md` - Codex用户的安装指南 +* `.codex/superpowers-bootstrap.md` - 包含Codex适配的引导程序说明 +* `.codex/superpowers-codex` - 包含所有功能的统一Node.js可执行文件 + +**注意:** Codex支持是实验性的。该集成提供了核心的superpowers功能,但可能需要根据用户反馈进行改进。 + +## v3.2.3 (2025-10-23) + +### 改进 + +**更新了using-superpowers技能以使用Skill工具而非Read工具** + +* 将技能调用说明从Read工具更改为Skill工具 +* 更新描述:"使用Read工具" → "使用Skill工具" +* 更新步骤3:"使用Read工具" → "使用Skill工具读取并运行" +* 更新合理化列表:"读取当前版本" → "运行当前版本" + +Skill工具是Claude Code中调用技能的正确机制。此更新更正了引导程序说明,以指导代理使用正确的工具。 + +### 变更的文件 + +* 更新:`skills/using-superpowers/SKILL.md` - 将工具引用从Read更改为Skill + +## v3.2.2 (2025-10-21) + +### 改进 + +**强化了using-superpowers技能以应对代理合理化行为** + +* 添加了包含绝对语言的EXTREMELY-IMPORTANT块,关于强制技能检查 + * "即使只有1%的可能性适用技能,你也必须读取它" + * "你没有选择。你无法合理化地回避。" +* 添加了MANDATORY FIRST RESPONSE PROTOCOL检查清单 + * 代理在做出任何响应前必须完成的5步流程 + * 明确的"未完成此步骤即响应 = 失败"后果 +* 添加了Common Rationalizations部分,包含8种特定的规避模式 + * "这只是一个简单问题" → 错误 + * "我可以快速检查文件" → 错误 + * "让我先收集信息" → 错误 + * 加上另外5种在代理行为中观察到的常见模式 + +这些变更解决了观察到的代理行为,即尽管有明确指示,他们仍会合理化地绕过技能使用。强制的语言和先发制人的反驳旨在使不遵守行为更难发生。 + +### 变更的文件 + +* 更新:`skills/using-superpowers/SKILL.md` - 添加了三层强制措施以防止技能跳过合理化 + +## v3.2.1 (2025-10-20) + +### 新功能 + +**代码评审代理现已包含在插件中** + +* 将`superpowers:code-reviewer`代理添加到插件的`agents/`目录 +* 该代理提供针对计划和编码标准的系统性代码评审 +* 之前要求用户拥有个人代理配置 +* 所有技能引用已更新为使用命名空间的`superpowers:code-reviewer` +* 修复了#55 + +### 变更的文件 + +* 新增:`agents/code-reviewer.md` - 包含评审检查清单和输出格式的代理定义 +* 更新:`skills/requesting-code-review/SKILL.md` - 对`superpowers:code-reviewer`的引用 +* 更新:`skills/subagent-driven-development/SKILL.md` - 对`superpowers:code-reviewer`的引用 + +## v3.2.0 (2025-10-18) + +### 新功能 + +**头脑风暴工作流中的设计文档** + +* 为头脑风暴技能添加了第4阶段:设计文档 +* 设计文档现在在实施前写入`docs/plans/YYYY-MM-DD--design.md` +* 恢复了原始头脑风暴命令在技能转换过程中丢失的功能 +* 在工作树设置和实施计划之前编写文档 +* 通过子代理在时间压力下测试以验证合规性 + +### 破坏性变更 + +**技能引用命名空间标准化** + +* 所有内部技能引用现在使用 `superpowers:` 命名空间前缀 +* 更新后的格式:`superpowers:test-driven-development`(之前仅为 `test-driven-development`) +* 影响所有 REQUIRED SUB-SKILL、RECOMMENDED SUB-SKILL 和 REQUIRED BACKGROUND 引用 +* 与使用 Skill 工具调用技能的方式保持一致 +* 更新的文件:brainstorming、executing-plans、subagent-driven-development、systematic-debugging、testing-skills-with-subagents、writing-plans、writing-skills + +### 改进 + +**设计文档与实现计划命名** + +* 设计文档使用 `-design.md` 后缀以防止文件名冲突 +* 实现计划继续使用现有的 `YYYY-MM-DD-.md` 格式 +* 两者都存储在 `docs/plans/` 目录中,具有清晰的命名区分 + +## v3.1.1 (2025-10-17) + +### 错误修复 + +* **修复了 README 中的命令语法** (#44) - 更新了所有命令引用以使用正确的命名空间语法(`/superpowers:brainstorm` 替代 `/brainstorm`)。插件提供的命令由 Claude Code 自动命名空间化,以避免插件之间的冲突。 + +## v3.1.0 (2025-10-17) + +### 破坏性变更 + +**技能名称标准化为小写** + +* 所有技能 frontmatter `name:` 字段现在使用小写 kebab-case,与目录名称匹配 +* 示例:`brainstorming`、`test-driven-development`、`using-git-worktrees` +* 所有技能公告和交叉引用已更新为小写格式 +* 这确保了目录名称、frontmatter 和文档之间的命名一致性 + +### 新功能 + +**增强的 brainstorming 技能** + +* 添加了显示阶段、活动和工具使用的快速参考表 +* 添加了用于跟踪进度的可复制工作流程清单 +* 添加了用于决定何时重新访问早期阶段的决策流程图 +* 添加了包含具体示例的全面 AskUserQuestion 工具指南 +* 添加了“问题模式”部分,解释何时使用结构化问题与开放式问题 +* 将关键原则重构为可扫描的表格 + +**Anthropic 最佳实践集成** + +* 添加了 `skills/writing-skills/anthropic-best-practices.md` - 官方 Anthropic 技能编写指南 +* 在 writing-skills SKILL.md 中引用以获取全面指导 +* 提供了渐进式披露、工作流程和评估的模式 + +### 改进 + +**技能交叉引用清晰度** + +* 所有技能引用现在使用明确的需求标记: + * `**REQUIRED BACKGROUND:**` - 你必须理解的先决条件 + * `**REQUIRED SUB-SKILL:**` - 必须在工作流程中使用的技能 + * `**Complementary skills:**` - 可选但有用的相关技能 +* 移除了旧的路径格式(`skills/collaboration/X` → 仅为 `X`) +* 使用分类关系(必需与补充)更新了集成部分 +* 使用最佳实践更新了交叉引用文档 + +**与 Anthropic 最佳实践保持一致** + +* 修复了描述语法和语态(完全第三人称) +* 添加了用于扫描的快速参考表 +* 添加了 Claude 可以复制和跟踪的工作流程清单 +* 对非明显决策点适当使用流程图 +* 改进了可扫描的表格格式 +* 所有技能均符合 500 行建议 + +### 错误修复 + +* **重新添加了缺失的命令重定向** - 恢复了在 v3.0 迁移中意外删除的 `commands/brainstorm.md` 和 `commands/write-plan.md` +* 修复了 `defense-in-depth` 名称不匹配问题(原为 `Defense-in-Depth-Validation`) +* 修复了 `receiving-code-review` 名称不匹配问题(原为 `Code-Review-Reception`) +* 修复了 `commands/brainstorm.md` 对正确技能名称的引用 +* 移除了对不存在相关技能的引用 + +### 文档 + +**writing-skills 改进** + +* 使用明确的需求标记更新了交叉引用指南 +* 添加了对 Anthropic 官方最佳实践的引用 +* 改进了显示正确技能引用格式的示例 + +## v3.0.1 (2025-10-16) + +### 变更 + +我们现在使用 Anthropic 的第一方技能系统! + +## v2.0.2 (2025-10-12) + +### 错误修复 + +* **修复了当本地技能仓库领先于上游时的错误警告** - 初始化脚本在本地仓库提交领先于上游时错误地警告“上游有新的技能可用”。逻辑现在正确区分了三种 git 状态:本地落后(应更新)、本地领先(无警告)和分叉(应警告)。 + +## v2.0.1 (2025-10-12) + +### 错误修复 + +* **修复了插件上下文中的 session-start 钩子执行问题** (#8, PR #9) - 该钩子静默失败并显示“插件钩子错误”,阻止了技能上下文的加载。通过以下方式修复: + * 在 Claude Code 执行上下文中 BASH\_SOURCE 未绑定时使用 `${BASH_SOURCE[0]:-$0}` 回退 + * 添加 `|| true` 以在过滤状态标志时优雅处理空的 grep 结果 + +*** + +# Superpowers v2.0.0 发布说明 + +## 概述 + +Superpowers v2.0 通过一次重大的架构转变,使技能更易访问、更易维护且更具社区驱动性。 + +头条变更是**技能仓库分离**:所有技能、脚本和文档已从插件中移出,转移到一个专用仓库([obra/superpowers-skills](https://github.com/obra/superpowers-skills))。这将 superpowers 从一个单体插件转变为一个轻量级垫片,用于管理技能仓库的本地克隆。技能在会话开始时自动更新。用户通过标准的 git 工作流程进行分叉和贡献改进。技能库独立于插件进行版本控制。 + +除了基础设施之外,此版本还添加了九个专注于问题解决、研究和架构的新技能。我们以命令式语调和更清晰的结构重写了核心的 **using-skills** 文档,使 Claude 更容易理解何时以及如何使用技能。**find-skills** 现在输出可以直接粘贴到 Read 工具中的路径,消除了技能发现工作流程中的摩擦。 + +用户体验无缝操作:插件自动处理克隆、分叉和更新。贡献者发现新的架构使得改进和共享技能变得微不足道。此版本为技能作为社区资源快速发展奠定了基础。 + +## 重大变更 + +### 技能仓库分离 + +**最大的变化:** 技能不再存在于插件中。它们已移至位于 [obra/superpowers-skills](https://github.com/obra/superpowers-skills) 的独立仓库。 + +**这对您意味着:** + +* **首次安装:** 插件自动将技能克隆到 `~/.config/superpowers/skills/` +* **分叉:** 在设置过程中,您将获得分叉技能仓库的选项(如果安装了 `gh`) +* **更新:** 技能在会话开始时自动更新(尽可能快进) +* **贡献:** 在分支上工作,本地提交,向上游提交 PR +* **不再有影子系统:** 旧的两层系统(个人/核心)被单一仓库分支工作流程取代 + +**迁移:** + +如果您有现有安装: + +1. 您旧的 `~/.config/superpowers/.git` 将备份到 `~/.config/superpowers/.git.bak` +2. 旧技能将备份到 `~/.config/superpowers/skills.bak` +3. 将在 `~/.config/superpowers/skills/` 处创建 obra/superpowers-skills 的新鲜克隆 + +### 移除的功能 + +* **个人 superpowers 覆盖系统** - 被 git 分支工作流程取代 +* **setup-personal-superpowers 钩子** - 被 initialize-skills.sh 取代 + +## 新功能 + +### 技能仓库基础设施 + +**自动克隆与设置** (`lib/initialize-skills.sh`) + +* 首次运行时克隆 obra/superpowers-skills +* 如果安装了 GitHub CLI,则提供分叉创建选项 +* 正确设置上游/源远程仓库 +* 处理从旧安装的迁移 + +**自动更新** + +* 每次会话开始时从跟踪远程仓库获取 +* 尽可能快进自动合并 +* 需要手动同步时通知(分支分叉) +* 使用 pulling-updates-from-skills-repository 技能进行手动同步 + +### 新技能 + +**问题解决技能** (`skills/problem-solving/`) + +* **collision-zone-thinking** - 强制无关概念碰撞以获得涌现的洞察 +* **inversion-exercise** - 翻转假设以揭示隐藏的约束 +* **meta-pattern-recognition** - 发现跨领域的通用原则 +* **scale-game** - 在极端情况下测试以暴露基本真理 +* **simplification-cascades** - 找到消除多个组件的洞察 +* **when-stuck** - 派遣到正确的问题解决技术 + +**研究技能** (`skills/research/`) + +* **tracing-knowledge-lineages** - 理解想法如何随时间演变 + +**架构技能** (`skills/architecture/`) + +* **preserving-productive-tensions** - 保持多种有效方法,而不是强制过早解决 + +### 技能改进 + +**using-skills(原 getting-started)** + +* 从 getting-started 重命名为 using-skills +* 使用命令式语调完全重写 (v4.0.0) +* 前置关键规则 +* 为所有工作流程添加了“为什么”解释 +* 引用中始终包含 /SKILL.md 后缀 +* 更清晰地区分严格规则和灵活模式 + +**writing-skills** + +* 交叉引用指南从 using-skills 移出 +* 添加了令牌效率部分(字数目标) +* 改进了 CSO(Claude 搜索优化)指南 + +**sharing-skills** + +* 更新为新的分支和 PR 工作流程 (v2.0.0) +* 移除了个人/核心分离引用 + +**pulling-updates-from-skills-repository(新)** + +* 与上游同步的完整工作流程 +* 取代了旧的“updating-skills”技能 + +### 工具改进 + +**find-skills** + +* 现在输出带有 /SKILL.md 后缀的完整路径 +* 使路径可直接与 Read 工具一起使用 +* 更新了帮助文本 + +**skill-run** + +* 从 scripts/ 移动到 skills/using-skills/ +* 改进了文档 + +### 插件基础设施 + +**会话开始钩子** + +* 现在从技能仓库位置加载 +* 在会话开始时显示完整的技能列表 +* 打印技能位置信息 +* 显示更新状态(成功更新 / 落后于上游) +* 将“技能落后”警告移至输出末尾 + +**环境变量** + +* `SUPERPOWERS_SKILLS_ROOT` 设置为 `~/.config/superpowers/skills` +* 在所有路径中一致使用 + +## 错误修复 + +* 修复了分叉时重复添加上游远程仓库的问题 +* 修复了 find-skills 输出中双“skills/”前缀的问题 +* 从 session-start 中移除了过时的 setup-personal-superpowers 调用 +* 修复了整个钩子和命令中的路径引用 + +## 文档 + +### README + +* 更新为新的技能仓库架构 +* 显著链接到 superpowers-skills 仓库 +* 更新了自动更新描述 +* 修复了技能名称和引用 +* 更新了元技能列表 + +### 测试文档 + +* 添加了全面的测试清单 (`docs/TESTING-CHECKLIST.md`) +* 为测试创建了本地市场配置 +* 记录了手动测试场景 + +## 技术细节 + +### 文件变更 + +**添加:** + +* `lib/initialize-skills.sh` - 技能仓库初始化和自动更新 +* `docs/TESTING-CHECKLIST.md` - 手动测试场景 +* `.claude-plugin/marketplace.json` - 本地测试配置 + +**移除:** + +* `skills/` 目录(82 个文件)- 现在位于 obra/superpowers-skills +* `scripts/` 目录 - 现在位于 obra/superpowers-skills/skills/using-skills/ +* `hooks/setup-personal-superpowers.sh` - 已过时 + +**修改:** + +* `hooks/session-start.sh` - 使用来自 ~/.config/superpowers/skills 的技能 +* `commands/brainstorm.md` - 更新路径至 SUPERPOWERS\_SKILLS\_ROOT +* `commands/write-plan.md` - 更新路径至 SUPERPOWERS\_SKILLS\_ROOT +* `commands/execute-plan.md` - 更新路径至 SUPERPOWERS\_SKILLS\_ROOT +* `README.md` - 为新架构完全重写 + +### 提交历史 + +此版本包括: + +* 20+ 次提交用于技能仓库分离 +* PR #1:受放大器启发的问题解决和研究技能 +* PR #2:个人 superpowers 覆盖系统(后来被取代) +* 多次技能细化和文档改进 + +## 升级说明 + +### 全新安装 + +```bash +# In Claude Code +/plugin marketplace add obra/superpowers-marketplace +/plugin install superpowers@superpowers-marketplace +``` + +插件自动处理一切。 + +### 从 v1.x 升级 + +1. **备份您的个人技能**(如果有的话): + ```bash + cp -r ~/.config/superpowers/skills ~/superpowers-skills-backup + ``` + +2. **更新插件:** + ```bash + /plugin update superpowers + ``` + +3. **在下一次会话开始时:** + * 旧安装将自动备份 + * 将克隆全新的技能仓库 + * 如果你有 GitHub CLI,系统将提供 fork 选项 + +4. **迁移个人技能**(如果你有的话): + * 在本地技能仓库中创建一个分支 + * 从备份中复制你的个人技能 + * 提交并推送到你的 fork + * 考虑通过 PR 回馈社区 + +## 下一步 + +### 对于用户 + +* 探索新的问题解决技能 +* 尝试基于分支的工作流来改进技能 +* 将技能贡献回社区 + +### 对于贡献者 + +* 技能仓库现位于 https://github.com/obra/superpowers-skills +* 采用 Fork → 分支 → PR 的工作流 +* 查看 skills/meta/writing-skills/SKILL.md 了解文档的 TDD 方法 + +## 已知问题 + +目前没有。 + +## 致谢 + +* 问题解决技能灵感来源于 Amplifier 模式 +* 社区贡献和反馈 +* 对技能有效性进行了广泛的测试和迭代 + +*** + +**完整更新日志:** https://github.com/obra/superpowers/compare/dd013f6...main +**技能仓库:** https://github.com/obra/superpowers-skills +**问题反馈:** https://github.com/obra/superpowers/issues diff --git a/zh-CN/agents/code-reviewer.md b/zh-CN/agents/code-reviewer.md new file mode 100644 index 0000000000..d068cb2033 --- /dev/null +++ b/zh-CN/agents/code-reviewer.md @@ -0,0 +1,47 @@ +--- +name: code-reviewer +description: 当主要项目步骤已完成,需要对照原始计划和编码标准进行审查时,请使用此代理。示例:上下文:用户正在创建一个代码审查代理,该代理应在编写完逻辑代码块后被调用。用户:“我已按照计划第3步完成了用户身份验证系统的实现” 助手:“干得好!现在让我使用代码审查代理来对照我们的计划和编码标准审查此实现” 由于主要项目步骤已完成,使用代码审查代理来验证工作是否符合计划并识别任何问题。 上下文:用户已完成一个重要功能实现。用户:“任务管理系统的API端点现已完成——这涵盖了架构文档中的第2步” 助手:“太好了!让我请代码审查代理检查此实现,以确保其符合我们的计划并遵循最佳实践” 计划文档中的一个编号步骤已完成,因此应使用代码审查代理审查工作。 +model: inherit +--- + +你是一位资深代码审查员,在软件架构、设计模式和最佳实践方面拥有专业知识。你的职责是根据原始计划审查已完成的项目步骤,并确保代码质量达标。 + +在审查已完成的工作时,你将: + +1. **计划对齐分析**: + * 将实现与原始规划文档或步骤描述进行对比 + * 识别与计划方法、架构或要求的任何偏差 + * 评估偏差是合理的改进还是有问题的偏离 + * 验证所有计划的功能是否已实现 + +2. **代码质量评估**: + * 审查代码是否遵循既定模式和约定 + * 检查是否正确处理错误、类型安全以及防御性编程 + * 评估代码组织、命名约定和可维护性 + * 评估测试覆盖率和测试实现的质量 + * 寻找潜在的安全漏洞或性能问题 + +3. **架构与设计审查**: + * 确保实现遵循 SOLID 原则和既定的架构模式 + * 检查是否实现了适当的关注点分离和松耦合 + * 验证代码与现有系统的集成是否良好 + * 评估可扩展性和可扩展性方面的考量 + +4. **文档与标准**: + * 验证代码是否包含适当的注释和文档 + * 检查文件头、函数文档和内联注释是否存在且准确 + * 确保遵守项目特定的编码标准和约定 + +5. **问题识别与建议**: + * 将问题明确分类为:关键(必须修复)、重要(应该修复)或建议(最好有) + * 针对每个问题,提供具体示例和可操作的建议 + * 当识别出计划偏差时,解释其是有问题的还是有益的 + * 在必要时,提供包含代码示例的具体改进建议 + +6. **沟通协议**: + * 如果发现与计划存在重大偏差,请要求编码代理审查并确认更改 + * 如果发现原始计划本身存在问题,建议更新计划 + * 对于实现问题,提供关于所需修复的明确指导 + * 在强调问题之前,始终先肯定做得好的方面 + +你的输出应具有结构性、可操作性,并专注于帮助维持高代码质量,同时确保项目目标达成。要做到彻底但简洁,始终提供建设性反馈,以帮助改进当前实现和未来的开发实践。 diff --git a/zh-CN/commands/brainstorm.md b/zh-CN/commands/brainstorm.md new file mode 100644 index 0000000000..ab1b54110d --- /dev/null +++ b/zh-CN/commands/brainstorm.md @@ -0,0 +1,5 @@ +--- +description: "已弃用 - 请改用 superpowers:头脑风暴技能" +--- + +告诉你的合作伙伴,这个命令已被弃用,并将在下一个主要版本中移除。他们应该要求你使用“superpowers 头脑风暴”技能代替。 diff --git a/zh-CN/commands/execute-plan.md b/zh-CN/commands/execute-plan.md new file mode 100644 index 0000000000..d827d82f37 --- /dev/null +++ b/zh-CN/commands/execute-plan.md @@ -0,0 +1,5 @@ +--- +description: "已弃用 - 请改用 superpowers:executing-plans 技能" +--- + +告诉你的合作伙伴,这个命令已被弃用,并将在下一个主要版本中移除。他们应该要求你使用“superpowers executing-plans”技能来代替。 diff --git a/zh-CN/commands/write-plan.md b/zh-CN/commands/write-plan.md new file mode 100644 index 0000000000..a1d81c49ba --- /dev/null +++ b/zh-CN/commands/write-plan.md @@ -0,0 +1,5 @@ +--- +description: "已弃用 - 请改用 superpowers:writing-plans 技能" +--- + +告诉你的合作伙伴,这个命令已被弃用,并将在下一个主要版本中移除。他们应该要求你使用 "superpowers writing-plans" 技能。 diff --git a/zh-CN/docs/README.codex.md b/zh-CN/docs/README.codex.md new file mode 100644 index 0000000000..a92a74ef47 --- /dev/null +++ b/zh-CN/docs/README.codex.md @@ -0,0 +1,128 @@ +# Superpowers for Codex + +使用原生技能发现功能,通过 OpenAI Codex 使用 Superpowers 的指南。 + +## 快速安装 + +告诉 Codex: + +``` +从 https://raw.githubusercontent.com/obra/superpowers/refs/heads/main/.codex/INSTALL.md 获取并遵循指令 +``` + +## 手动安装 + +### 先决条件 + +* OpenAI Codex CLI +* Git + +### 步骤 + +1. 克隆仓库: + ```bash + git clone https://github.com/obra/superpowers.git ~/.codex/superpowers + ``` + +2. 创建技能符号链接: + ```bash + mkdir -p ~/.agents/skills + ln -s ~/.codex/superpowers/skills ~/.agents/skills/superpowers + ``` + +3. 重启 Codex。 + +4. **对于子代理技能**(可选):诸如 `dispatching-parallel-agents` 和 `subagent-driven-development` 这类技能需要 Codex 的多代理功能。请将以下内容添加到你的 Codex 配置中: + ```toml + [features] + multi_agent = true + ``` + +### Windows + +使用连接点代替符号链接(无需开发者模式): + +```powershell +New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.agents\skills" +cmd /c mklink /J "$env:USERPROFILE\.agents\skills\superpowers" "$env:USERPROFILE\.codex\superpowers\skills" +``` + +## 工作原理 + +Codex 具有原生技能发现功能——它在启动时扫描 `~/.agents/skills/`,解析 SKILL.md 的前置元数据,并按需加载技能。Superpowers 技能通过单个符号链接变得可见: + +``` +~/.agents/skills/superpowers/ → ~/.codex/superpowers/skills/ +``` + +`using-superpowers` 技能会被自动发现,并强制执行技能使用规范——无需额外配置。 + +## 使用 + +技能会被自动发现。Codex 在以下情况下激活它们: + +* 你按名称提及一个技能(例如,“使用 brainstorming”) +* 任务与某个技能的描述匹配 +* `using-superpowers` 技能指示 Codex 使用某个技能 + +### 个人技能 + +在 `~/.agents/skills/` 中创建你自己的技能: + +```bash +mkdir -p ~/.agents/skills/my-skill +``` + +创建 `~/.agents/skills/my-skill/SKILL.md`: + +```markdown +--- +name: my-skill +description: Use when [condition] - [what it does] +--- + +# 我的技能 + +[你的技能内容在这里] +``` + +`description` 字段是 Codex 决定何时自动激活技能的依据——将其写成一个清晰的触发条件。 + +## 更新 + +```bash +cd ~/.codex/superpowers && git pull +``` + +技能通过符号链接即时更新。 + +## 卸载 + +```bash +rm ~/.agents/skills/superpowers +``` + +**Windows (PowerShell):** + +```powershell +Remove-Item "$env:USERPROFILE\.agents\skills\superpowers" +``` + +可选择删除克隆的仓库:`rm -rf ~/.codex/superpowers`(Windows:`Remove-Item -Recurse -Force "$env:USERPROFILE\.codex\superpowers"`)。 + +## 故障排除 + +### 技能未显示 + +1. 验证符号链接:`ls -la ~/.agents/skills/superpowers` +2. 检查技能是否存在:`ls ~/.codex/superpowers/skills` +3. 重启 Codex——技能在启动时被发现 + +### Windows 连接点问题 + +连接点通常无需特殊权限即可工作。如果创建失败,请尝试以管理员身份运行 PowerShell。 + +## 获取帮助 + +* 报告问题:https://github.com/obra/superpowers/issues +* 主要文档:https://github.com/obra/superpowers diff --git a/zh-CN/docs/README.opencode.md b/zh-CN/docs/README.opencode.md new file mode 100644 index 0000000000..3e5cd75db2 --- /dev/null +++ b/zh-CN/docs/README.opencode.md @@ -0,0 +1,130 @@ +# OpenCode 的 Superpowers + +与 [OpenCode.ai](https://opencode.ai) 一起使用 Superpowers 的完整指南。 + +## 安装 + +将 superpowers 添加到你的 `opencode.json`(全局或项目级)中的 `plugin` 数组: + +```json +{ + "plugin": ["superpowers@git+https://github.com/obra/superpowers.git"] +} +``` + +重启 OpenCode。插件将通过 Bun 自动安装并自动注册所有技能。 + +通过询问以下内容进行验证:“告诉我关于你的 superpowers” + +### 从旧的基于符号链接的安装迁移 + +如果你之前使用 `git clone` 和符号链接安装了 superpowers,请移除旧设置: + +```bash +# Remove old symlinks +rm -f ~/.config/opencode/plugins/superpowers.js +rm -rf ~/.config/opencode/skills/superpowers + +# Optionally remove the cloned repo +rm -rf ~/.config/opencode/superpowers + +# Remove skills.paths from opencode.json if you added one for superpowers +``` + +然后按照上述安装步骤操作。 + +## 使用 + +### 查找技能 + +使用 OpenCode 原生的 `skill` 工具列出所有可用技能: + +``` +使用技能工具来列出技能 +``` + +### 加载技能 + +``` +使用技能工具加载 superpowers/brainstorming +``` + +### 个人技能 + +在 `~/.config/opencode/skills/` 中创建您自己的技能: + +```bash +mkdir -p ~/.config/opencode/skills/my-skill +``` + +创建 `~/.config/opencode/skills/my-skill/SKILL.md`: + +```markdown +--- +name: my-skill +description: Use when [condition] - [what it does] +--- + +# 我的技能 + +[你的技能内容在此] +``` + +### 项目技能 + +在你的项目中,于 `.opencode/skills/` 内创建项目特定技能。 + +**技能优先级:** 项目技能 > 个人技能 > Superpowers 技能 + +## 更新 + +Superpowers 在你重启 OpenCode 时会自动更新。插件在每次启动时都会从 git 仓库重新安装。 + +要固定特定版本,请使用分支或标签: + +```json +{ + "plugin": ["superpowers@git+https://github.com/obra/superpowers.git#v5.0.3"] +} +``` + +## 工作原理 + +该插件执行两项操作: + +1. **通过 `experimental.chat.system.transform` 钩子注入引导上下文**,为每次对话添加 superpowers 感知。 +2. **通过 `config` 钩子注册技能目录**,以便 OpenCode 无需符号链接或手动配置即可发现所有 superpowers 技能。 + +### 工具映射 + +为 Claude Code 编写的技能会自动适配到 OpenCode: + +* `TodoWrite` → `todowrite` +* 带有子代理的 `Task` → OpenCode 的 `@mention` 系统 +* `Skill` 工具 → OpenCode 原生的 `skill` 工具 +* 文件操作 → 原生 OpenCode 工具 + +## 故障排除 + +### 插件未加载 + +1. 检查 OpenCode 日志:`opencode run --print-logs "hello" 2>&1 | grep -i superpowers` +2. 验证你的 `opencode.json` 中的插件行是否正确 +3. 确保你运行的是最新版本的 OpenCode + +### 技能未找到 + +1. 使用 OpenCode 的 `skill` 工具列出可用技能 +2. 检查插件是否正在加载(见上文) +3. 每个技能都需要一个带有有效 YAML 前置元数据的 `SKILL.md` 文件 + +### 引导程序未出现 + +1. 检查 OpenCode 版本是否支持 `experimental.chat.system.transform` 钩子 +2. 在配置更改后重启 OpenCode + +## 获取帮助 + +* 报告问题:https://github.com/obra/superpowers/issues +* 主要文档:https://github.com/obra/superpowers +* OpenCode 文档:https://opencode.ai/docs/ diff --git a/zh-CN/docs/plans/2025-11-22-opencode-support-design.md b/zh-CN/docs/plans/2025-11-22-opencode-support-design.md new file mode 100644 index 0000000000..c443c171ad --- /dev/null +++ b/zh-CN/docs/plans/2025-11-22-opencode-support-design.md @@ -0,0 +1,294 @@ +# OpenCode 支持设计 + +**日期:** 2025-11-22 +**作者:** Bot & Jesse +**状态:** 设计完成,待实施 + +## 概述 + +通过使用与现有 Codex 实现共享核心功能的本机 OpenCode 插件架构,为 OpenCode.ai 添加完整的 superpowers 支持。 + +## 背景 + +OpenCode.ai 是一个类似于 Claude Code 和 Codex 的编码代理。之前将 superpowers 移植到 OpenCode 的尝试(PR #93, PR #116)使用了文件复制方法。本设计采用不同的方法:使用 OpenCode 的 JavaScript/TypeScript 插件系统构建一个本机 OpenCode 插件,同时与 Codex 实现共享代码。 + +### 平台间的关键差异 + +* **Claude Code**:本机 Anthropic 插件系统 + 基于文件的技能 +* **Codex**:无插件系统 → 引导式 markdown + CLI 脚本 +* **OpenCode**:具有事件钩子和自定义工具 API 的 JavaScript/TypeScript 插件 + +### OpenCode 的代理系统 + +* **主要代理**:构建(默认,完全访问)和计划(受限,只读) +* **子代理**:通用(研究、搜索、多步骤任务) +* **调用方式**:由主要代理自动分派 或 手动 `@mention` 语法 +* **配置**:在 `opencode.json` 或 `~/.config/opencode/agent/` 中配置自定义代理 + +## 架构 + +### 高层次结构 + +1. **共享核心模块** (`lib/skills-core.js`) + * 通用的技能发现和解析逻辑 + * 由 Codex 和 OpenCode 实现共同使用 + +2. **平台特定包装器** + * Codex:CLI 脚本 (`.codex/superpowers-codex`) + * OpenCode:插件模块 (`.opencode/plugin/superpowers.js`) + +3. **技能目录** + * 核心:`~/.config/opencode/superpowers/skills/`(或安装位置) + * 个人:`~/.config/opencode/skills/`(覆盖核心技能) + +### 代码复用策略 + +从 `.codex/superpowers-codex` 中提取通用功能到共享模块: + +```javascript +// lib/skills-core.js +module.exports = { + extractFrontmatter(filePath), // Parse name + description from YAML + findSkillsInDir(dir, maxDepth), // Recursive SKILL.md discovery + findAllSkills(dirs), // Scan multiple directories + resolveSkillPath(skillName, dirs), // Handle shadowing (personal > core) + checkForUpdates(repoDir) // Git fetch/status check +}; +``` + +### 技能 Frontmatter 格式 + +当前格式(无 `when_to_use` 字段): + +```yaml +--- +name: skill-name +description: Use when [condition] - [what it does]; [additional context] +--- +``` + +## OpenCode 插件实现 + +### 自定义工具 + +**工具 1:`use_skill`** + +将特定技能的内容加载到对话中(相当于 Claude 的 Skill 工具)。 + +```javascript +{ + name: 'use_skill', + description: 'Load and read a specific skill to guide your work', + schema: z.object({ + skill_name: z.string().describe('Name of skill (e.g., "superpowers:brainstorming")') + }), + execute: async ({ skill_name }) => { + const { skillPath, content, frontmatter } = resolveAndReadSkill(skill_name); + const skillDir = path.dirname(skillPath); + + return `# ${frontmatter.name} +# ${frontmatter.description} +# Supporting tools and docs are in ${skillDir} +# ============================================ + +${content}`; + } +} +``` + +**工具 2:`find_skills`** + +列出所有可用技能及其元数据。 + +```javascript +{ + name: 'find_skills', + description: 'List all available skills', + schema: z.object({}), + execute: async () => { + const skills = discoverAllSkills(); + return skills.map(s => + `${s.namespace}:${s.name} + ${s.description} + Directory: ${s.directory} +`).join('\n'); + } +} +``` + +### 会话启动钩子 + +当新会话开始时(`session.started` 事件): + +1. **注入 using-superpowers 内容** + * using-superpowers 技能的全部内容 + * 建立强制性的工作流程 + +2. **自动运行 find\_skills** + * 预先显示完整的可用技能列表 + * 包含每个技能的目录 + +3. **注入工具映射说明** + ```markdown + **OpenCode 工具映射:** + 当技能引用你未拥有的工具时,请替换为: + - `TodoWrite` → `update_plan` + - 带有子代理的 `Task` → 使用 OpenCode 子代理系统(@提及) + - `Skill` 工具 → `use_skill` 自定义工具 + - Read、Write、Edit、Bash → 你的本机等效工具 + + **技能目录包含:** + - 支持脚本(使用 bash 运行) + - 附加文档(使用 read 工具读取) + - 该技能特定的实用程序 + ``` + +4. **检查更新**(非阻塞) + * 带超时的快速 git fetch + * 如有可用更新则通知 + +### 插件结构 + +```javascript +// .opencode/plugin/superpowers.js +const skillsCore = require('../../lib/skills-core'); +const path = require('path'); +const fs = require('fs'); +const { z } = require('zod'); + +export const SuperpowersPlugin = async ({ client, directory, $ }) => { + const superpowersDir = path.join(process.env.HOME, '.config/opencode/superpowers'); + const personalDir = path.join(process.env.HOME, '.config/opencode/skills'); + + return { + 'session.started': async () => { + const usingSuperpowers = await readSkill('using-superpowers'); + const skillsList = await findAllSkills(); + const toolMapping = getToolMappingInstructions(); + + return { + context: `${usingSuperpowers}\n\n${skillsList}\n\n${toolMapping}` + }; + }, + + tools: [ + { + name: 'use_skill', + description: 'Load and read a specific skill', + schema: z.object({ + skill_name: z.string() + }), + execute: async ({ skill_name }) => { + // Implementation using skillsCore + } + }, + { + name: 'find_skills', + description: 'List all available skills', + schema: z.object({}), + execute: async () => { + // Implementation using skillsCore + } + } + ] + }; +}; +``` + +## 文件结构 + +``` +superpowers/ +├── lib/ +│ └── skills-core.js # 新增:共享技能逻辑 +├── .codex/ +│ ├── superpowers-codex # 已更新:使用 skills-core +│ ├── superpowers-bootstrap.md +│ └── INSTALL.md +├── .opencode/ +│ ├── plugin/ +│ │ └── superpowers.js # 新增:OpenCode 插件 +│ └── INSTALL.md # 新增:安装指南 +└── skills/ # 未更改 +``` + +## 实施计划 + +### 阶段 1:重构共享核心 + +1. 创建 `lib/skills-core.js` + * 从 `.codex/superpowers-codex` 中提取 frontmatter 解析逻辑 + * 提取技能发现逻辑 + * 提取路径解析逻辑(含覆盖机制) + * 更新为仅使用 `name` 和 `description`(不使用 `when_to_use`) + +2. 更新 `.codex/superpowers-codex` 以使用共享核心 + * 从 `../lib/skills-core.js` 导入 + * 移除重复代码 + * 保留 CLI 包装器逻辑 + +3. 测试 Codex 实现是否仍然有效 + * 验证 bootstrap 命令 + * 验证 use-skill 命令 + * 验证 find-skills 命令 + +### 阶段 2:构建 OpenCode 插件 + +1. 创建 `.opencode/plugin/superpowers.js` + * 从 `../../lib/skills-core.js` 导入共享核心 + * 实现插件函数 + * 定义自定义工具(use\_skill, find\_skills) + * 实现 session.started 钩子 + +2. 创建 `.opencode/INSTALL.md` + * 安装说明 + * 目录设置 + * 配置指南 + +3. 测试 OpenCode 实现 + * 验证会话启动引导 + * 验证 use\_skill 工具工作正常 + * 验证 find\_skills 工具工作正常 + * 验证技能目录可访问 + +### 阶段 3:文档与完善 + +1. 更新 README,包含 OpenCode 支持 +2. 在主文档中添加 OpenCode 安装说明 +3. 更新 RELEASE-NOTES +4. 测试 Codex 和 OpenCode 是否都能正常工作 + +## 后续步骤 + +1. **创建独立工作区**(使用 git worktrees) + * 分支:`feature/opencode-support` + +2. **在适用处遵循 TDD** + * 测试共享核心函数 + * 测试技能发现和解析 + * 两个平台的集成测试 + +3. **增量实施** + * 阶段 1:重构共享核心 + 更新 Codex + * 继续之前验证 Codex 是否仍有效 + * 阶段 2:构建 OpenCode 插件 + * 阶段 3:文档与完善 + +4. **测试策略** + * 使用真实的 OpenCode 安装进行手动测试 + * 验证技能加载、目录、脚本正常工作 + * 并排测试 Codex 和 OpenCode + * 验证工具映射正常工作 + +5. **PR 与合并** + * 创建包含完整实现的 PR + * 在干净环境中测试 + * 合并到主分支 + +## 优势 + +* **代码复用**:技能发现/解析的单一事实来源 +* **可维护性**:错误修复适用于两个平台 +* **可扩展性**:易于添加未来平台(Cursor、Windsurf 等) +* **本机集成**:正确使用 OpenCode 的插件系统 +* **一致性**:在所有平台上获得相同的技能体验 diff --git a/zh-CN/docs/plans/2025-11-22-opencode-support-implementation.md b/zh-CN/docs/plans/2025-11-22-opencode-support-implementation.md new file mode 100644 index 0000000000..c6d505fe42 --- /dev/null +++ b/zh-CN/docs/plans/2025-11-22-opencode-support-implementation.md @@ -0,0 +1,1119 @@ +# OpenCode 支持实施计划 + +> **对于代理工作者:** 必需子技能:使用 superpowers:executing-plans 来逐任务实施此计划。 + +**目标:** 为 OpenCode.ai 添加完整的 superpowers 支持,使用一个与现有 Codex 实现共享核心功能的原生 JavaScript 插件。 + +**架构:** 将通用技能发现/解析逻辑提取到 `lib/skills-core.js` 中,重构 Codex 以使用它,然后使用其原生插件 API 以及自定义工具和会话钩子构建 OpenCode 插件。 + +**技术栈:** Node.js, JavaScript, OpenCode 插件 API, Git worktrees + +*** + +## 阶段 1:创建共享核心模块 + +### 任务 1:提取 Frontmatter 解析 + +**文件:** + +* 创建:`lib/skills-core.js` +* 参考:`.codex/superpowers-codex` (第 40-74 行) + +**步骤 1:创建 lib/skills-core.js 并包含 extractFrontmatter 函数** + +```javascript +#!/usr/bin/env node + +const fs = require('fs'); +const path = require('path'); + +/** + * Extract YAML frontmatter from a skill file. + * Current format: + * --- + * name: skill-name + * description: Use when [condition] - [what it does] + * --- + * + * @param {string} filePath - Path to SKILL.md file + * @returns {{name: string, description: string}} + */ +function extractFrontmatter(filePath) { + try { + const content = fs.readFileSync(filePath, 'utf8'); + const lines = content.split('\n'); + + let inFrontmatter = false; + let name = ''; + let description = ''; + + for (const line of lines) { + if (line.trim() === '---') { + if (inFrontmatter) break; + inFrontmatter = true; + continue; + } + + if (inFrontmatter) { + const match = line.match(/^(\w+):\s*(.*)$/); + if (match) { + const [, key, value] = match; + switch (key) { + case 'name': + name = value.trim(); + break; + case 'description': + description = value.trim(); + break; + } + } + } + } + + return { name, description }; + } catch (error) { + return { name: '', description: '' }; + } +} + +module.exports = { + extractFrontmatter +}; +``` + +**步骤 2:验证文件已创建** + +运行:`ls -l lib/skills-core.js` +预期:文件存在 + +**步骤 3:提交** + +```bash +git add lib/skills-core.js +git commit -m "feat: create shared skills core module with frontmatter parser" +``` + +*** + +### 任务 2:提取技能发现逻辑 + +**文件:** + +* 修改:`lib/skills-core.js` +* 参考:`.codex/superpowers-codex` (第 97-136 行) + +**步骤 1:向 skills-core.js 添加 findSkillsInDir 函数** + +在 `module.exports` 之前添加: + +```javascript +/** + * Find all SKILL.md files in a directory recursively. + * + * @param {string} dir - Directory to search + * @param {string} sourceType - 'personal' or 'superpowers' for namespacing + * @param {number} maxDepth - Maximum recursion depth (default: 3) + * @returns {Array<{path: string, name: string, description: string, sourceType: string}>} + */ +function findSkillsInDir(dir, sourceType, maxDepth = 3) { + const skills = []; + + if (!fs.existsSync(dir)) return skills; + + function recurse(currentDir, depth) { + if (depth > maxDepth) return; + + const entries = fs.readdirSync(currentDir, { withFileTypes: true }); + + for (const entry of entries) { + const fullPath = path.join(currentDir, entry.name); + + if (entry.isDirectory()) { + // Check for SKILL.md in this directory + const skillFile = path.join(fullPath, 'SKILL.md'); + if (fs.existsSync(skillFile)) { + const { name, description } = extractFrontmatter(skillFile); + skills.push({ + path: fullPath, + skillFile: skillFile, + name: name || entry.name, + description: description || '', + sourceType: sourceType + }); + } + + // Recurse into subdirectories + recurse(fullPath, depth + 1); + } + } + } + + recurse(dir, 0); + return skills; +} +``` + +**步骤 2:更新 module.exports** + +替换导出行为: + +```javascript +module.exports = { + extractFrontmatter, + findSkillsInDir +}; +``` + +**步骤 3:验证语法** + +运行:`node -c lib/skills-core.js` +预期:无输出(成功) + +**步骤 4:提交** + +```bash +git add lib/skills-core.js +git commit -m "feat: add skill discovery function to core module" +``` + +*** + +### 任务 3:提取技能解析逻辑 + +**文件:** + +* 修改:`lib/skills-core.js` +* 参考:`.codex/superpowers-codex` (第 212-280 行) + +**步骤 1:添加 resolveSkillPath 函数** + +在 `module.exports` 之前添加: + +```javascript +/** + * Resolve a skill name to its file path, handling shadowing + * (personal skills override superpowers skills). + * + * @param {string} skillName - Name like "superpowers:brainstorming" or "my-skill" + * @param {string} superpowersDir - Path to superpowers skills directory + * @param {string} personalDir - Path to personal skills directory + * @returns {{skillFile: string, sourceType: string, skillPath: string} | null} + */ +function resolveSkillPath(skillName, superpowersDir, personalDir) { + // Strip superpowers: prefix if present + const forceSuperpowers = skillName.startsWith('superpowers:'); + const actualSkillName = forceSuperpowers ? skillName.replace(/^superpowers:/, '') : skillName; + + // Try personal skills first (unless explicitly superpowers:) + if (!forceSuperpowers && personalDir) { + const personalPath = path.join(personalDir, actualSkillName); + const personalSkillFile = path.join(personalPath, 'SKILL.md'); + if (fs.existsSync(personalSkillFile)) { + return { + skillFile: personalSkillFile, + sourceType: 'personal', + skillPath: actualSkillName + }; + } + } + + // Try superpowers skills + if (superpowersDir) { + const superpowersPath = path.join(superpowersDir, actualSkillName); + const superpowersSkillFile = path.join(superpowersPath, 'SKILL.md'); + if (fs.existsSync(superpowersSkillFile)) { + return { + skillFile: superpowersSkillFile, + sourceType: 'superpowers', + skillPath: actualSkillName + }; + } + } + + return null; +} +``` + +**步骤 2:更新 module.exports** + +```javascript +module.exports = { + extractFrontmatter, + findSkillsInDir, + resolveSkillPath +}; +``` + +**步骤 3:验证语法** + +运行:`node -c lib/skills-core.js` +预期:无输出 + +**步骤 4:提交** + +```bash +git add lib/skills-core.js +git commit -m "feat: add skill path resolution with shadowing support" +``` + +*** + +### 任务 4:提取更新检查逻辑 + +**文件:** + +* 修改:`lib/skills-core.js` +* 参考:`.codex/superpowers-codex` (第 16-38 行) + +**步骤 1:添加 checkForUpdates 函数** + +在顶部 require 之后添加: + +```javascript +const { execSync } = require('child_process'); +``` + +在 `module.exports` 之前添加: + +```javascript +/** + * Check if a git repository has updates available. + * + * @param {string} repoDir - Path to git repository + * @returns {boolean} - True if updates are available + */ +function checkForUpdates(repoDir) { + try { + // Quick check with 3 second timeout to avoid delays if network is down + const output = execSync('git fetch origin && git status --porcelain=v1 --branch', { + cwd: repoDir, + timeout: 3000, + encoding: 'utf8', + stdio: 'pipe' + }); + + // Parse git status output to see if we're behind + const statusLines = output.split('\n'); + for (const line of statusLines) { + if (line.startsWith('## ') && line.includes('[behind ')) { + return true; // We're behind remote + } + } + return false; // Up to date + } catch (error) { + // Network down, git error, timeout, etc. - don't block bootstrap + return false; + } +} +``` + +**步骤 2:更新 module.exports** + +```javascript +module.exports = { + extractFrontmatter, + findSkillsInDir, + resolveSkillPath, + checkForUpdates +}; +``` + +**步骤 3:验证语法** + +运行:`node -c lib/skills-core.js` +预期:无输出 + +**步骤 4:提交** + +```bash +git add lib/skills-core.js +git commit -m "feat: add git update checking to core module" +``` + +*** + +## 阶段 2:重构 Codex 以使用共享核心 + +### 任务 5:更新 Codex 以导入共享核心 + +**文件:** + +* 修改:`.codex/superpowers-codex` (在顶部添加导入) + +**步骤 1:添加导入语句** + +在文件顶部现有的 require 之后(大约第 6 行),添加: + +```javascript +const skillsCore = require('../lib/skills-core'); +``` + +**步骤 2:验证语法** + +运行:`node -c .codex/superpowers-codex` +预期:无输出 + +**步骤 3:提交** + +```bash +git add .codex/superpowers-codex +git commit -m "refactor: import shared skills core in codex" +``` + +*** + +### 任务 6:将 extractFrontmatter 替换为核心版本 + +**文件:** + +* 修改:`.codex/superpowers-codex` (第 40-74 行) + +**步骤 1:移除本地的 extractFrontmatter 函数** + +删除第 40-74 行(整个 extractFrontmatter 函数定义)。 + +**步骤 2:更新所有 extractFrontmatter 调用** + +查找并替换所有调用,从 `extractFrontmatter(` 到 `skillsCore.extractFrontmatter(` + +受影响的代码行大约在:90, 310 + +**步骤 3:验证脚本仍然工作** + +运行:`.codex/superpowers-codex find-skills | head -20` +预期:显示技能列表 + +**步骤 4:提交** + +```bash +git add .codex/superpowers-codex +git commit -m "refactor: use shared extractFrontmatter in codex" +``` + +*** + +### 任务 7:将 findSkillsInDir 替换为核心版本 + +**文件:** + +* 修改:`.codex/superpowers-codex` (大约第 97-136 行) + +**步骤 1:移除本地的 findSkillsInDir 函数** + +删除整个 `findSkillsInDir` 函数定义(大约第 97-136 行)。 + +**步骤 2:更新所有 findSkillsInDir 调用** + +将调用从 `findSkillsInDir(` 替换为 `skillsCore.findSkillsInDir(` + +**步骤 3:验证脚本仍然工作** + +运行:`.codex/superpowers-codex find-skills | head -20` +预期:显示技能列表 + +**步骤 4:提交** + +```bash +git add .codex/superpowers-codex +git commit -m "refactor: use shared findSkillsInDir in codex" +``` + +*** + +### 任务 8:将 checkForUpdates 替换为核心版本 + +**文件:** + +* 修改:`.codex/superpowers-codex` (大约第 16-38 行) + +**步骤 1:移除本地的 checkForUpdates 函数** + +删除整个 `checkForUpdates` 函数定义。 + +**步骤 2:更新所有 checkForUpdates 调用** + +将调用从 `checkForUpdates(` 替换为 `skillsCore.checkForUpdates(` + +**步骤 3:验证脚本仍然工作** + +运行:`.codex/superpowers-codex bootstrap | head -50` +预期:显示引导内容 + +**步骤 4:提交** + +```bash +git add .codex/superpowers-codex +git commit -m "refactor: use shared checkForUpdates in codex" +``` + +*** + +## 阶段 3:构建 OpenCode 插件 + +### 任务 9:创建 OpenCode 插件目录结构 + +**文件:** + +* 创建:`.opencode/plugin/superpowers.js` + +**步骤 1:创建目录** + +运行:`mkdir -p .opencode/plugin` + +**步骤 2:创建基础插件文件** + +```javascript +#!/usr/bin/env node + +/** + * Superpowers plugin for OpenCode.ai + * + * Provides custom tools for loading and discovering skills, + * with automatic bootstrap on session start. + */ + +const skillsCore = require('../../lib/skills-core'); +const path = require('path'); +const fs = require('fs'); +const os = require('os'); + +const homeDir = os.homedir(); +const superpowersSkillsDir = path.join(homeDir, '.config/opencode/superpowers/skills'); +const personalSkillsDir = path.join(homeDir, '.config/opencode/skills'); + +/** + * OpenCode plugin entry point + */ +export const SuperpowersPlugin = async ({ project, client, $, directory, worktree }) => { + return { + // Custom tools and hooks will go here + }; +}; +``` + +**步骤 3:验证文件已创建** + +运行:`ls -l .opencode/plugin/superpowers.js` +预期:文件存在 + +**步骤 4:提交** + +```bash +git add .opencode/plugin/superpowers.js +git commit -m "feat: create opencode plugin scaffold" +``` + +*** + +### 任务 10:实现 use\_skill 工具 + +**文件:** + +* 修改:`.opencode/plugin/superpowers.js` + +**步骤 1:添加 use\_skill 工具实现** + +替换插件的返回语句为: + +```javascript +export const SuperpowersPlugin = async ({ project, client, $, directory, worktree }) => { + // Import zod for schema validation + const { z } = await import('zod'); + + return { + tools: [ + { + name: 'use_skill', + description: 'Load and read a specific skill to guide your work. Skills contain proven workflows, mandatory processes, and expert techniques.', + schema: z.object({ + skill_name: z.string().describe('Name of the skill to load (e.g., "superpowers:brainstorming" or "my-custom-skill")') + }), + execute: async ({ skill_name }) => { + // Resolve skill path (handles shadowing: personal > superpowers) + const resolved = skillsCore.resolveSkillPath( + skill_name, + superpowersSkillsDir, + personalSkillsDir + ); + + if (!resolved) { + return `Error: Skill "${skill_name}" not found.\n\nRun find_skills to see available skills.`; + } + + // Read skill content + const fullContent = fs.readFileSync(resolved.skillFile, 'utf8'); + const { name, description } = skillsCore.extractFrontmatter(resolved.skillFile); + + // Extract content after frontmatter + const lines = fullContent.split('\n'); + let inFrontmatter = false; + let frontmatterEnded = false; + const contentLines = []; + + for (const line of lines) { + if (line.trim() === '---') { + if (inFrontmatter) { + frontmatterEnded = true; + continue; + } + inFrontmatter = true; + continue; + } + + if (frontmatterEnded || !inFrontmatter) { + contentLines.push(line); + } + } + + const content = contentLines.join('\n').trim(); + const skillDirectory = path.dirname(resolved.skillFile); + + // Format output similar to Claude Code's Skill tool + return `# ${name || skill_name} +# ${description || ''} +# Supporting tools and docs are in ${skillDirectory} +# ============================================ + +${content}`; + } + } + ] + }; +}; +``` + +**步骤 2:验证语法** + +运行:`node -c .opencode/plugin/superpowers.js` +预期:无输出 + +**步骤 3:提交** + +```bash +git add .opencode/plugin/superpowers.js +git commit -m "feat: implement use_skill tool for opencode" +``` + +*** + +### 任务 11:实现 find\_skills 工具 + +**文件:** + +* 修改:`.opencode/plugin/superpowers.js` + +**步骤 1:向工具数组添加 find\_skills 工具** + +在 use\_skill 工具定义之后,关闭工具数组之前添加: + +```javascript + { + name: 'find_skills', + description: 'List all available skills in the superpowers and personal skill libraries.', + schema: z.object({}), + execute: async () => { + // Find skills in both directories + const superpowersSkills = skillsCore.findSkillsInDir( + superpowersSkillsDir, + 'superpowers', + 3 + ); + const personalSkills = skillsCore.findSkillsInDir( + personalSkillsDir, + 'personal', + 3 + ); + + // Combine and format skills list + const allSkills = [...personalSkills, ...superpowersSkills]; + + if (allSkills.length === 0) { + return 'No skills found. Install superpowers skills to ~/.config/opencode/superpowers/skills/'; + } + + let output = 'Available skills:\n\n'; + + for (const skill of allSkills) { + const namespace = skill.sourceType === 'personal' ? '' : 'superpowers:'; + const skillName = skill.name || path.basename(skill.path); + + output += `${namespace}${skillName}\n`; + if (skill.description) { + output += ` ${skill.description}\n`; + } + output += ` Directory: ${skill.path}\n\n`; + } + + return output; + } + } +``` + +**步骤 2:验证语法** + +运行:`node -c .opencode/plugin/superpowers.js` +预期:无输出 + +**步骤 3:提交** + +```bash +git add .opencode/plugin/superpowers.js +git commit -m "feat: implement find_skills tool for opencode" +``` + +*** + +### 任务 12:实现会话启动钩子 + +**文件:** + +* 修改:`.opencode/plugin/superpowers.js` + +**步骤 1:添加 session.started 钩子** + +在工具数组之后添加: + +```javascript + 'session.started': async () => { + // Read using-superpowers skill content + const usingSuperpowersPath = skillsCore.resolveSkillPath( + 'using-superpowers', + superpowersSkillsDir, + personalSkillsDir + ); + + let usingSuperpowersContent = ''; + if (usingSuperpowersPath) { + const fullContent = fs.readFileSync(usingSuperpowersPath.skillFile, 'utf8'); + // Strip frontmatter + const lines = fullContent.split('\n'); + let inFrontmatter = false; + let frontmatterEnded = false; + const contentLines = []; + + for (const line of lines) { + if (line.trim() === '---') { + if (inFrontmatter) { + frontmatterEnded = true; + continue; + } + inFrontmatter = true; + continue; + } + + if (frontmatterEnded || !inFrontmatter) { + contentLines.push(line); + } + } + + usingSuperpowersContent = contentLines.join('\n').trim(); + } + + // Tool mapping instructions + const toolMapping = ` +**Tool Mapping for OpenCode:** +When skills reference tools you don't have, substitute OpenCode equivalents: +- \`TodoWrite\` → \`update_plan\` (your planning/task tracking tool) +- \`Task\` tool with subagents → Use OpenCode's subagent system (@mention syntax or automatic dispatch) +- \`Skill\` tool → \`use_skill\` custom tool (already available) +- \`Read\`, \`Write\`, \`Edit\`, \`Bash\` → Use your native tools + +**Skill directories contain supporting files:** +- Scripts you can run with bash tool +- Additional documentation you can read +- Utilities and helpers specific to that skill + +**Skills naming:** +- Superpowers skills: \`superpowers:skill-name\` (from ~/.config/opencode/superpowers/skills/) +- Personal skills: \`skill-name\` (from ~/.config/opencode/skills/) +- Personal skills override superpowers skills when names match +`; + + // Check for updates (non-blocking) + const hasUpdates = skillsCore.checkForUpdates( + path.join(homeDir, '.config/opencode/superpowers') + ); + + const updateNotice = hasUpdates ? + '\n\n⚠️ **Updates available!** Run `cd ~/.config/opencode/superpowers && git pull` to update superpowers.' : + ''; + + // Return context to inject into session + return { + context: ` +You have superpowers. + +**Below is the full content of your 'superpowers:using-superpowers' skill - your introduction to using skills. For all other skills, use the 'use_skill' tool:** + +${usingSuperpowersContent} + +${toolMapping}${updateNotice} +` + }; + } +``` + +**步骤 2:验证语法** + +运行:`node -c .opencode/plugin/superpowers.js` +预期:无输出 + +**步骤 3:提交** + +```bash +git add .opencode/plugin/superpowers.js +git commit -m "feat: implement session.started hook for opencode" +``` + +*** + +## 阶段 4:文档 + +### 任务 13:创建 OpenCode 安装指南 + +**文件:** + +* 创建:`.opencode/INSTALL.md` + +**步骤 1:创建安装指南** + +````markdown +# 为 OpenCode 安装 Superpowers + +## 先决条件 + +- 已安装 [OpenCode.ai](https://opencode.ai) +- 已安装 Node.js +- 已安装 Git + +## 安装步骤 + +### 1. 安装 Superpowers 技能 + +```bash +# 将 superpowers 技能克隆到 OpenCode 配置目录 +mkdir -p ~/.config/opencode/superpowers +git clone https://github.com/obra/superpowers.git ~/.config/opencode/superpowers +```` + +### 2. 安装插件 + +插件包含在你刚刚克隆的 superpowers 仓库中。 + +OpenCode 会自动从以下位置发现它: + +* `~/.config/opencode/superpowers/.opencode/plugin/superpowers.js` + +或者,你可以将其链接到项目本地的插件目录: + +```bash +# In your OpenCode project +mkdir -p .opencode/plugin +ln -s ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js .opencode/plugin/superpowers.js +``` + +### 3. 重启 OpenCode + +重启 OpenCode 以加载插件。在下一次会话中,你应该会看到: + +``` +你有 superpowers。 +``` + +## 使用方法 + +### 查找技能 + +使用 `find_skills` 工具列出所有可用技能: + +``` +使用 find_skills 工具 +``` + +### 加载技能 + +使用 `use_skill` 工具加载特定技能: + +``` +使用 use_skill 工具,技能名称:"superpowers:brainstorming" +``` + +### 个人技能 + +在 `~/.config/opencode/skills/` 中创建你自己的技能: + +```bash +mkdir -p ~/.config/opencode/skills/my-skill +``` + +创建 `~/.config/opencode/skills/my-skill/SKILL.md`: + +```markdown +--- +name: my-skill +description: Use when [condition] - [what it does] +--- + +# 我的技能 + +[你的技能内容在这里] +``` + +个人技能会覆盖同名的 superpowers 技能。 + +## 更新 + +```bash +cd ~/.config/opencode/superpowers +git pull +``` + +## 故障排除 + +### 插件未加载 + +1. 检查插件文件是否存在:`ls ~/.config/opencode/superpowers/.opencode/plugin/superpowers.js` +2. 检查 OpenCode 日志以查找错误 +3. 验证 Node.js 是否已安装:`node --version` + +### 技能未找到 + +1. 验证技能目录是否存在:`ls ~/.config/opencode/superpowers/skills` +2. 使用 `find_skills` 工具查看发现了什么 +3. 检查文件结构:每个技能应有一个 `SKILL.md` 文件 + +### 工具映射问题 + +当技能引用了你没有的 Claude Code 工具时: + +* `TodoWrite` → 使用 `update_plan` +* 带有子代理的 `Task` → 使用 `@mention` 语法来调用 OpenCode 子代理 +* `Skill` → 使用 `use_skill` 工具 +* 文件操作 → 使用你的原生工具 + +## 获取帮助 + +* 报告问题:https://github.com/obra/superpowers/issues +* 文档:https://github.com/obra/superpowers + +```` +**Step 2: 验证文件已创建** + +运行: `ls -l .opencode/INSTALL.md` +预期: 文件存在 + +**Step 3: 提交** + +```bash +git add .opencode/INSTALL.md +git commit -m "docs: add opencode installation guide" + +```` + +*** + +### 任务 14:更新主 README + +**文件:** + +* 修改:`README.md` + +**步骤 1:添加 OpenCode 部分** + +查找关于支持平台的部分(在文件中搜索 "Codex"),并在其后添加: + +```markdown +### OpenCode + +Superpowers 通过原生 JavaScript 插件与 [OpenCode.ai](https://opencode.ai) 协同工作。 + +**安装:** 参见 [.opencode/INSTALL.md](.opencode/INSTALL.md) + +**功能特性:** +- 自定义工具:`use_skill` 和 `find_skills` +- 自动会话引导 +- 具备影射功能的个人技能 +- 支持文件和脚本访问 +``` + +**步骤 2:验证格式** + +运行:`grep -A 10 "### OpenCode" README.md` +预期:显示你添加的部分 + +**步骤 3:提交** + +```bash +git add README.md +git commit -m "docs: add opencode support to readme" +``` + +*** + +### 任务 15:更新发布说明 + +**文件:** + +* 修改:`RELEASE-NOTES.md` + +**步骤 1:为 OpenCode 支持添加条目** + +在文件顶部(标题之后),添加: + +```markdown +## [未发布] + +### 新增 + +- **OpenCode 支持**:原生 JavaScript 插件,用于 OpenCode.ai + - 自定义工具:`use_skill` 和 `find_skills` + - 自动会话引导,附带工具映射说明 + - 共享核心模块(`lib/skills-core.js`),用于代码复用 + - 安装指南位于 `.opencode/INSTALL.md` + +### 变更 + +- **重构了 Codex 实现**:现在使用共享的 `lib/skills-core.js` 模块 + - 消除了 Codex 和 OpenCode 之间的代码重复 + - 技能发现和解析的单一事实来源 + +--- +``` + +**步骤 2:验证格式** + +运行:`head -30 RELEASE-NOTES.md` +预期:显示你的新部分 + +**步骤 3:提交** + +```bash +git add RELEASE-NOTES.md +git commit -m "docs: add opencode support to release notes" +``` + +*** + +## 阶段 5:最终验证 + +### 任务 16:测试 Codex 是否仍然工作 + +**文件:** + +* 测试:`.codex/superpowers-codex` + +**步骤 1:测试 find-skills 命令** + +运行:`.codex/superpowers-codex find-skills | head -20` +预期:显示带有名称和描述的技能列表 + +**步骤 2:测试 use-skill 命令** + +运行:`.codex/superpowers-codex use-skill superpowers:brainstorming | head -20` +预期:显示头脑风暴技能内容 + +**步骤 3:测试 bootstrap 命令** + +运行:`.codex/superpowers-codex bootstrap | head -30` +预期:显示带有说明的引导内容 + +**步骤 4:如果所有测试通过,记录成功** + +无需提交 - 这只是验证。 + +*** + +### 任务 17:验证文件结构 + +**文件:** + +* 检查:所有新文件都存在 + +**步骤 1:验证所有文件已创建** + +运行: + +```bash +ls -l lib/skills-core.js +ls -l .opencode/plugin/superpowers.js +ls -l .opencode/INSTALL.md +``` + +预期:所有文件都存在 + +**步骤 2:验证目录结构** + +运行:`tree -L 2 .opencode/` (如果 tree 命令不可用,则使用 `find .opencode -type f`) +预期: + +``` +.opencode/ +├── INSTALL.md +└── plugin/ + └── superpowers.js +``` + +**步骤 3:如果结构正确,则继续** + +无需提交 - 这只是验证。 + +*** + +### 任务 18:最终提交与总结 + +**文件:** + +* 检查:`git status` + +**步骤 1:检查 git 状态** + +运行:`git status` +预期:工作树干净,所有更改已提交 + +**步骤 2:查看提交日志** + +运行:`git log --oneline -20` +预期:显示此实施过程中的所有提交 + +**步骤 3:创建总结文档** + +创建一个完成总结,显示: + +* 总共进行的提交 +* 创建的文件:`lib/skills-core.js`, `.opencode/plugin/superpowers.js`, `.opencode/INSTALL.md` +* 修改的文件:`.codex/superpowers-codex`, `README.md`, `RELEASE-NOTES.md` +* 执行的测试:Codex 命令已验证 +* 准备就绪,可用于:使用实际的 OpenCode 安装进行测试 + +**步骤 4:报告完成** + +向用户呈现总结并提供以下选项: + +1. 推送到远程仓库 +2. 创建拉取请求 +3. 使用真实的 OpenCode 安装进行测试(需要已安装 OpenCode) + +*** + +## 测试指南(手动 - 需要 OpenCode) + +这些步骤需要安装 OpenCode,不属于自动化实施的一部分: + +1. **安装技能**:按照 `.opencode/INSTALL.md` 操作 +2. **启动 OpenCode 会话**:验证引导信息出现 +3. **测试 find\_skills**:应列出所有可用技能 +4. **测试 use\_skill**:加载一个技能并验证内容出现 +5. **测试支持文件**:验证技能目录路径可访问 +6. **测试个人技能**:创建一个个人技能并验证它覆盖了核心技能 +7. **测试工具映射**:验证 TodoWrite → update\_plan 映射有效 + +## 成功标准 + +* \[ ] `lib/skills-core.js` 已创建,包含所有核心功能 +* \[ ] `.codex/superpowers-codex` 已重构为使用共享核心 +* \[ ] Codex 命令仍然有效(find-skills, use-skill, bootstrap) +* \[ ] `.opencode/plugin/superpowers.js` 已创建,包含工具和钩子 +* \[ ] 安装指南已创建 +* \[ ] README 和 RELEASE-NOTES 已更新 +* \[ ] 所有更改已提交 +* \[ ] 工作树干净 diff --git a/zh-CN/docs/plans/2025-11-28-skills-improvements-from-user-feedback.md b/zh-CN/docs/plans/2025-11-28-skills-improvements-from-user-feedback.md new file mode 100644 index 0000000000..41a34a0515 --- /dev/null +++ b/zh-CN/docs/plans/2025-11-28-skills-improvements-from-user-feedback.md @@ -0,0 +1,751 @@ +# 基于用户反馈的技能改进 + +**日期:** 2025-11-28 +**状态:** 草案 +**来源:** 两个 Claude 实例在实际开发场景中使用 superpowers + +*** + +## 执行摘要 + +两个 Claude 实例提供了来自实际开发会话的详细反馈。他们的反馈揭示了当前技能中存在的**系统性缺陷**,这些缺陷导致可预防的 bug 在遵循技能的情况下仍然被发布。 + +**关键洞察:** 这些都是问题报告,而不仅仅是解决方案提议。问题是真实存在的;解决方案需要仔细评估。 + +**关键主题:** + +1. **验证缺口** - 我们验证操作成功,但不验证它们是否达到了预期结果 +2. **流程卫生** - 后台进程累积并在子代理之间产生干扰 +3. **上下文优化** - 子代理获取了太多无关信息 +4. **缺少自我反思** - 在移交前没有提示来批判自己的工作 +5. **模拟安全** - 模拟可能偏离接口而无法被检测到 +6. **技能激活** - 技能存在但未被阅读/使用 + +*** + +## 已识别的问题 + +### 问题 1:配置变更验证缺口 + +**发生了什么:** + +* 子代理测试了“OpenAI 集成” +* 设置了 `OPENAI_API_KEY` 环境变量 +* 收到了状态 200 的响应 +* 报告“OpenAI 集成工作正常” +* **但是** 响应包含 `"model": "claude-sonnet-4-20250514"` - 实际上使用的是 Anthropic + +**根本原因:** +`verification-before-completion` 检查操作是否成功,但不检查结果是否反映了预期的配置变更。 + +**影响:** 高 - 对集成测试产生虚假信心,bug 发布到生产环境 + +**示例失败模式:** + +* 切换 LLM 提供商 → 验证状态 200 但不检查模型名称 +* 启用功能标志 → 验证无错误但不检查功能是否激活 +* 更改环境 → 验证部署成功但不检查环境变量 + +*** + +### 问题 2:后台进程累积 + +**发生了什么:** + +* 会话期间分派了多个子代理 +* 每个子代理都启动了后台服务器进程 +* 进程累积(4 个以上服务器在运行) +* 过时的进程仍然绑定到端口 +* 后来的端到端测试命中了配置错误的陈旧服务器 +* 导致混淆/不正确的测试结果 + +**根本原因:** +子代理是无状态的 - 不知道先前子代理的进程。没有清理协议。 + +**影响:** 中-高 - 测试命中错误的服务器,虚假通过/失败,调试混淆 + +*** + +### 问题 3:子代理提示中的上下文膨胀 + +**发生了什么:** + +* 标准方法:给子代理完整的计划文件阅读 +* 实验:只给任务 + 模式 + 文件 + 验证命令 +* 结果:更快、更专注、单次尝试完成更常见 + +**根本原因:** +子代理在无关的计划部分浪费了令牌和注意力。 + +**影响:** 中 - 执行速度慢,更多失败尝试 + +**有效的方法:** + +``` +你正在为 packnplay 的测试套件添加一个端到端测试。 + +**你的任务:** 在 `pkg/runner/e2e_test.go` 中添加 `TestE2E_FeaturePrivilegedMode` + +**测试内容:** 一个在其元数据中请求了 `"privileged": true` 的本地 devcontainer 功能,应该导致容器以 `--privileged` 标志运行。 + +**请严格按照 TestE2E_FeatureOptionValidation 的模式编写**(位于文件末尾) + +**编写完成后,运行:** `go test -v ./pkg/runner -run TestE2E_FeaturePrivilegedMode -timeout 5m` +``` + +*** + +### 问题 4:移交前无自我反思 + +**发生了什么:** + +* 添加了自我反思提示:“用新的眼光审视你的工作 - 哪些地方可以做得更好?” +* 任务 5 的实施者识别出测试失败是由于实现 bug,而不是测试 bug +* 追溯到第 99 行:`strings.Join(metadata.Entrypoint, " ")` 创建了无效的 Docker 语法 +* 如果没有自我反思,只会报告“测试失败”而不说明根本原因 + +**根本原因:** +实施者在报告完成前,不会自然地退一步批判自己的工作。 + +**影响:** 中 - 实施者本可以发现的 bug 被移交给审查者 + +*** + +### 问题 5:模拟-接口漂移 + +**发生了什么:** + +```typescript +// Interface defines close() +interface PlatformAdapter { + close(): Promise; +} + +// Code (BUGGY) calls cleanup() +await adapter.cleanup(); + +// Mock (MATCHES BUG) defines cleanup() +vi.mock('web-adapter', () => ({ + WebAdapter: vi.fn().mockImplementation(() => ({ + cleanup: vi.fn().mockResolvedValue(undefined), // Wrong! + })), +})); +``` + +* 测试通过 +* 运行时崩溃:“adapter.cleanup is not a function” + +**根本原因:** +模拟源自错误代码调用的内容,而非接口定义。TypeScript 无法捕获方法名错误的行内模拟。 + +**影响:** 高 - 测试给出虚假信心,运行时崩溃 + +**为什么测试反模式没有防止这种情况:** +该技能涵盖了测试模拟行为和在不理解的情况下进行模拟,但没有涵盖“从接口而非实现派生模拟”的具体模式。 + +*** + +### 问题 6:代码审查者文件访问 + +**发生了什么:** + +* 分派了代码审查子代理 +* 找不到测试文件:“该文件似乎不存在于仓库中” +* 文件实际存在 +* 审查者不知道需要先显式读取它 + +**根本原因:** +审查者提示不包括显式的文件读取指令。 + +**影响:** 低-中 - 审查失败或不完整 + +*** + +### 问题 7:修复工作流延迟 + +**发生了什么:** + +* 实施者在自我反思期间识别出 bug +* 实施者知道如何修复 +* 当前工作流:报告 → 我分派修复者 → 修复者修复 → 我验证 +* 额外的往返增加了延迟,但没有增加价值 + +**根本原因:** +当实施者已经诊断出问题时,实施者和修复者角色之间仍存在严格的分离。 + +**影响:** 低 - 延迟,但无正确性问题 + +*** + +### 问题 8:技能未被阅读 + +**发生了什么:** + +* `testing-anti-patterns` 技能存在 +* 无论是人类还是子代理在编写测试前都没有阅读它 +* 本可以防止一些问题(虽然不是全部 - 参见问题 5) + +**根本原因:** +没有强制要求子代理阅读相关技能。没有提示包含技能阅读。 + +**影响:** 中 - 如果不使用,技能投资就被浪费了 + +*** + +## 提议的改进 + +### 1. verification-before-completion: 添加配置变更验证 + +**添加新部分:** + +```markdown +## 验证配置变更 + +测试配置、提供商、功能开关或环境变更时: + +**不要仅验证操作成功。要验证输出反映了预期的变更。** + +### 常见失败模式 + +操作成功是因为存在*某些*有效配置,但并非你打算测试的配置。 + +### 示例 + +| 变更 | 不充分的验证 | 必需的验证 | +|--------|-------------|----------| +| 切换LLM提供商 | 状态码200 | 响应包含预期的模型名称 | +| 启用功能开关 | 无错误 | 功能行为实际已激活 | +| 更改环境 | 部署成功 | 日志/变量引用新环境 | +| 设置凭据 | 身份验证成功 | 已验证的用户/上下文正确 | + +### 门控函数 +``` + +在声称配置变更有效之前: + +1. 识别:此变更后,什么应该**不同**? +2. 定位:这种差异在哪里可以观察到? + * 响应字段(模型名称,用户 ID) + * 日志行(环境,提供商) + * 行为(功能激活/未激活) +3. 运行:显示可观察差异的命令 +4. 验证:输出包含预期的差异 +5. 只有**在那之后**:声称配置变更有效 + +危险信号: + +* “请求成功”但不检查内容 + * 检查状态码但不检查响应体 + * 验证无错误但不进行积极确认 + +```` +**Why this works:** +Forces verification of INTENT, not just operation success. + +--- + +### 2. subagent-driven-development: Add Process Hygiene for E2E Tests + +**Add new section:** + +```markdown +## Process Hygiene for E2E Tests + +When dispatching subagents that start services (servers, databases, message queues): + +### Problem + +Subagents are stateless - they don't know about processes started by previous subagents. Background processes persist and can interfere with later tests. + +### Solution + +**Before dispatching E2E test subagent, include cleanup in prompt:** + +```` + +在启动任何服务之前: + +1. 终止现有进程:pkill -f "" 2>/dev/null || true +2. 等待清理:sleep 1 +3. 验证端口空闲:lsof -i : && echo "ERROR: Port still in use" || echo "Port free" + +测试完成后: + +1. 终止你启动的进程 +2. 验证清理:pgrep -f "" || echo "Cleanup successful" + +``` +### 示例 +``` + +任务:运行 API 服务器的端到端测试 + +提示包括: +“在启动服务器之前: + +* 终止任何现有服务器: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'” + +``` +### 为何这很重要 + +- 过时的进程会使用错误的配置处理请求 +- 端口冲突导致静默失败 +- 进程累积拖慢系统 +- 造成混淆的测试结果(访问到错误的服务器) +``` + +**权衡分析:** + +* 给提示增加了样板代码 +* 但防止了非常令人困惑的调试 +* 对于端到端测试子代理来说是值得的 + +*** + +### 3. subagent-driven-development: 添加精简上下文选项 + +**修改步骤 2:使用子代理执行任务** + +**之前:** + +``` +仔细阅读 [plan-file] 中的任务。 +``` + +**之后:** + +``` +## 上下文处理方式 + +**完整计划(默认):** +适用于任务复杂或存在依赖关系时: +``` + +仔细阅读 \[plan-file] 中的任务 N。 + +``` +**Lean Context(适用于独立任务):** +当任务独立且基于模式时使用: +``` + +你正在实现:\[1-2 句任务描述] + +要修改的文件:\[确切路径] +要遵循的模式:\[对现有函数/测试的引用] +要实现的内容:\[具体要求] +验证:\[要运行的精确命令] + +\[请勿包含完整的计划文件] + +``` +**在以下情况下使用精简上下文:** +- 任务遵循现有模式(添加类似测试,实现类似功能) +- 任务是自包含的(不需要其他任务的上下文) +- 模式参考已足够(例如,"遵循 TestE2E_FeatureOptionValidation") + +**在以下情况下使用完整计划:** +- 任务依赖于其他任务 +- 需要理解整体架构 +- 需要上下文才能理解的复杂逻辑 +``` + +**示例:** + +``` +Lean 上下文提示: + +"你正在为 devcontainer 功能添加特权模式测试。 + +文件:pkg/runner/e2e_test.go +模式:遵循 TestE2E_FeatureOptionValidation(在文件末尾) +测试:元数据中带有 `"privileged": true` 的功能应产生 `--privileged` 标志 +验证:go test -v ./pkg/runner -run TestE2E_FeaturePrivilegedMode -timeout 5m + +报告:实现情况、测试结果、任何问题。" +``` + +**为什么这有效:** +减少令牌使用,提高专注度,在适当时更快完成。 + +*** + +### 4. subagent-driven-development: 添加自我反思步骤 + +**修改步骤 2:使用子代理执行任务** + +**添加到提示模板:** + +``` +当完成后,在汇报之前: + +退一步,用全新的视角审视你的工作。 + +问自己: +- 这真的解决了指定的任务吗? +- 有没有我没有考虑到的边缘情况? +- 我是否正确遵循了模式? +- 如果测试失败,根本原因是什么(实现错误还是测试错误)? +- 这个实现还有哪些可以改进的地方? + +如果在这次反思中发现了问题,现在就去修复它们。 + +然后汇报: +- 你实现了什么 +- 自我反思的发现(如果有的话) +- 测试结果 +- 更改的文件 +``` + +**为什么这有效:** +在移交前捕获实施者自己能发现的 bug。有记录的案例:通过自我反思识别了入口点 bug。 + +**权衡:** +每个任务增加约 30 秒,但在审查前捕获问题。 + +*** + +### 5. requesting-code-review: 添加显式文件读取 + +**修改代码审查者模板:** + +**在开头添加:** + +```markdown +## 待审阅文件 + +开始分析前,请先阅读以下文件: + +1. [列出差异中涉及的具体文件] +2. [被变更引用但未修改的文件] + +使用 Read 工具加载每个文件。 + +如果找不到文件: +- 检查差异中提供的准确路径 +- 尝试其他可能的位置 +- 报告:"无法定位 [路径] - 请确认文件是否存在" + +在未实际阅读代码前,请勿继续审阅。 +``` + +**为什么这有效:** +明确的指令防止“找不到文件”的问题。 + +*** + +### 6. testing-anti-patterns: 添加模拟-接口漂移反模式 + +**添加新的反模式 6:** + +````markdown +## 反模式 6:从实现细节派生的模拟 + +**违规情况:** +```typescript +// 代码(有缺陷)调用了 cleanup() +await adapter.cleanup(); + +// 模拟(匹配缺陷)包含了 cleanup() +const mock = { + cleanup: vi.fn().mockResolvedValue(undefined) +}; + +// 接口(正确)定义的是 close() +interface PlatformAdapter { + close(): Promise; +} +```` + +**为什么这是错误的:** + +* 模拟将 bug 编码到测试中 +* TypeScript 无法捕获方法名错误的行内模拟 +* 测试通过是因为代码和模拟都是错误的 +* 使用真实对象时运行时崩溃 + +**修复方法:** + +```typescript +// ✅ GOOD: Derive mock from interface + +// Step 1: Open interface definition (PlatformAdapter) +// Step 2: List methods defined there (close, initialize, etc.) +// Step 3: Mock EXACTLY those methods + +const mock = { + initialize: vi.fn().mockResolvedValue(undefined), + close: vi.fn().mockResolvedValue(undefined), // From interface! +}; + +// Now test FAILS because code calls cleanup() which doesn't exist +// That failure reveals the bug BEFORE runtime +``` + +### 门控函数 + +``` +在编写任何模拟之前: + + 1. 停止 - 请勿查看待测代码 + 2. 查找:依赖项的接口/类型定义 + 3. 阅读:接口文件 + 4. 列出:接口中定义的方法 + 5. 模拟:仅模拟那些方法,并使用完全相同的名称 + 6. 不要:查看你的代码调用了什么 + + 如果你的测试因代码调用了模拟中不存在的内容而失败: + ✅ 很好 - 测试发现了你代码中的一个错误 + 修复代码以调用正确的接口方法 + 而不是修改模拟 + + 危险信号: + - "我会模拟代码调用的内容" + - 从实现中复制方法名称 + - 未阅读接口就编写模拟 + - "测试失败了,所以我会在模拟中添加这个方法" +``` + +**检测:** + +当你看到运行时错误“X 不是一个函数”而测试通过时: + +1. 检查 X 是否被模拟 +2. 比较模拟方法与接口方法 +3. 寻找方法名不匹配 + +```` +**Why this works:** +直接针对反馈中的失败模式进行解决。 + +--- + +### 7. subagent-driven-development: 要求测试子代理具备技能阅读能力 + +**当任务涉及测试时,添加到提示模板中:** + +```markdown +BEFORE writing any tests: + +1. Read testing-anti-patterns skill: + Use Skill tool: superpowers:testing-anti-patterns + +2. Apply gate functions from that skill when: + - Writing mocks + - Adding methods to production classes + - Mocking dependencies + +This is NOT optional. Tests that violate anti-patterns will be rejected in review. + +```` + +**为什么这有效:** +确保技能实际被使用,而不仅仅是存在。 + +**权衡:** +每个任务增加时间,但防止了整类 bug。 + +*** + +### 8. subagent-driven-development: 允许实施者修复自我识别的问题 + +**修改步骤 2:** + +**当前:** + +``` +Subagent 报告工作摘要。 +``` + +**提议:** + +``` +Subagent 进行自我反思,然后: + +IF 自我反思识别出可修复的问题: + 1. 修复问题 + 2. 重新运行验证 + 3. 报告:"初始实现 + 自我反思修复" + +ELSE: + 报告:"实施完成" + +报告中包含: +- 自我反思的发现 +- 是否应用了修复 +- 最终的验证结果 +``` + +**为什么这有效:** +当实施者已经知道修复方法时,减少延迟。有记录的案例:本可以为入口点 bug 节省一次往返。 + +**权衡:** +提示稍微复杂一些,但端到端速度更快。 + +*** + +## 实施计划 + +### 第一阶段:高影响,低风险(优先实施) + +1. **verification-before-completion: 配置变更验证** + * 清晰的补充,不改变现有内容 + * 解决高影响问题(测试中的虚假信心) + * 文件:`skills/verification-before-completion/SKILL.md` + +2. **testing-anti-patterns: 模拟-接口漂移** + * 添加新反模式,不修改现有内容 + * 解决高影响问题(运行时崩溃) + * 文件:`skills/testing-anti-patterns/SKILL.md` + +3. **requesting-code-review: 显式文件读取** + * 对模板的简单补充 + * 解决具体问题(审查者找不到文件) + * 文件:`skills/requesting-code-review/SKILL.md` + +### 第二阶段:中等变更(仔细测试) + +4. **subagent-driven-development: 流程卫生** + * 添加新部分,不改变工作流 + * 解决中-高影响问题(测试可靠性) + * 文件:`skills/subagent-driven-development/SKILL.md` + +5. **subagent-driven-development: 自我反思** + * 更改提示模板(风险较高) + * 但有记录表明能捕获 bug + * 文件:`skills/subagent-driven-development/SKILL.md` + +6. **subagent-driven-development: 技能阅读要求** + * 增加提示开销 + * 但确保技能实际被使用 + * 文件:`skills/subagent-driven-development/SKILL.md` + +### 第三阶段:优化(先验证) + +7. **subagent-driven-development: 精简上下文选项** + * 增加复杂性(两种方法) + * 需要验证它不会引起混淆 + * 文件:`skills/subagent-driven-development/SKILL.md` + +8. **subagent-driven-development: 允许实施者修复** + * 更改工作流(风险较高) + * 优化,而非 bug 修复 + * 文件:`skills/subagent-driven-development/SKILL.md` + +*** + +## 开放性问题 + +1. **精简上下文方法:** + * 对于基于模式的任务,我们应该将其设为默认吗? + * 我们如何决定使用哪种方法? + * 过于精简而遗漏重要上下文的风险? + +2. **自我反思:** + * 这会显著减慢简单任务的速度吗? + * 是否只应应用于复杂任务? + * 如何防止其变得机械而导致的“反思疲劳”? + +3. **流程卫生:** + * 这应该放在 subagent-driven-development 中,还是一个单独的技能里? + * 它是否适用于端到端测试之外的其他工作流? + * 如何处理进程**应该**持续存在的情况(开发服务器)? + +4. **技能阅读强制要求:** + * 我们应该要求**所有**子代理阅读相关技能吗? + * 如何防止提示变得过长? + * 过度文档化而失去焦点的风险? + +*** + +## 成功指标 + +我们如何知道这些改进有效? + +1. **配置验证:** + * “测试通过但使用了错误配置”的实例为零 + * Jesse 不会说“那实际上并没有测试你认为它在测试的东西” + +2. **流程卫生:** + * “测试命中错误服务器”的实例为零 + * 端到端测试运行期间无端口冲突错误 + +3. **模拟接口漂移:** + * 零出现“测试通过但运行时因缺少方法而崩溃”的情况 + * 模拟对象与接口之间不存在方法名不匹配 + +4. **自我反思:** + * 可衡量性:执行者报告是否包含自我反思的发现? + * 定性分析:进入代码审查阶段的缺陷是否减少? + +5. **技能解读:** + * 子代理报告引用技能门控函数 + * 代码审查中反模式违规情况减少 + +*** + +## 风险与应对措施 + +### 风险:提示膨胀 + +**问题:** 添加所有这些要求会使提示变得过于冗长 +**应对措施:** + +* 分阶段实施(不要一次性添加所有内容) +* 使部分附加要求成为条件性(端到端卫生仅适用于端到端测试) +* 考虑为不同任务类型设置模板 + +### 风险:分析瘫痪 + +**问题:** 过多的反思/验证会拖慢执行速度 +**应对措施:** + +* 保持门控函数快速执行(秒级,而非分钟级) +* 初始阶段将精简上下文设为可选功能 +* 监控任务完成时间 + +### 风险:虚假安全感 + +**问题:** 遵循检查清单并不能保证正确性 +**应对措施:** + +* 强调门控函数是最低要求,而非最高标准 +* 在技能描述中保留“运用判断力”的表述 +* 说明技能旨在发现常见错误,而非所有错误 + +### 风险:技能分歧 + +**问题:** 不同技能给出相互矛盾的建议 +**应对措施:** + +* 审查所有技能的变更以确保一致性 +* 记录技能间的协作方式(集成章节) +* 部署前通过真实场景进行测试 + +*** + +## 实施建议 + +**立即启动第一阶段:** + +* 完成前验证:配置变更验证 +* 测试反模式:模拟接口漂移检测 +* 发起代码审查:显式文件读取要求 + +**与Jesse共同测试第二阶段后再定稿:** + +* 获取关于自我反思影响的反馈 +* 验证流程卫生方法的有效性 +* 确认技能解读要求值得其额外开销 + +**暂缓实施第三阶段以待验证:** + +* 精简上下文需经实际场景测试 +* 执行者修复工作流变更需谨慎评估 + +这些改进措施针对用户记录的实际问题,同时最大限度降低了技能质量下降的风险。 diff --git a/zh-CN/docs/plans/2026-01-17-visual-brainstorming.md b/zh-CN/docs/plans/2026-01-17-visual-brainstorming.md new file mode 100644 index 0000000000..fe74222b64 --- /dev/null +++ b/zh-CN/docs/plans/2026-01-17-visual-brainstorming.md @@ -0,0 +1,579 @@ +# 视觉化头脑风暴伴侣实施计划 + +> **对于智能体工作者:** 必需子技能:使用 superpowers:executing-plans 来按任务实施此计划。 + +**目标:** 为 Claude 提供一个基于浏览器的视觉伴侣,用于头脑风暴会议——在终端对话旁展示线框图、原型和交互式选择。 + +**架构:** Claude 将 HTML 写入一个临时文件。一个本地 Node.js 服务器监视该文件,并通过一个自动注入的辅助库来提供该文件。用户交互通过 WebSocket 流到服务器的标准输出,Claude 可以在后台任务输出中看到这些交互。 + +**技术栈:** Node.js, Express, ws (WebSocket), chokidar (文件监视) + +*** + +## 任务 1:创建服务器基础 + +**文件:** + +* 创建:`lib/brainstorm-server/index.js` +* 创建:`lib/brainstorm-server/package.json` + +**步骤 1:创建 package.json** + +```json +{ + "name": "brainstorm-server", + "version": "1.0.0", + "description": "Visual brainstorming companion server for Claude Code", + "main": "index.js", + "dependencies": { + "chokidar": "^3.5.3", + "express": "^4.18.2", + "ws": "^8.14.2" + } +} +``` + +**步骤 2:创建可启动的最小服务器** + +```javascript +const express = require('express'); +const http = require('http'); +const WebSocket = require('ws'); +const chokidar = require('chokidar'); +const fs = require('fs'); +const path = require('path'); + +const PORT = process.env.BRAINSTORM_PORT || 3333; +const SCREEN_FILE = process.env.BRAINSTORM_SCREEN || '/tmp/brainstorm/screen.html'; +const SCREEN_DIR = path.dirname(SCREEN_FILE); + +// Ensure screen directory exists +if (!fs.existsSync(SCREEN_DIR)) { + fs.mkdirSync(SCREEN_DIR, { recursive: true }); +} + +// Create default screen if none exists +if (!fs.existsSync(SCREEN_FILE)) { + fs.writeFileSync(SCREEN_FILE, ` + + + Brainstorm Companion + + + +

Brainstorm Companion

+

Waiting for Claude to push a screen...

+ +`); +} + +const app = express(); +const server = http.createServer(app); +const wss = new WebSocket.Server({ server }); + +// Track connected browsers for reload notifications +const clients = new Set(); + +wss.on('connection', (ws) => { + clients.add(ws); + ws.on('close', () => clients.delete(ws)); + + ws.on('message', (data) => { + // User interaction event - write to stdout for Claude + const event = JSON.parse(data.toString()); + console.log(JSON.stringify({ type: 'user-event', ...event })); + }); +}); + +// Serve current screen with helper.js injected +app.get('/', (req, res) => { + let html = fs.readFileSync(SCREEN_FILE, 'utf-8'); + + // Inject helper script before + const helperScript = fs.readFileSync(path.join(__dirname, 'helper.js'), 'utf-8'); + const injection = ``; + + if (html.includes('')) { + html = html.replace('', `${injection}\n`); + } else { + html += injection; + } + + res.type('html').send(html); +}); + +// Watch for screen file changes +chokidar.watch(SCREEN_FILE).on('change', () => { + console.log(JSON.stringify({ type: 'screen-updated', file: SCREEN_FILE })); + // Notify all browsers to reload + clients.forEach(ws => { + if (ws.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify({ type: 'reload' })); + } + }); +}); + +server.listen(PORT, '127.0.0.1', () => { + console.log(JSON.stringify({ type: 'server-started', port: PORT, url: `http://localhost:${PORT}` })); +}); +``` + +**步骤 3:运行 npm install** + +运行:`cd lib/brainstorm-server && npm install` +预期:依赖项已安装 + +**步骤 4:测试服务器启动** + +运行:`cd lib/brainstorm-server && timeout 3 node index.js || true` +预期:看到包含 `server-started` 和端口信息的 JSON + +**步骤 5:提交** + +```bash +git add lib/brainstorm-server/ +git commit -m "feat: add brainstorm server foundation" +``` + +*** + +## 任务 2:创建辅助库 + +**文件:** + +* 创建:`lib/brainstorm-server/helper.js` + +**步骤 1:创建带有事件自动捕获功能的 helper.js** + +```javascript +(function() { + const WS_URL = 'ws://' + window.location.host; + let ws = null; + let eventQueue = []; + + function connect() { + ws = new WebSocket(WS_URL); + + ws.onopen = () => { + // Send any queued events + eventQueue.forEach(e => ws.send(JSON.stringify(e))); + eventQueue = []; + }; + + ws.onmessage = (msg) => { + const data = JSON.parse(msg.data); + if (data.type === 'reload') { + window.location.reload(); + } + }; + + ws.onclose = () => { + // Reconnect after 1 second + setTimeout(connect, 1000); + }; + } + + function send(event) { + event.timestamp = Date.now(); + if (ws && ws.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify(event)); + } else { + eventQueue.push(event); + } + } + + // Auto-capture clicks on interactive elements + document.addEventListener('click', (e) => { + const target = e.target.closest('button, a, [data-choice], [role="button"], input[type="submit"]'); + if (!target) return; + + // Don't capture regular link navigation + if (target.tagName === 'A' && !target.dataset.choice) return; + + e.preventDefault(); + + send({ + type: 'click', + text: target.textContent.trim(), + choice: target.dataset.choice || null, + id: target.id || null, + className: target.className || null + }); + }); + + // Auto-capture form submissions + document.addEventListener('submit', (e) => { + e.preventDefault(); + const form = e.target; + const formData = new FormData(form); + const data = {}; + formData.forEach((value, key) => { data[key] = value; }); + + send({ + type: 'submit', + formId: form.id || null, + formName: form.name || null, + data: data + }); + }); + + // Auto-capture input changes (debounced) + let inputTimeout = null; + document.addEventListener('input', (e) => { + const target = e.target; + if (!target.matches('input, textarea, select')) return; + + clearTimeout(inputTimeout); + inputTimeout = setTimeout(() => { + send({ + type: 'input', + name: target.name || null, + id: target.id || null, + value: target.value, + inputType: target.type || target.tagName.toLowerCase() + }); + }, 500); // 500ms debounce + }); + + // Expose for explicit use if needed + window.brainstorm = { + send: send, + choice: (value, metadata = {}) => send({ type: 'choice', value, ...metadata }) + }; + + connect(); +})(); +``` + +**步骤 2:验证 helper.js 语法有效** + +运行:`node -c lib/brainstorm-server/helper.js` +预期:无语法错误 + +**步骤 3:提交** + +```bash +git add lib/brainstorm-server/helper.js +git commit -m "feat: add browser helper library for event capture" +``` + +*** + +## 任务 3:为服务器编写测试 + +**文件:** + +* 创建:`tests/brainstorm-server/server.test.js` +* 创建:`tests/brainstorm-server/package.json` + +**步骤 1:创建测试 package.json** + +```json +{ + "name": "brainstorm-server-tests", + "version": "1.0.0", + "scripts": { + "test": "node server.test.js" + } +} +``` + +**步骤 2:编写服务器测试** + +```javascript +const { spawn } = require('child_process'); +const http = require('http'); +const WebSocket = require('ws'); +const fs = require('fs'); +const path = require('path'); +const assert = require('assert'); + +const SERVER_PATH = path.join(__dirname, '../../lib/brainstorm-server/index.js'); +const TEST_PORT = 3334; +const TEST_SCREEN = '/tmp/brainstorm-test/screen.html'; + +// Clean up test directory +function cleanup() { + if (fs.existsSync(path.dirname(TEST_SCREEN))) { + fs.rmSync(path.dirname(TEST_SCREEN), { recursive: true }); + } +} + +async function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +async function fetch(url) { + return new Promise((resolve, reject) => { + http.get(url, (res) => { + let data = ''; + res.on('data', chunk => data += chunk); + res.on('end', () => resolve({ status: res.statusCode, body: data })); + }).on('error', reject); + }); +} + +async function runTests() { + cleanup(); + + // Start server + const server = spawn('node', [SERVER_PATH], { + env: { ...process.env, BRAINSTORM_PORT: TEST_PORT, BRAINSTORM_SCREEN: TEST_SCREEN } + }); + + let stdout = ''; + server.stdout.on('data', (data) => { stdout += data.toString(); }); + server.stderr.on('data', (data) => { console.error('Server stderr:', data.toString()); }); + + await sleep(1000); // Wait for server to start + + try { + // Test 1: Server starts and outputs JSON + console.log('Test 1: Server startup message'); + assert(stdout.includes('server-started'), 'Should output server-started'); + assert(stdout.includes(TEST_PORT.toString()), 'Should include port'); + console.log(' PASS'); + + // Test 2: GET / returns HTML with helper injected + console.log('Test 2: Serves HTML with helper injected'); + const res = await fetch(`http://localhost:${TEST_PORT}/`); + assert.strictEqual(res.status, 200); + assert(res.body.includes('brainstorm'), 'Should include brainstorm content'); + assert(res.body.includes('WebSocket'), 'Should have helper.js injected'); + console.log(' PASS'); + + // Test 3: WebSocket connection and event relay + console.log('Test 3: WebSocket relays events to stdout'); + stdout = ''; // Reset stdout capture + const ws = new WebSocket(`ws://localhost:${TEST_PORT}`); + await new Promise(resolve => ws.on('open', resolve)); + + ws.send(JSON.stringify({ type: 'click', text: 'Test Button' })); + await sleep(100); + + assert(stdout.includes('user-event'), 'Should relay user events'); + assert(stdout.includes('Test Button'), 'Should include event data'); + ws.close(); + console.log(' PASS'); + + // Test 4: File change triggers reload notification + console.log('Test 4: File change notifies browsers'); + const ws2 = new WebSocket(`ws://localhost:${TEST_PORT}`); + await new Promise(resolve => ws2.on('open', resolve)); + + let gotReload = false; + ws2.on('message', (data) => { + const msg = JSON.parse(data.toString()); + if (msg.type === 'reload') gotReload = true; + }); + + // Modify the screen file + fs.writeFileSync(TEST_SCREEN, 'Updated'); + await sleep(500); + + assert(gotReload, 'Should send reload message on file change'); + ws2.close(); + console.log(' PASS'); + + console.log('\nAll tests passed!'); + + } finally { + server.kill(); + cleanup(); + } +} + +runTests().catch(err => { + console.error('Test failed:', err); + process.exit(1); +}); +``` + +**步骤 3:运行测试** + +运行:`cd tests/brainstorm-server && npm install ws && node server.test.js` +预期:所有测试通过 + +**步骤 4:提交** + +```bash +git add tests/brainstorm-server/ +git commit -m "test: add brainstorm server integration tests" +``` + +*** + +## 任务 4:将视觉伴侣添加到头脑风暴技能 + +**文件:** + +* 修改:`skills/brainstorming/SKILL.md` +* 创建:`skills/brainstorming/visual-companion.md` (支持文档) + +**步骤 1:创建支持文档** + +创建 `skills/brainstorming/visual-companion.md`: + +````markdown +# Visual Companion 参考 + +## 启动服务器 + +以后台任务运行: + +```bash +node ${PLUGIN_ROOT}/lib/brainstorm-server/index.js +```` + +告诉用户:"我已经在 http://localhost:3333 启动了一个视觉伴侣——请在浏览器中打开它。" + +## 推送屏幕 + +将 HTML 写入 `/tmp/brainstorm/screen.html`。服务器监视此文件并自动刷新浏览器。 + +## 读取用户响应 + +在后台任务输出中检查 JSON 事件: + +```json +{"type":"user-event","type":"click","text":"Option A","choice":"optionA","timestamp":1234567890} +{"type":"user-event","type":"submit","data":{"notes":"My feedback"},"timestamp":1234567891} +``` + +事件类型: + +* **click:** 用户点击了按钮或 `data-choice` 元素 +* **submit:** 用户提交了表单(包含所有表单数据) +* **input:** 用户在字段中输入了内容(防抖 500 毫秒) + +## HTML 模式 + +### 选择卡片 + +```html +
+ + +
+``` + +### 交互式线框图 + +```html +
+
App Header
+ +
Content
+
+``` + +### 带备注的表单 + +```html +
+ + + +
+``` + +### 显式 JavaScript + +```html + +``` + +```` +**第二步:为头脑风暴技能添加视觉伴侣部分** + +在 `skills/brainstorming/SKILL.md` 中的"核心原则"后添加: + +```markdown + +## 视觉伴侣(可选) + +当头脑风暴涉及视觉元素——UI 原型、线框图、交互式原型——时,使用基于浏览器的视觉伴侣。 + +**何时使用:** +- 展示受益于视觉比较的 UI/UX 方案 +- 展示线框图或布局选项 +- 收集结构化反馈(评分、表单) +- 原型点击交互 + +**工作原理:** +1. 将服务器作为后台作业启动 +2. 告知用户打开 http://localhost:3333 +3. 将 HTML 写入 `/tmp/brainstorm/screen.html`(自动刷新) +4. 检查后台任务输出以获取用户交互 + +终端仍是主要的对话界面。浏览器是一个视觉辅助工具。 + +**参考:** 查看此技能目录中的 `visual-companion.md` 以获取 HTML 模式和 API 详情。 +```` + +**步骤 3:验证编辑** + +运行:`grep -A5 "Visual Companion" skills/brainstorming/SKILL.md` +预期:显示新章节 + +**步骤 4:提交** + +```bash +git add skills/brainstorming/ +git commit -m "feat: add visual companion to brainstorming skill" +``` + +*** + +## 任务 5:将服务器添加到插件忽略列表(可选清理) + +**文件:** + +* 检查 `.gitignore` 是否需要为 lib/brainstorm-server 排除 node\_modules + +**步骤 1:检查当前的 gitignore** + +运行:`cat .gitignore 2>/dev/null || echo "No .gitignore"` + +**步骤 2:如果需要,添加 node\_modules** + +如果尚未存在,添加: + +``` +lib/brainstorm-server/node_modules/ +``` + +**步骤 3:如果更改则提交** + +```bash +git add .gitignore +git commit -m "chore: ignore brainstorm-server node_modules" +``` + +*** + +## 总结 + +完成所有任务后: + +1. **服务器**位于 `lib/brainstorm-server/` —— 监视 HTML 文件并中继事件的 Node.js 服务器 +2. **辅助库**自动注入 —— 捕获点击、表单、输入事件 +3. **测试**位于 `tests/brainstorm-server/` —— 验证服务器行为 +4. **头脑风暴技能**更新了视觉伴侣章节和 `visual-companion.md` 参考文档 + +**使用方法:** + +1. 将服务器作为后台任务启动:`node lib/brainstorm-server/index.js &` +2. 告诉用户打开 `http://localhost:3333` +3. 将 HTML 写入 `/tmp/brainstorm/screen.html` +4. 在任务输出中检查用户事件 diff --git a/zh-CN/docs/superpowers/plans/2026-01-22-document-review-system.md b/zh-CN/docs/superpowers/plans/2026-01-22-document-review-system.md new file mode 100644 index 0000000000..bcea5e9018 --- /dev/null +++ b/zh-CN/docs/superpowers/plans/2026-01-22-document-review-system.md @@ -0,0 +1,310 @@ +# 文档评审系统实施计划 + +> **对于智能体工作者:** 必需:使用 superpowers:子智能体驱动开发(如果子智能体可用)或 superpowers:执行计划来实现此计划。 + +**目标:** 为头脑风暴和编写计划技能添加规范和计划文档评审循环。 + +**架构:** 在每个技能目录中创建评审者提示模板。修改技能文件以在文档创建后添加评审循环。使用 Task 工具和通用子智能体进行评审者调度。 + +**技术栈:** Markdown 技能文件,通过 Task 工具进行子智能体调度 + +**规范:** docs/superpowers/specs/2026-01-22-document-review-system-design.md + +*** + +## 模块 1:规范文档评审者 + +此模块将规范文档评审者添加到头脑风暴技能中。 + +### 任务 1:创建规范文档评审者提示模板 + +**文件:** + +* 创建:`skills/brainstorming/spec-document-reviewer-prompt.md` + +* \[ ] **步骤 1:** 创建评审者提示模板文件 + +```markdown +# 规格文档审阅者提示模板 + +在派发规格文档审阅者子代理时使用此模板。 + +**目的:** 验证规格是否完整、一致,并已准备好进行实施规划。 + +**派发时机:** 规格文档已写入 docs/superpowers/specs/ +``` + +Task 工具(通用): +description: "评审规范文档" +prompt: | +您是一名规范文档评审者。请验证此规范是否完整并已准备好进行规划。 + +``` +**Spec to review:** [SPEC_FILE_PATH] + +## What to Check + +| Category | What to Look For | +|----------|------------------| +| Completeness | TODOs, placeholders, "TBD", incomplete sections | +| Coverage | Missing error handling, edge cases, integration points | +| Consistency | Internal contradictions, conflicting requirements | +| Clarity | Ambiguous requirements | +| YAGNI | Unrequested features, over-engineering | + +## CRITICAL + +Look especially hard for: +- Any TODO markers or placeholder text +- Sections saying "to be defined later" or "will spec when X is done" +- Sections noticeably less detailed than others + +## Output Format + +## Spec Review + +**Status:** ✅ Approved | ❌ Issues Found + +**Issues (if any):** +- [Section X]: [specific issue] - [why it matters] + +**Recommendations (advisory):** +- [suggestions that don't block approval] +``` + +``` +**审阅者返回:** 状态,问题(如有),建议 +``` + +* \[ ] **步骤 2:** 验证文件是否正确创建 + +运行:`cat skills/brainstorming/spec-document-reviewer-prompt.md | head -20` +预期:显示标题和目的部分 + +* \[ ] **步骤 3:** 提交 + +```bash +git add skills/brainstorming/spec-document-reviewer-prompt.md +git commit -m "feat: add spec document reviewer prompt template" +``` + +*** + +### 任务 2:将评审循环添加到头脑风暴技能 + +**文件:** + +* 修改:`skills/brainstorming/SKILL.md` + +* \[ ] **步骤 1:** 读取当前的头脑风暴技能 + +运行:`cat skills/brainstorming/SKILL.md` + +* \[ ] **步骤 2:** 在“设计之后”部分后添加评审循环部分 + +找到“设计之后”部分,并在文档之后、实施之前添加一个新的“规范评审循环”部分: + +```markdown +**规范审查循环:** +编写规范文档后: +1. 派发规范文档审查子代理(参见 spec-document-reviewer-prompt.md) +2. 若 ❌ 发现问题: + - 在规范文档中修复问题 + - 重新派发审查员 + - 重复直至 ✅ 获得批准 +3. 若 ✅ 获得批准:继续执行实施设置 + +**审查循环指导原则:** +- 由编写规范的同一代理进行修复(保持上下文一致) +- 若循环超过5次迭代,则提请人工指导 +- 审查员仅提供建议——若您认为反馈有误,请解释分歧点 +``` + +* \[ ] **步骤 3:** 验证更改 + +运行:`grep -A 15 "Spec Review Loop" skills/brainstorming/SKILL.md` +预期:显示新的评审循环部分 + +* \[ ] **步骤 4:** 提交 + +```bash +git add skills/brainstorming/SKILL.md +git commit -m "feat: add spec review loop to brainstorming skill" +``` + +*** + +## 模块 2:计划文档评审者 + +此模块将计划文档评审者添加到编写计划技能中。 + +### 任务 3:创建计划文档评审者提示模板 + +**文件:** + +* 创建:`skills/writing-plans/plan-document-reviewer-prompt.md` + +* \[ ] **步骤 1:** 创建评审者提示模板文件 + +```markdown +# 计划文档评审员提示模板 + +在派遣计划文档评审员子代理时使用此模板。 + +**目的:** 验证计划片段是否完整,是否符合规范,并具有适当的任务分解。 + +**派遣时机:** 每个计划片段撰写完成后 +``` + +Task 工具(通用): +description: "评审计划模块 N" +prompt: | +您是一名计划文档评审者。请验证此计划模块是否完整并已准备好实施。 + +``` +**Plan chunk to review:** [PLAN_FILE_PATH] - Chunk N only +**Spec for reference:** [SPEC_FILE_PATH] + +## What to Check + +| Category | What to Look For | +|----------|------------------| +| Completeness | TODOs, placeholders, incomplete tasks, missing steps | +| Spec Alignment | Chunk covers relevant spec requirements, no scope creep | +| Task Decomposition | Tasks atomic, clear boundaries, steps actionable | +| Task Syntax | Checkbox syntax (`- [ ]`) on tasks and steps | +| Chunk Size | Each chunk under 1000 lines | + +## CRITICAL + +Look especially hard for: +- Any TODO markers or placeholder text +- Steps that say "similar to X" without actual content +- Incomplete task definitions +- Missing verification steps or expected outputs + +## Output Format + +## Plan Review - Chunk N + +**Status:** ✅ Approved | ❌ Issues Found + +**Issues (if any):** +- [Task X, Step Y]: [specific issue] - [why it matters] + +**Recommendations (advisory):** +- [suggestions that don't block approval] +``` + +``` +**审阅者返回:** 状态,问题(如有),建议 +``` + +* \[ ] **步骤 2:** 验证文件已创建 + +运行:`cat skills/writing-plans/plan-document-reviewer-prompt.md | head -20` +预期:显示标题和目的部分 + +* \[ ] **步骤 3:** 提交 + +```bash +git add skills/writing-plans/plan-document-reviewer-prompt.md +git commit -m "feat: add plan document reviewer prompt template" +``` + +*** + +### 任务 4:将评审循环添加到编写计划技能 + +**文件:** + +* 修改:`skills/writing-plans/SKILL.md` + +* \[ ] **步骤 1:** 读取当前技能文件 + +运行:`cat skills/writing-plans/SKILL.md` + +* \[ ] **步骤 2:** 添加逐模块评审部分 + +在“执行交接”部分之前添加: + +```markdown +## 计划审查循环 + +完成每个计划区块后: + +1. 针对当前区块调度计划-文档-审查子代理 + - 提供:区块内容、规范文档路径 +2. 如果 ❌ 发现问题: + - 在区块中修复问题 + - 重新调度该区块的审查 + - 重复直到 ✅ 通过批准 +3. 如果 ✅ 通过批准:继续下一个区块(或如果是最后一个区块,则移交执行) + +**区块边界:** 使用 `## Chunk N: ` 标题来划分区块。每个区块应 ≤1000 行且在逻辑上自成一体。 +``` + +* \[ ] **步骤 3:** 更新任务语法示例以使用复选框 + +更改“任务结构”部分以显示复选框语法: + +```markdown +### 任务 N: [组件名称] + +- [ ] **步骤 1:** 编写失败的测试 + - 文件: `tests/path/test.py` + ... +``` + +* \[ ] **步骤 4:** 验证评审循环部分已添加 + +运行:`grep -A 15 "Plan Review Loop" skills/writing-plans/SKILL.md` +预期:显示新的评审循环部分 + +* \[ ] **步骤 5:** 验证任务语法示例已更新 + +运行:`grep -A 5 "Task N:" skills/writing-plans/SKILL.md` +预期:显示复选框语法 `### Task N:` + +* \[ ] **步骤 6:** 提交 + +```bash +git add skills/writing-plans/SKILL.md +git commit -m "feat: add plan review loop and checkbox syntax to writing-plans skill" +``` + +*** + +## 模块 3:更新计划文档标题 + +此模块更新计划文档标题模板,以引用新的复选框语法要求。 + +### 任务 5:在编写计划技能中更新计划标题模板 + +**文件:** + +* 修改:`skills/writing-plans/SKILL.md` + +* \[ ] **步骤 1:** 读取当前计划标题模板 + +运行:`grep -A 20 "Plan Document Header" skills/writing-plans/SKILL.md` + +* \[ ] **步骤 2:** 更新标题模板以引用复选框语法 + +计划标题应注明任务和步骤使用复选框语法。更新标题注释: + +```markdown +> **对于智能体工作者:** 必需:使用 superpowers:subagent-driven-development(如果子智能体可用)或 superpowers:executing-plans 来实施此计划。任务和步骤使用复选框(`- [ ]`)语法进行跟踪。 +``` + +* \[ ] **步骤 3:** 验证更改 + +运行:`grep -A 5 "For agentic workers:" skills/writing-plans/SKILL.md` +预期:显示提及复选框语法的更新后标题 + +* \[ ] **步骤 4:** 提交 + +```bash +git add skills/writing-plans/SKILL.md +git commit -m "docs: update plan header to reference checkbox syntax" +``` diff --git a/zh-CN/docs/superpowers/plans/2026-02-19-visual-brainstorming-refactor.md b/zh-CN/docs/superpowers/plans/2026-02-19-visual-brainstorming-refactor.md new file mode 100644 index 0000000000..e7bc2955ef --- /dev/null +++ b/zh-CN/docs/superpowers/plans/2026-02-19-visual-brainstorming-refactor.md @@ -0,0 +1,539 @@ +# 视觉化头脑风暴重构实施计划 + +> **对于智能体工作者:** 必需:使用 superpowers:subagent-driven-development(如果子智能体可用)或 superpowers:executing-plans 来实施此计划。步骤使用复选框(`- [ ]`)语法进行跟踪。 + +**目标:** 将视觉化头脑风暴从阻塞式 TUI 反馈模型重构为非阻塞式“浏览器显示,终端命令”架构。 + +**架构:** 浏览器成为交互式显示界面;终端保持为对话通道。服务器将用户事件写入一个每屏的 `.events` 文件,供 Claude 在其下一次轮次读取。消除 `wait-for-feedback.sh` 和所有 `TaskOutput` 阻塞。 + +**技术栈:** Node.js (Express, ws, chokidar), 原生 HTML/CSS/JS + +**规范:** `docs/superpowers/specs/2026-02-19-visual-brainstorming-refactor-design.md` + +*** + +## 文件映射 + +| 文件 | 操作 | 职责 | +|------|--------|---------------| +| `lib/brainstorm-server/index.js` | 修改 | 服务器:添加 `.events` 文件写入,在新屏幕时清除,替换 `wrapInFrame` | +| `lib/brainstorm-server/frame-template.html` | 修改 | 模板:移除反馈页脚,添加内容占位符 + 选择指示器 | +| `lib/brainstorm-server/helper.js` | 修改 | 客户端 JS:移除发送/反馈函数,精简为点击捕获 + 指示器更新 | +| `lib/brainstorm-server/wait-for-feedback.sh` | 删除 | 不再需要 | +| `skills/brainstorming/visual-companion.md` | 修改 | 技能说明:重写循环为非阻塞式流程 | +| `tests/brainstorm-server/server.test.js` | 修改 | 测试:更新以适应新模板结构和 helper.js API | + +*** + +## 块 1:服务器、模板、客户端、测试、技能 + +### 任务 1:更新 `frame-template.html` + +**文件:** + +* 修改:`lib/brainstorm-server/frame-template.html` + +* \[ ] **步骤 1:移除反馈页脚 HTML** + +将 feedback-footer div(第 227-233 行)替换为选择指示器栏: + +```html +
+ Click an option above, then return to the terminal +
+``` + +同时将 `#claude-content` 内的默认内容(第 220-223 行)替换为内容占位符: + +```html +
+ +
+``` + +* \[ ] **步骤 2:将反馈页脚 CSS 替换为指示器栏 CSS** + +移除 `.feedback-footer`、`.feedback-footer label`、`.feedback-row` 以及 `.feedback-footer` 内的 textarea/button 样式(第 82-112 行)。 + +添加指示器栏 CSS: + +```css + .indicator-bar { + background: var(--bg-secondary); + border-top: 1px solid var(--border); + padding: 0.5rem 1.5rem; + flex-shrink: 0; + text-align: center; + } + .indicator-bar span { + font-size: 0.75rem; + color: var(--text-secondary); + } + .indicator-bar .selected-text { + color: var(--accent); + font-weight: 500; + } +``` + +* \[ ] **步骤 3:验证模板渲染** + +运行测试套件以检查模板是否仍能加载: + +```bash +cd /Users/drewritter/prime-rad/superpowers && node tests/brainstorm-server/server.test.js +``` + +预期:测试 1-5 应仍通过。测试 6-8 可能失败(预期如此——它们断言的是旧结构)。 + +* \[ ] **步骤 4:提交** + +```bash +git add lib/brainstorm-server/frame-template.html +git commit -m "Replace feedback footer with selection indicator bar in brainstorm template" +``` + +*** + +### 任务 2:更新 `index.js` — 内容注入和 `.events` 文件 + +**文件:** + +* 修改:`lib/brainstorm-server/index.js` + +* \[ ] **步骤 1:为 `.events` 文件写入编写失败测试** + +在 `tests/brainstorm-server/server.test.js` 的测试 4 区域后添加——一个新的测试,发送带有 `choice` 字段的 WebSocket 事件,并验证 `.events` 文件被写入: + +```javascript + // Test: Choice events written to .events file + console.log('Test: Choice events written to .events file'); + const ws3 = new WebSocket(`ws://localhost:${TEST_PORT}`); + await new Promise(resolve => ws3.on('open', resolve)); + + ws3.send(JSON.stringify({ type: 'click', choice: 'a', text: 'Option A' })); + await sleep(300); + + const eventsFile = path.join(TEST_DIR, '.events'); + assert(fs.existsSync(eventsFile), '.events file should exist after choice click'); + const lines = fs.readFileSync(eventsFile, 'utf-8').trim().split('\n'); + const event = JSON.parse(lines[lines.length - 1]); + assert.strictEqual(event.choice, 'a', 'Event should contain choice'); + assert.strictEqual(event.text, 'Option A', 'Event should contain text'); + ws3.close(); + console.log(' PASS'); +``` + +* \[ ] **步骤 2:运行测试以验证其失败** + +```bash +cd /Users/drewritter/prime-rad/superpowers && node tests/brainstorm-server/server.test.js +``` + +预期:新测试失败——`.events` 文件尚不存在。 + +* \[ ] **步骤 3:为 `.events` 文件在新屏幕时清除编写失败测试** + +添加另一个测试: + +```javascript + // Test: .events cleared on new screen + console.log('Test: .events cleared on new screen'); + // .events file should still exist from previous test + assert(fs.existsSync(path.join(TEST_DIR, '.events')), '.events should exist before new screen'); + fs.writeFileSync(path.join(TEST_DIR, 'new-screen.html'), '

New screen

'); + await sleep(500); + assert(!fs.existsSync(path.join(TEST_DIR, '.events')), '.events should be cleared after new screen'); + console.log(' PASS'); +``` + +* \[ ] **步骤 4:运行测试以验证其失败** + +```bash +cd /Users/drewritter/prime-rad/superpowers && node tests/brainstorm-server/server.test.js +``` + +预期:新测试失败——`.events` 在推送屏幕时未被清除。 + +* \[ ] **步骤 5:在 `index.js` 中实现 `.events` 文件写入** + +在 WebSocket `message` 处理程序中(`index.js` 的第 74-77 行),`console.log` 之后,添加: + +```javascript + // Write user events to .events file for Claude to read + if (event.choice) { + const eventsFile = path.join(SCREEN_DIR, '.events'); + fs.appendFileSync(eventsFile, JSON.stringify(event) + '\n'); + } +``` + +在 chokidar `add` 处理程序中(第 104-111 行),添加 `.events` 清除: + +```javascript + if (filePath.endsWith('.html')) { + // Clear events from previous screen + const eventsFile = path.join(SCREEN_DIR, '.events'); + if (fs.existsSync(eventsFile)) fs.unlinkSync(eventsFile); + + console.log(JSON.stringify({ type: 'screen-added', file: filePath })); + // ... existing reload broadcast + } +``` + +* \[ ] **步骤 6:用注释占位符注入替换 `wrapInFrame`** + +替换 `wrapInFrame` 函数(`index.js` 的第 27-32 行): + +```javascript +function wrapInFrame(content) { + return frameTemplate.replace('', content); +} +``` + +* \[ ] **步骤 7:运行所有测试** + +```bash +cd /Users/drewritter/prime-rad/superpowers && node tests/brainstorm-server/server.test.js +``` + +预期:新的 `.events` 测试通过。现有测试可能仍有来自旧断言的失败(将在任务 4 中修复)。 + +* \[ ] **步骤 8:提交** + +```bash +git add lib/brainstorm-server/index.js tests/brainstorm-server/server.test.js +git commit -m "Add .events file writing and comment-based content injection to brainstorm server" +``` + +*** + +### 任务 3:简化 `helper.js` + +**文件:** + +* 修改:`lib/brainstorm-server/helper.js` + +* \[ ] **步骤 1:移除 `sendToClaude` 函数** + +删除 `sendToClaude` 函数(第 92-106 行)——函数体和页面接管 HTML。 + +* \[ ] **步骤 2:移除 `window.send` 函数** + +删除 `window.send` 函数(第 120-129 行)——该函数与已移除的发送按钮绑定。 + +* \[ ] **步骤 3:移除表单提交和输入变更处理程序** + +删除表单提交处理程序(第 57-71 行)和输入变更处理程序(第 73-89 行),包括 `inputTimeout` 变量。 + +* \[ ] **步骤 4:移除 `pageshow` 事件监听器** + +删除我们之前添加的 `pageshow` 监听器(不再有需要清除的文本域)。 + +* \[ ] **步骤 5:将点击处理程序精简为仅 `[data-choice]`** + +替换点击处理程序(第 36-55 行)为一个更精简的版本: + +```javascript + // Capture clicks on choice elements + document.addEventListener('click', (e) => { + const target = e.target.closest('[data-choice]'); + if (!target) return; + + sendEvent({ + type: 'click', + text: target.textContent.trim(), + choice: target.dataset.choice, + id: target.id || null + }); + }); +``` + +* \[ ] **步骤 6:在选择点击时添加指示器栏更新** + +在点击处理程序中的 `sendEvent` 调用后,添加: + +```javascript + // Update indicator bar + const indicator = document.getElementById('indicator-text'); + if (indicator) { + const label = target.querySelector('h3, .content h3, .card-body h3')?.textContent?.trim() || target.dataset.choice; + indicator.innerHTML = '' + label + ' selected — return to terminal to continue'; + } +``` + +* \[ ] **步骤 7:从 `window.brainstorm` API 中移除 `sendToClaude`** + +更新 `window.brainstorm` 对象(第 132-136 行)以移除 `sendToClaude`: + +```javascript + window.brainstorm = { + send: sendEvent, + choice: (value, metadata = {}) => sendEvent({ type: 'choice', value, ...metadata }) + }; +``` + +* \[ ] **步骤 8:运行测试** + +```bash +cd /Users/drewritter/prime-rad/superpowers && node tests/brainstorm-server/server.test.js +``` + +* \[ ] **步骤 9:提交** + +```bash +git add lib/brainstorm-server/helper.js +git commit -m "Simplify helper.js: remove feedback functions, narrow to choice capture + indicator" +``` + +*** + +### 任务 4:为新结构更新测试 + +**文件:** + +* 修改:`tests/brainstorm-server/server.test.js` + +**注意:** 下面的行号引用来自*原始*文件。任务 2 在文件更早位置插入了新测试,因此实际行号会发生偏移。通过 `console.log` 标签(例如 "Test 5:"、"Test 6:")查找测试。 + +* \[ ] **步骤 1:更新测试 5(完整文档断言)** + +找到测试 5 的断言 `!fullRes.body.includes('feedback-footer')`。将其更改为:完整文档不应该有指示器栏(它们按原样提供): + +```javascript + assert(!fullRes.body.includes('indicator-bar') || fullDoc.includes('indicator-bar'), + 'Should not wrap full documents in frame template'); +``` + +* \[ ] **步骤 2:更新测试 6(片段包装)** + +第 125 行:将 `feedback-footer` 断言替换为指示器栏断言: + +```javascript + assert(fragRes.body.includes('indicator-bar'), 'Fragment should get indicator bar from frame'); +``` + +同时验证内容占位符已被替换(片段内容出现,占位符注释不出现): + +```javascript + assert(!fragRes.body.includes(''), 'Content placeholder should be replaced'); +``` + +* \[ ] **步骤 3:更新测试 7(helper.js API)** + +第 140-142 行:更新断言以反映新的 API 接口: + +```javascript + assert(helperContent.includes('toggleSelect'), 'helper.js should define toggleSelect'); + assert(helperContent.includes('sendEvent'), 'helper.js should define sendEvent'); + assert(helperContent.includes('selectedChoice'), 'helper.js should track selectedChoice'); + assert(helperContent.includes('brainstorm'), 'helper.js should expose brainstorm API'); + assert(!helperContent.includes('sendToClaude'), 'helper.js should not contain sendToClaude'); +``` + +* \[ ] **步骤 4:将测试 8(sendToClaude 主题)替换为指示器栏测试** + +替换测试 8(第 145-149 行)——`sendToClaude` 不再存在。改为测试指示器栏: + +```javascript + // Test 8: Indicator bar uses CSS variables (theme support) + console.log('Test 8: Indicator bar uses CSS variables'); + const templateContent = fs.readFileSync( + path.join(__dirname, '../../lib/brainstorm-server/frame-template.html'), 'utf-8' + ); + assert(templateContent.includes('indicator-bar'), 'Template should have indicator bar'); + assert(templateContent.includes('indicator-text'), 'Template should have indicator text element'); + console.log(' PASS'); +``` + +* \[ ] **步骤 5:运行完整测试套件** + +```bash +cd /Users/drewritter/prime-rad/superpowers && node tests/brainstorm-server/server.test.js +``` + +预期:所有测试通过。 + +* \[ ] **步骤 6:提交** + +```bash +git add tests/brainstorm-server/server.test.js +git commit -m "Update brainstorm server tests for new template structure and helper.js API" +``` + +*** + +### 任务 5:删除 `wait-for-feedback.sh` + +**文件:** + +* 删除:`lib/brainstorm-server/wait-for-feedback.sh` + +* \[ ] **步骤 1:验证没有其他文件导入或引用 `wait-for-feedback.sh`** + +搜索代码库: + +```bash +grep -r "wait-for-feedback" /Users/drewritter/prime-rad/superpowers/ --include="*.js" --include="*.md" --include="*.sh" --include="*.json" +``` + +预期引用:只有 `visual-companion.md`(将在任务 6 中重写)以及可能的发布说明(历史记录,保留原样)。 + +* \[ ] **步骤 2:删除文件** + +```bash +rm lib/brainstorm-server/wait-for-feedback.sh +``` + +* \[ ] **步骤 3:运行测试以确认没有破坏任何东西** + +```bash +cd /Users/drewritter/prime-rad/superpowers && node tests/brainstorm-server/server.test.js +``` + +预期:所有测试通过(没有测试引用此文件)。 + +* \[ ] **步骤 4:提交** + +```bash +git add -u lib/brainstorm-server/wait-for-feedback.sh +git commit -m "Delete wait-for-feedback.sh: replaced by .events file" +``` + +*** + +### 任务 6:重写 `visual-companion.md` + +**文件:** + +* 修改:`skills/brainstorming/visual-companion.md` + +* \[ ] **步骤 1:更新“工作原理”描述(第 18 行)** + +将关于接收反馈“作为 JSON”的句子替换为: + +```markdown +服务器监视一个目录中的 HTML 文件,并将最新的一个提供给浏览器。你编写 HTML 内容,用户在其浏览器中查看,并可以通过点击来选择选项。选择会被记录到一个 `.events` 文件中,供你在下一回合读取。 +``` + +* \[ ] **步骤 2:更新片段描述(第 20 行)** + +从框架模板提供的描述中移除“反馈页脚”: + +```markdown +**内容片段与完整文档:** 如果您的 HTML 文件以 ` +``` + +* \[ ] **步骤 3:验证没有残留的陈旧引用** + +```bash +grep -r "wait-for-feedback\|sendToClaude\|feedback-footer\|send-to-claude\|TaskOutput.*block.*true" /Users/drewritter/prime-rad/superpowers/ --include="*.js" --include="*.md" --include="*.sh" --include="*.html" | grep -v node_modules | grep -v RELEASE-NOTES | grep -v "\.md:.*spec\|plan" +``` + +预期:除了发布说明和规范/计划文档(这些是历史记录)外,没有其他匹配项。 + +* \[ ] **步骤 4:如果需要任何清理,进行最终提交** + +```bash +git status +# Review untracked/modified files, stage specific files as needed, commit if clean +``` diff --git a/zh-CN/docs/superpowers/plans/2026-03-11-zero-dep-brainstorm-server.md b/zh-CN/docs/superpowers/plans/2026-03-11-zero-dep-brainstorm-server.md new file mode 100644 index 0000000000..dfe1547c2a --- /dev/null +++ b/zh-CN/docs/superpowers/plans/2026-03-11-zero-dep-brainstorm-server.md @@ -0,0 +1,490 @@ +# 零依赖头脑风暴服务器实现计划 + +> **针对智能体工作者:** 必需:使用 superpowers:子智能体驱动开发(如果子智能体可用)或 superpowers:执行计划 来实现此计划。步骤使用复选框(`- [ ]`)语法进行跟踪。 + +**目标:** 将头脑风暴服务器的第三方 node\_modules 替换为单个零依赖的 `server.js`,仅使用 Node 内置模块。 + +**架构:** 单个文件,包含 WebSocket 协议(RFC 6455 文本帧)、HTTP 服务器(`http` 模块)和文件监视(`fs.watch`)。当作为模块被需要时,导出协议函数以供单元测试。 + +**技术栈:** 仅使用 Node.js 内置模块:`http`, `crypto`, `fs`, `path` + +**规范:** `docs/superpowers/specs/2026-03-11-zero-dep-brainstorm-server-design.md` + +**现有测试:** `tests/brainstorm-server/ws-protocol.test.js`(单元测试),`tests/brainstorm-server/server.test.js`(集成测试) + +*** + +## 文件映射 + +* **创建:** `skills/brainstorming/scripts/server.js` — 零依赖替代文件 +* **修改:** `skills/brainstorming/scripts/start-server.sh:94,100` — 将 `index.js` 改为 `server.js` +* **修改:** `.gitignore:6` — 移除 `!skills/brainstorming/scripts/node_modules/` 例外 +* **删除:** `skills/brainstorming/scripts/index.js` +* **删除:** `skills/brainstorming/scripts/package.json` +* **删除:** `skills/brainstorming/scripts/package-lock.json` +* **删除:** `skills/brainstorming/scripts/node_modules/`(714 个文件) +* **无更改:** `skills/brainstorming/scripts/helper.js`, `skills/brainstorming/scripts/frame-template.html`, `skills/brainstorming/scripts/stop-server.sh` + +*** + +## 区块 1:WebSocket 协议层 + +### 任务 1:实现 WebSocket 协议导出 + +**文件:** + +* 创建:`skills/brainstorming/scripts/server.js` + +* 测试:`tests/brainstorm-server/ws-protocol.test.js`(已存在) + +* \[ ] **步骤 1:创建 server.js,包含 OPCODES 常量和 computeAcceptKey 函数** + +```js +const crypto = require('crypto'); + +const OPCODES = { TEXT: 0x01, CLOSE: 0x08, PING: 0x09, PONG: 0x0A }; +const WS_MAGIC = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'; + +function computeAcceptKey(clientKey) { + return crypto.createHash('sha1').update(clientKey + WS_MAGIC).digest('base64'); +} +``` + +* \[ ] **步骤 2:实现 encodeFrame 函数** + +服务器帧从不掩码。三种长度编码: + +* 载荷 < 126:2 字节头部(FIN+操作码,长度) +* 126-65535:4 字节头部(FIN+操作码,126,16 位长度) +* \> 65535:10 字节头部(FIN+操作码,127,64 位长度) + +```js +function encodeFrame(opcode, payload) { + const fin = 0x80; + const len = payload.length; + let header; + + if (len < 126) { + header = Buffer.alloc(2); + header[0] = fin | opcode; + header[1] = len; + } else if (len < 65536) { + header = Buffer.alloc(4); + header[0] = fin | opcode; + header[1] = 126; + header.writeUInt16BE(len, 2); + } else { + header = Buffer.alloc(10); + header[0] = fin | opcode; + header[1] = 127; + header.writeBigUInt64BE(BigInt(len), 2); + } + + return Buffer.concat([header, payload]); +} +``` + +* \[ ] **步骤 3:实现 decodeFrame 函数** + +客户端帧始终被掩码。返回 `{ opcode, payload, bytesConsumed }` 或 `null` 表示不完整。对未掩码的帧抛出错误。 + +```js +function decodeFrame(buffer) { + if (buffer.length < 2) return null; + + const firstByte = buffer[0]; + const secondByte = buffer[1]; + const opcode = firstByte & 0x0F; + const masked = (secondByte & 0x80) !== 0; + let payloadLen = secondByte & 0x7F; + let offset = 2; + + if (!masked) throw new Error('Client frames must be masked'); + + if (payloadLen === 126) { + if (buffer.length < 4) return null; + payloadLen = buffer.readUInt16BE(2); + offset = 4; + } else if (payloadLen === 127) { + if (buffer.length < 10) return null; + payloadLen = Number(buffer.readBigUInt64BE(2)); + offset = 10; + } + + const maskOffset = offset; + const dataOffset = offset + 4; + const totalLen = dataOffset + payloadLen; + if (buffer.length < totalLen) return null; + + const mask = buffer.slice(maskOffset, dataOffset); + const data = Buffer.alloc(payloadLen); + for (let i = 0; i < payloadLen; i++) { + data[i] = buffer[dataOffset + i] ^ mask[i % 4]; + } + + return { opcode, payload: data, bytesConsumed: totalLen }; +} +``` + +* \[ ] **步骤 4:在文件底部添加模块导出** + +```js +module.exports = { computeAcceptKey, encodeFrame, decodeFrame, OPCODES }; +``` + +* \[ ] **步骤 5:运行单元测试** + +运行:`cd tests/brainstorm-server && node ws-protocol.test.js` +预期:所有测试通过(握手、编码、解码、边界情况、边缘情况) + +* \[ ] **步骤 6:提交** + +```bash +git add skills/brainstorming/scripts/server.js +git commit -m "Add WebSocket protocol layer for zero-dep brainstorm server" +``` + +*** + +## 区块 2:HTTP 服务器和应用逻辑 + +### 任务 2:添加 HTTP 服务器、文件监视和 WebSocket 连接处理 + +**文件:** + +* 修改:`skills/brainstorming/scripts/server.js` + +* 测试:`tests/brainstorm-server/server.test.js`(已存在) + +* \[ ] **步骤 1:在 server.js 顶部(require 之后)添加配置和常量** + +```js +const http = require('http'); +const fs = require('fs'); +const path = require('path'); + +const PORT = process.env.BRAINSTORM_PORT || (49152 + Math.floor(Math.random() * 16383)); +const HOST = process.env.BRAINSTORM_HOST || '127.0.0.1'; +const URL_HOST = process.env.BRAINSTORM_URL_HOST || (HOST === '127.0.0.1' ? 'localhost' : HOST); +const SCREEN_DIR = process.env.BRAINSTORM_DIR || '/tmp/brainstorm'; + +const MIME_TYPES = { + '.html': 'text/html', '.css': 'text/css', '.js': 'application/javascript', + '.json': 'application/json', '.png': 'image/png', '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', '.gif': 'image/gif', '.svg': 'image/svg+xml' +}; +``` + +* \[ ] **步骤 2:添加 WAITING\_PAGE、模板加载(模块作用域)和辅助函数** + +在模块作用域加载 `frameTemplate` 和 `helperInjection`,以便 `wrapInFrame` 和 `handleRequest` 可以访问。它们只从 `__dirname`(脚本目录)读取文件,无论模块是被 require 还是直接运行,这都是有效的。 + +```js +const WAITING_PAGE = ` + +Brainstorm Companion + + +

Brainstorm Companion

+

Waiting for Claude to push a screen...

`; + +const frameTemplate = fs.readFileSync(path.join(__dirname, 'frame-template.html'), 'utf-8'); +const helperScript = fs.readFileSync(path.join(__dirname, 'helper.js'), 'utf-8'); +const helperInjection = ''; + +function isFullDocument(html) { + const trimmed = html.trimStart().toLowerCase(); + return trimmed.startsWith('', content); +} + +function getNewestScreen() { + const files = fs.readdirSync(SCREEN_DIR) + .filter(f => f.endsWith('.html')) + .map(f => { + const fp = path.join(SCREEN_DIR, f); + return { path: fp, mtime: fs.statSync(fp).mtime.getTime() }; + }) + .sort((a, b) => b.mtime - a.mtime); + return files.length > 0 ? files[0].path : null; +} +``` + +* \[ ] **步骤 3:添加 HTTP 请求处理器** + +```js +function handleRequest(req, res) { + if (req.method === 'GET' && req.url === '/') { + const screenFile = getNewestScreen(); + let html = screenFile + ? (raw => isFullDocument(raw) ? raw : wrapInFrame(raw))(fs.readFileSync(screenFile, 'utf-8')) + : WAITING_PAGE; + + if (html.includes('')) { + html = html.replace('', helperInjection + '\n'); + } else { + html += helperInjection; + } + + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end(html); + } else if (req.method === 'GET' && req.url.startsWith('/files/')) { + const fileName = req.url.slice(7); // strip '/files/' + const filePath = path.join(SCREEN_DIR, path.basename(fileName)); + if (!fs.existsSync(filePath)) { + res.writeHead(404); + res.end('Not found'); + return; + } + const ext = path.extname(filePath).toLowerCase(); + const contentType = MIME_TYPES[ext] || 'application/octet-stream'; + res.writeHead(200, { 'Content-Type': contentType }); + res.end(fs.readFileSync(filePath)); + } else { + res.writeHead(404); + res.end('Not found'); + } +} +``` + +* \[ ] **步骤 4:添加 WebSocket 连接处理** + +```js +const clients = new Set(); + +function handleUpgrade(req, socket) { + const key = req.headers['sec-websocket-key']; + if (!key) { socket.destroy(); return; } + + const accept = computeAcceptKey(key); + socket.write( + 'HTTP/1.1 101 Switching Protocols\r\n' + + 'Upgrade: websocket\r\n' + + 'Connection: Upgrade\r\n' + + 'Sec-WebSocket-Accept: ' + accept + '\r\n\r\n' + ); + + let buffer = Buffer.alloc(0); + clients.add(socket); + + socket.on('data', (chunk) => { + buffer = Buffer.concat([buffer, chunk]); + while (buffer.length > 0) { + let result; + try { + result = decodeFrame(buffer); + } catch (e) { + socket.end(encodeFrame(OPCODES.CLOSE, Buffer.alloc(0))); + clients.delete(socket); + return; + } + if (!result) break; + buffer = buffer.slice(result.bytesConsumed); + + switch (result.opcode) { + case OPCODES.TEXT: + handleMessage(result.payload.toString()); + break; + case OPCODES.CLOSE: + socket.end(encodeFrame(OPCODES.CLOSE, Buffer.alloc(0))); + clients.delete(socket); + return; + case OPCODES.PING: + socket.write(encodeFrame(OPCODES.PONG, result.payload)); + break; + case OPCODES.PONG: + break; + default: + // Unsupported opcode — close with 1003 + const closeBuf = Buffer.alloc(2); + closeBuf.writeUInt16BE(1003); + socket.end(encodeFrame(OPCODES.CLOSE, closeBuf)); + clients.delete(socket); + return; + } + } + }); + + socket.on('close', () => clients.delete(socket)); + socket.on('error', () => clients.delete(socket)); +} + +function handleMessage(text) { + let event; + try { + event = JSON.parse(text); + } catch (e) { + console.error('Failed to parse WebSocket message:', e.message); + return; + } + console.log(JSON.stringify({ source: 'user-event', ...event })); + if (event.choice) { + const eventsFile = path.join(SCREEN_DIR, '.events'); + fs.appendFileSync(eventsFile, JSON.stringify(event) + '\n'); + } +} + +function broadcast(msg) { + const frame = encodeFrame(OPCODES.TEXT, Buffer.from(JSON.stringify(msg))); + for (const socket of clients) { + try { socket.write(frame); } catch (e) { clients.delete(socket); } + } +} +``` + +* \[ ] **步骤 5:添加防抖计时器映射** + +```js +const debounceTimers = new Map(); +``` + +文件监视逻辑内联在 `startServer`(步骤 6)中,以便将监视器生命周期与服务器生命周期保持在一起,并根据规范包含一个 `error` 处理器。 + +* \[ ] **步骤 6:添加 startServer 函数和条件主逻辑** + +`frameTemplate` 和 `helperInjection` 已在模块作用域(步骤 2)。`startServer` 只是创建屏幕目录、启动 HTTP 服务器、监视器并记录启动信息。 + +```js +function startServer() { + if (!fs.existsSync(SCREEN_DIR)) fs.mkdirSync(SCREEN_DIR, { recursive: true }); + + const server = http.createServer(handleRequest); + server.on('upgrade', handleUpgrade); + + const watcher = fs.watch(SCREEN_DIR, (eventType, filename) => { + if (!filename || !filename.endsWith('.html')) return; + if (debounceTimers.has(filename)) clearTimeout(debounceTimers.get(filename)); + debounceTimers.set(filename, setTimeout(() => { + debounceTimers.delete(filename); + const filePath = path.join(SCREEN_DIR, filename); + if (eventType === 'rename' && fs.existsSync(filePath)) { + const eventsFile = path.join(SCREEN_DIR, '.events'); + if (fs.existsSync(eventsFile)) fs.unlinkSync(eventsFile); + console.log(JSON.stringify({ type: 'screen-added', file: filePath })); + } else if (eventType === 'change') { + console.log(JSON.stringify({ type: 'screen-updated', file: filePath })); + } + broadcast({ type: 'reload' }); + }, 100)); + }); + watcher.on('error', (err) => console.error('fs.watch error:', err.message)); + + server.listen(PORT, HOST, () => { + const info = JSON.stringify({ + type: 'server-started', port: Number(PORT), host: HOST, + url_host: URL_HOST, url: 'http://' + URL_HOST + ':' + PORT, + screen_dir: SCREEN_DIR + }); + console.log(info); + fs.writeFileSync(path.join(SCREEN_DIR, '.server-info'), info + '\n'); + }); +} + +if (require.main === module) { + startServer(); +} +``` + +* \[ ] **步骤 7:运行集成测试** + +测试目录已有一个 `package.json`,依赖 `ws`。如果需要,请安装它,然后运行测试。 + +运行:`cd tests/brainstorm-server && npm install && node server.test.js` +预期:所有测试通过 + +* \[ ] **步骤 8:提交** + +```bash +git add skills/brainstorming/scripts/server.js +git commit -m "Add HTTP server, WebSocket handling, and file watching to server.js" +``` + +*** + +## 区块 3:替换和清理 + +### 任务 3:更新 start-server.sh 并删除旧文件 + +**文件:** + +* 修改:`skills/brainstorming/scripts/start-server.sh:94,100` + +* 修改:`.gitignore:6` + +* 删除:`skills/brainstorming/scripts/index.js` + +* 删除:`skills/brainstorming/scripts/package.json` + +* 删除:`skills/brainstorming/scripts/package-lock.json` + +* 删除:`skills/brainstorming/scripts/node_modules/`(整个目录) + +* \[ ] **步骤 1:更新 start-server.sh — 将 `index.js` 改为 `server.js`** + +需要更改两行: + +第 94 行:`env BRAINSTORM_DIR="$SCREEN_DIR" BRAINSTORM_HOST="$BIND_HOST" BRAINSTORM_URL_HOST="$URL_HOST" node server.js` + +第 100 行:`nohup env BRAINSTORM_DIR="$SCREEN_DIR" BRAINSTORM_HOST="$BIND_HOST" BRAINSTORM_URL_HOST="$URL_HOST" node server.js > "$LOG_FILE" 2>&1 &` + +* \[ ] **步骤 2:移除对 node\_modules 的 gitignore 例外** + +在 `.gitignore` 中,删除第 6 行:`!skills/brainstorming/scripts/node_modules/` + +* \[ ] **步骤 3:删除旧文件** + +```bash +git rm skills/brainstorming/scripts/index.js +git rm skills/brainstorming/scripts/package.json +git rm skills/brainstorming/scripts/package-lock.json +git rm -r skills/brainstorming/scripts/node_modules/ +``` + +* \[ ] **步骤 4:运行两个测试套件** + +运行:`cd tests/brainstorm-server && node ws-protocol.test.js && node server.test.js` +预期:所有测试通过 + +* \[ ] **步骤 5:提交** + +```bash +git add skills/brainstorming/scripts/ .gitignore +git commit -m "Remove vendored node_modules, swap to zero-dep server.js" +``` + +### 任务 4:手动冒烟测试 + +* \[ ] **步骤 1:手动启动服务器** + +```bash +cd skills/brainstorming/scripts +BRAINSTORM_DIR=/tmp/brainstorm-smoke BRAINSTORM_PORT=9876 node server.js +``` + +预期:打印 `server-started` JSON,端口为 9876 + +* \[ ] **步骤 2:在浏览器中打开 http://localhost:9876** + +预期:显示等待页面,内容为"Waiting for Claude to push a screen..." + +* \[ ] **步骤 3:向屏幕目录写入一个 HTML 文件** + +```bash +echo '

Hello from smoke test

' > /tmp/brainstorm-smoke/test.html +``` + +预期:浏览器刷新并显示"Hello from smoke test",包裹在框架模板中 + +* \[ ] **步骤 4:验证 WebSocket 是否正常工作 — 检查浏览器控制台** + +打开浏览器开发者工具。WebSocket 连接应显示为已连接(控制台无错误)。框架模板的状态指示器应显示"Connected"。 + +* \[ ] **步骤 5:使用 Ctrl-C 停止服务器,清理** + +```bash +rm -rf /tmp/brainstorm-smoke +``` diff --git a/zh-CN/docs/superpowers/specs/2026-01-22-document-review-system-design.md b/zh-CN/docs/superpowers/specs/2026-01-22-document-review-system-design.md new file mode 100644 index 0000000000..cdf2243b39 --- /dev/null +++ b/zh-CN/docs/superpowers/specs/2026-01-22-document-review-system-design.md @@ -0,0 +1,146 @@ +# 文档评审系统设计 + +## 概述 + +在 superpowers 工作流中新增两个评审阶段: + +1. **规格说明书评审** - 头脑风暴之后,编写计划之前 +2. **计划文档评审** - 编写计划之后,实施之前 + +两者都遵循实施评审所使用的迭代循环模式。 + +## 规格说明书评审员 + +**目的:** 验证规格说明书是否完整、一致,并已准备好用于实施规划。 + +**位置:** `skills/brainstorming/spec-document-reviewer-prompt.md` + +**检查内容:** + +| 类别 | 需要关注的点 | +|------|--------------| +| 完整性 | TODO项、占位符、"TBD"、不完整的章节 | +| 覆盖度 | 缺失的错误处理、边界情况、集成点 | +| 一致性 | 内部矛盾、冲突的需求 | +| 清晰度 | 模糊不清的需求 | +| YAGNI(你不需要它) | 未要求的功能、过度设计 | + +**输出格式:** + +``` +## 规格评审 + +**状态:** 已批准 | 发现问题 + +**问题(如有):** +- [章节 X]: [问题] - [原因说明] + +**建议(仅供参考):** +- [不影响批准的建议] +``` + +**评审循环:** 发现问题 -> 头脑风暴代理修复 -> 重新评审 -> 重复直至批准。 + +**调度机制:** 使用任务工具 `subagent_type: general-purpose`。评审员提示模板提供了完整的提示。头脑风暴技能的控制器负责调度评审员。 + +## 计划文档评审员 + +**目的:** 验证计划是否完整、与规格说明书匹配,并且具有正确的任务分解。 + +**位置:** `skills/writing-plans/plan-document-reviewer-prompt.md` + +**检查内容:** + +| 类别 | 需要关注的点 | +|------|--------------| +| 完整性 | TODO项、占位符、不完整的任务 | +| 规格对齐 | 计划覆盖了规格需求,无范围蔓延 | +| 任务分解 | 任务具有原子性,边界清晰 | +| 任务语法 | 任务和步骤的复选框语法 | +| 区块大小 | 每个区块少于 1000 行 | + +**区块定义:** 区块是计划文档内任务的逻辑分组,由 `## Chunk N: ` 标题分隔。编写计划技能根据逻辑阶段(例如"基础"、"核心功能"、"集成")创建这些边界。每个区块应足够自包含,以便独立评审。 + +**规格对齐验证:** 评审员接收以下两项: + +1. 计划文档(或当前区块) +2. 用于参考的规格说明书路径 + +评审员读取两者并比较需求覆盖情况。 + +**输出格式:** 与规格说明书评审员相同,但范围限定在当前区块。 + +**评审流程(逐区块):** + +1. 编写计划创建区块 N +2. 控制器调度计划文档评审员,附带区块 N 内容和规格说明书路径 +3. 评审员读取区块和规格说明书,返回裁决 +4. 如果发现问题:编写计划代理修复区块 N,转到步骤 2 +5. 如果批准:继续处理区块 N+1 +6. 重复直到所有区块获得批准 + +**调度机制:** 与规格说明书评审员相同 - 使用任务工具 `subagent_type: general-purpose`。 + +## 更新后的工作流 + +``` +brainstorming -> spec -> SPEC REVIEW LOOP -> writing-plans -> plan -> PLAN REVIEW LOOP -> implementation +``` + +**规格评审循环:** + +1. 规格说明书完成 +2. 调度评审员 +3. 如果发现问题:修复 -> 转到 2 +4. 如果批准:继续 + +**计划评审循环:** + +1. 区块 N 完成 +2. 为区块 N 调度评审员 +3. 如果发现问题:修复 -> 转到 2 +4. 如果批准:处理下一个区块或进入实施阶段 + +## Markdown 任务语法 + +任务和步骤使用复选框语法: + +```markdown +- [ ] ### 任务 1:名称 + +- [ ] **步骤 1:描述** + - 文件:路径 + - 命令:cmd +``` + +## 错误处理 + +**评审循环终止:** + +* 无硬性迭代限制 - 循环持续直到评审员批准 +* 如果循环超过 5 次迭代,控制器应将此情况呈现给人类以寻求指导 +* 人类可以选择:继续迭代、批准已知问题或中止 + +**分歧处理:** + +* 评审员是建议性的 - 他们标记问题但不阻塞 +* 如果代理认为评审员的反馈不正确,应在修复中解释原因 +* 如果同一问题在 3 次迭代后仍存在分歧,则呈现给人类 + +**评审员输出格式错误:** + +* 控制器应验证评审员输出是否具有必填字段(状态,以及适用时的"问题") +* 如果格式错误,重新调度评审员并附带关于预期格式的说明 +* 在 2 次格式错误的响应后,呈现给人类 + +## 需要更改的文件 + +**新增文件:** + +* `skills/brainstorming/spec-document-reviewer-prompt.md` +* `skills/writing-plans/plan-document-reviewer-prompt.md` + +**修改文件:** + +* `skills/brainstorming/SKILL.md` - 在规格说明书编写后添加评审循环 +* `skills/writing-plans/SKILL.md` - 添加逐区块评审循环,更新任务语法示例 diff --git a/zh-CN/docs/superpowers/specs/2026-02-19-visual-brainstorming-refactor-design.md b/zh-CN/docs/superpowers/specs/2026-02-19-visual-brainstorming-refactor-design.md new file mode 100644 index 0000000000..929e61f623 --- /dev/null +++ b/zh-CN/docs/superpowers/specs/2026-02-19-visual-brainstorming-refactor-design.md @@ -0,0 +1,174 @@ +# 可视化头脑风暴重构:浏览器显示与终端命令 + +**日期:** 2026-02-19 +**状态:** 已批准 +**范围:** `lib/brainstorm-server/`, `skills/brainstorming/visual-companion.md`, `tests/brainstorm-server/` + +## 问题 + +在可视化头脑风暴过程中,Claude 将 `wait-for-feedback.sh` 作为后台任务运行并阻塞在 `TaskOutput(block=true, timeout=600s)` 上。这会完全占用 TUI —— 在可视化头脑风暴运行时用户无法向 Claude 输入。浏览器成为唯一的输入通道。 + +Claude Code 的执行模型是基于轮次的。Claude 无法在一个轮次内同时监听两个通道。阻塞式的 `TaskOutput` 模式是错误的原语 —— 它模拟了平台不支持的基于事件的行为。 + +## 设计 + +### 核心模型 + +**浏览器 = 交互式显示。** 显示设计稿,让用户点击选择选项。选择结果记录在服务器端。 + +**终端 = 对话通道。** 始终保持畅通,始终可用。用户在此与 Claude 对话。 + +### 循环流程 + +1. Claude 将 HTML 文件写入会话目录 +2. 服务器通过 chokidar 检测到该文件,通过 WebSocket 推送重新加载指令到浏览器(保持不变) +3. Claude 结束其轮次 —— 告诉用户检查浏览器并在终端中回应 +4. 用户查看浏览器,可选地点击选择选项,然后在终端中输入反馈 +5. 在下一轮次中,Claude 读取 `$SCREEN_DIR/.events` 以获取浏览器交互流(点击、选择),并与终端文本合并 +6. 迭代或推进 + +无后台任务。无 `TaskOutput` 阻塞。无轮询脚本。 + +### 关键删除项:`wait-for-feedback.sh` + +完全删除。其目的是在“服务器将事件记录到标准输出”和“Claude 需要接收这些事件”之间建立桥梁。`.events` 文件取代了它 —— 服务器直接写入用户交互事件,而 Claude 使用平台提供的任何文件读取机制来读取它们。 + +### 关键新增项:`.events` 文件(每屏幕事件流) + +服务器将所有用户交互事件写入 `$SCREEN_DIR/.events`,每行一个 JSON 对象。这为 Claude 提供了当前屏幕的完整交互流 —— 不仅仅是最终选择,还包括用户的探索路径(点击了 A,然后 B,最终选定 C)。 + +用户探索选项后的示例内容: + +```jsonl +{"type":"click","choice":"a","text":"Option A - Preset-First Wizard","timestamp":1706000101} +{"type":"click","choice":"c","text":"Option C - Manual Config","timestamp":1706000108} +{"type":"click","choice":"b","text":"Option B - Hybrid Approach","timestamp":1706000115} +``` + +* 在单个屏幕内是追加写入。每个用户事件都作为新行追加。 +* 当 chokidar 检测到新的 HTML 文件(推送新屏幕)时,文件会被清除(删除),防止陈旧的事件延续。 +* 如果 Claude 读取时文件不存在,则表示没有发生浏览器交互 —— Claude 仅使用终端文本。 +* 该文件仅包含用户事件(`click` 等)—— 不包含服务器生命周期事件(`server-started`、`screen-added`)。这使其保持小巧且专注。 +* Claude 可以读取完整流来理解用户的探索模式,或者仅查看最后的 `choice` 事件以获取最终选择。 + +## 按文件划分的变更 + +### `index.js`(服务器) + +**A. 将用户事件写入 `.events` 文件。** + +在 WebSocket `message` 处理程序中,将事件记录到标准输出后:通过 `fs.appendFileSync` 将事件作为 JSON 行追加到 `$SCREEN_DIR/.events`。仅写入用户交互事件(那些带有 `source: 'user-event'` 的),不写入服务器生命周期事件。 + +**B. 在新屏幕时清除 `.events`。** + +在 chokidar `add` 处理程序(检测到新的 `.html` 文件)中,如果 `$SCREEN_DIR/.events` 存在则删除它。这是明确的“新屏幕”信号 —— 比在每次重新加载都会触发的 GET `/` 时清除更好。 + +**C. 替换 `wrapInFrame` 内容注入。** + +当前的正则表达式锚定在 `