关于 ship
Ship 是一项用于软件功能交付的技能,覆盖从规格制定到审核就绪分支的完整流程。它支持交互式协作和无交互的 headless 模式,并通过状态文件在阶段间保存进度。
主要功能
- 01从规格推进至审核就绪分支
- 02支持交互式与 headless 模式
- 03分阶段执行实现、文档和 QA
- 04通过状态文件恢复工作进度
- 05运行本地审核与质量检查
适用场景
- 01将已提供的规格端到端交付
- 02协作定义功能需求并启动实现
- 03在中断后恢复未完成的交付流程
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ inkeep/ team-skills --skill ship安装后在 Claude Code 中输入/ship确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/capability-detection.mdcompletion-checklist.mdstate-initialization.mdworktree-setup.mdscripts/build-local-review-fix-prompt.shparse-local-review-summary.shrun-local-review.shship-init-state.shship-upload-pr-asset.jsship-worktree.shstage-local-review-bundle.shtest-build-local-review-fix-prompt.shtest-exit-payload.shtest-parse-local-review-summary.shtest-run-local-review.shtest-ship-worktree.sh详细介绍
Ship
此技能有两种交互模式:
- 交互式(默认):在编写规范(阶段 1)期间,你是协作式的思考伙伴——用户是产品负责人,你们一起确定要构建什么。规范定稿且用户移交实现工作后,你将成为自主工程师,负责完成剩余生命周期。
- 无头模式(
--headless,或将完整规范作为输入):整个工作流从头到尾运行,无需任何用户交互。每个阶段都会执行,每项技能都会加载,每份检查清单都会运行。通常需要通过<input>确认的决策,将由你自主做出,并记录在完成报告中。
进入自主执行阶段后(交互模式下为阶段 1 移交之后,无头模式下则从一开始),你就是负责整个生命周期的自主工程师:从 spec.json 到可供审核的分支。/implement 和本地审核者都是工具和输入。你做出所有最终决策。
Ship Loop 重新进入
如果你的提示以 [SHIP-LOOP] 开头,说明你正处于工作流中途——停止钩子在上下文压缩或尝试退出后重新注入了提示。不要从阶段 0 重新开始。提示中包含:
-
**标头:**当前阶段、已完成阶段、分支、规范路径
-
状态文件(自动注入):
state.json、SPEC.md、spec.json和progress.txt(末尾部分)——均位于=== STATE FILES ===分隔符之间。 -
**Git 状态(自动注入):**已筛选的
git status、git diff --stat、按分支筛选的提交日志和分支跟踪状态——均位于=== GIT STATE ===分隔符之间。已预先过滤无关内容(锁文件、构建产物、tmp/ship/)。 -
系统消息中的 SKILL.md 提供完整的阶段参考
所有自动注入的内容都已在你的提示中——不要重新读取状态文件,也不要重新运行 Git 命令(git status、git log、git diff)。
直接跳转到当前阶段对应的部分。你的首要任务是从上次中断处继续——状态文件和 Git 状态已提供所需的全部信息。
后台进程处理
启动后台进程(implement.sh、run-local-review.sh、嵌套的 claude -p)时,按照状态更新表中的“Background process launched”行,将其记录在 state.json 中。
**重要原因:**当 backgroundProcesses 中包含运行中的条目时,停止钩子允许退出。否则钩子会阻止退出并重新注入完整状态——但 Agent 没有新任务可做,于是结束当前轮次,钩子再次阻止退出,如此循环直至上下文耗尽。允许退出后,Claude Code 内置的等待循环可以无限期等待后台任务完成,并在下一轮收到 <task-notification>。
**后台任务完成后重新进入时:**处理完 <task-notification> 的下一轮中,停止钩子会触发。此时 PID 已结束(进程已完成)。钩子会清理 backgroundProcesses 中已结束的条目,并重新注入完整状态。检查注入的 state.json 中的 backgroundProcesses——如果仍有条目,请确认工作已完成:
- **
implement.sh:**检查spec.json中的故事进度(passes: true/false)。读取progress.txt。移除该条目。继续当前阶段。 - **
run-local-review.sh:**检查review-status.json。移除该条目。继续当前阶段。 - **嵌套的
claude -p:**检查预期输出产物(阶段 4 已提交的文档、阶段 6/7 的qa-progress.json)。移除该条目。继续当前阶段。 - 任务未完成便已终止(没有输出产物,也没有进度):移除该条目。根据已生成的部分产物,判断是否需要重新启动。
处理完所有后台进程后,将 state.json 中的 backgroundProcesses 清空为 [],然后继续当前阶段。
上下文由系统管理——切勿仓促推进各阶段
交付循环具有自动保存状态并重启的机制。如果你的上下文所剩不多,停止钩子会保存你的完整状态(state.json、SPEC.md、spec.json、进度日志),并将你重新注入正确的阶段,同时提供继续工作所需的一切。这是有意设计的机制,并非故障。
**这对你意味着:**上下文不是你需要在各阶段之间精打细算的资源。不要因为预计上下文即将耗尽,就压缩、仓促推进或跳过任何阶段。每个阶段都要深入开展,按需加载所有必需的技能、执行所有检查清单,并委派子 Agent 进行调查。如果在某个阶段中途耗尽上下文,系统会自动处理后续衔接。
**此机制旨在防止的失败模式:**如果 Agent 因为“上下文快用完了”而仓促完成第 4 至第 9 阶段(文档、评审、QA 规划、测试、评审、完成),最终交付的工作就会不完整。干净重启后,以完整上下文重新进入第 4 阶段,比在精力耗尽时压缩完成后续阶段,能带来更好的结果。
无头模式
当以下情况满足时,Ship 会进入无头模式:
$ARGUMENTS包含--headless,或- 输入是提供的规范(指向现有 SPEC.md 的路径、内联 SPEC.md 内容或 spec.json)
无头模式意味着整个工作流期间都没有人类参与。 每个阶段都会运行,每项技能都会加载,每份清单都会执行,但没有任何阶段会暂停等待用户输入。
无头模式下的行为规则:
- 所有阶段均自主运行。 不存在协作阶段。跳过阶段 1 的规范编写(规范已提供)。仍会执行阶段 1 的验证——缺失的信息会用合理的默认值补全,而不是通过提问获取。
- 绝不输出
<input>。 禁用<input>暂停机制。对于通常需要人类判断的决策,应依据通过/research、/explore和代码库调查收集的证据自主作出。每项此类决策都必须记录在完成报告中。 - 绝不提问。 任何时候都不要请求确认、澄清或批准。如果状态存在,阶段 0 的恢复会自动继续。阶段转换无需经过确认环节。
- 审查关卡仅供参考。 如果审查关卡在达到最大自动修复次数后仍未收敛,应记录剩余问题并继续。不要陷入僵局。
- 向所有支持
--headless的子技能传递--headless(/qa、/debug、/qa-plan)。对于嵌套子进程(阶段 3、5、6),按/nest-claude约定启用非交互模式。 - 必须加载每项技能。 对于工作流要求加载的技能,不得以直接操作代替。每一步都必须加载所有技能——它们包含无头模式仍须遵循的质量关卡和清单。
- 内联规范内容: 如果输入是内联 SPEC.md 内容(而非文件路径),则在继续之前将其写入
specs/<feature-name>/SPEC.md。根据规范标题或问题陈述确定功能名称。
headless 标志会记录在 state.json 中(参见 references/state-initialization.md),并在压缩上下文或重新进入时保留。重新进入时,Agent 会从 state.json 中读取 headless: true,并继续以无头模式运行。
⚠️ 已知错误:子进程执行历来会跳过后续阶段。
当 /ship 本身作为嵌套的 claude -p 子进程运行时(例如通过 /nest-claude 委派),由于上下文压缩导致子进程状态跟踪丢失,阶段 5–9 历来会被跳过。这是错误行为,不可接受。 如果你是 Ship 编排器,无论是在子进程中还是顶层对话中,都必须执行每个阶段。此错误的存在不代表可以跳过任何阶段。
如果你不是作为子进程运行(即你是顶层 Agent 或以交互方式运行),则完全不受此限制影响。执行每个阶段。
如果你是作为子进程运行: 抵制跳过阶段的倾向。加载每项技能,启动每个子进程,运行每个阶段。如果上下文压缩中断了你,停止钩子会在正确的阶段重新注入你——相信它,并从那里继续。
Ship 工作目录
所有执行状态都存储在可配置的工作目录中(已加入 gitignore)。解析优先级如下:
| 优先级 | 来源 | 默认值 |
|---|---|---|
| 1 | 会话锚点(按 session_id 索引,由 ship-worktree.sh 写入——仅供停止钩子使用) | -- |
| 2 | 环境变量 CLAUDE_SHIP_DIR_OVERRIDE(用于 Docker/CI/隔离环境的显式覆盖) | -- |
| 3 | 根据 git 根目录动态解析 | $(git rev-parse --show-toplevel)/tmp/ship |
Ship 脚本会根据 git rev-parse --show-toplevel 动态解析 Ship 目录——无需手动维护环境变量。在此技能及其子技能(/implement、/cancel-ship)中,tmp/ship/ 指解析后的 Ship 目录。Shell 脚本(ship-init-state.sh、implement.sh、ship-stop-hook.sh)会动态解析此目录——每个工作树都会自动获得自己的 tmp/ship/ 目录。
进入工作树后,脚本会通过 git rev-parse 自动将目录解析为该工作树的 tmp/ship/。
状态文件
所有执行状态都存储在 tmp/ship/ 中(已加入 gitignore)。唯一提交的产物是 SPEC.md。子技能(/spec、/implement)会管理各自的内部产物——详情请参阅它们的 SKILL.md 文件。
| 文件 | 内容 | 创建时间 | 更新时间 | 读取者 |
|---|---|---|---|---|
tmp/ship/state.json | 工作流状态——当前阶段、功能名称、规格路径、分支、能力、质量关卡、修订、后台进程 | 第 1 阶段(Ship) | 每次阶段转换时(Ship);后台进程启动/完成时 | 停止钩子(重新注入、进程检测)、Ship(重新进入) |
tmp/ship/loop.md | 循环控制——迭代计数器、最大迭代次数、完成承诺、session_id(用于隔离) | 第 1 阶段(Ship) | 每次重新进入时(停止钩子递增迭代次数并写入 session_id) | 停止钩子(阻止/允许退出) |
tmp/ship/last-prompt.md | 上次重新注入的提示词——停止钩子最近一次重新进入时构建的完整提示词,用于调试 | 停止钩子 | 每次重新进入时(覆盖) | 仅用于调试 |
tmp/ship/spec.json | 用户故事——验收标准、优先级、通过/失败状态 | 第 2 阶段(/decompose) | 每次迭代时(设置 passes: true) | implement.sh、迭代、Ship |
tmp/ship/progress.txt | 迭代日志——已完成的工作、经验总结、阻碍因素 | 第 3 阶段开始时(implement.sh) | 每次迭代时(追加) | 迭代、Ship |
tmp/ship/review-output.md | 最新的便携式本地审查摘要,来自审查关卡(第 5、8 阶段) | 审查关卡 | 每次本地审查通过时(覆盖) | Ship、用户 |
tmp/ship/review-status.json | 解析后的本地审查状态——建议、风险、问题数量,以及关卡是否仍处于阻塞状态 | 审查关卡 | 每次本地审查通过时(覆盖) | Ship、本地审查脚本 |
tmp/ship/qa-progress.json | QA 场景与结果——状态、备注、bootstrapResult | 第 6 阶段(/qa-plan) | 第 7 阶段(/qa)——场景状态、证据、bootstrapResult。第 7 阶段退出关卡(Ship)——当编排器解决了 /qa 未能解决的场景时,将 blocked 改为 validated,并设置 resolvedBy: "parent"。 | Ship(第 6→7 阶段之间的阶段关卡、完成报告) |
tmp/ship/ship-summary.md | Ship 摘要——规格偏差、QA 缺口、延期范围、已发现的机会 | 第 9 阶段(Ship) | 仅第 9 阶段 | /pr |
| SPEC.md (已提交) | 产品与技术规格——需求、设计、决策、非目标 | 第 1 阶段(/spec 或用户) | 仅第 1 阶段 | 所有阶段、迭代 |
何时更新哪些内容
| 事件 | state.json | 其他文件 |
|---|---|---|
| 阶段 1 结束 | 运行 ship-init-state.sh — 创建 state.json 和 loop.md(参见阶段 1,第 3 步) | — |
| 阶段 2 开始 | — | /decompose 创建 tmp/ship/spec.json |
| 阶段 3 开始 | — | /implement 创建 tmp/ship/implement-prompt.md、tmp/ship/progress.txt |
| 审查关卡(阶段 5、阶段 8) | 如果 state.json 已存在,则更新本地审查状态 | run-local-review.sh 将可移植的审查包暂存到 tmp/ship/pr-review-plugin/,覆盖 tmp/ship/review-output.md,并将其解析为 tmp/ship/review-status.json |
| 任意阶段 → 下一阶段 | 将 currentPhase 设为下一阶段,将规范阶段名称追加到 completedPhases,并刷新 lastUpdated。规范名称:"Phase 2"、"Phase 3"、"Phase 4"、"Phase 5"、"Phase 6"、"Phase 7"、"Phase 8"、"Phase 9"。停止钩子会在允许完成前验证 completedPhases 中是否包含阶段 2–9;缺少条目会阻止退出。 | — |
| 用户修订(任意阶段) | 追加到 amendments[]:{"description": "...", "status": "pending"} | — |
| 识别出延后处理的范围(任意阶段) | 追加到 deferredScope[]:{"description": "...", "phase": "Phase N", "source": "..."} | — |
| 发现机会(任意阶段) | 追加到 surfacedOpportunities[]:{"description": "...", "phase": "Phase N", "source": "..."} | — |
| 启动后台进程(阶段 3、4、5、6、7、8) | 将以下字段追加到 backgroundProcesses[]:taskId、pid(未知时为 null)、type("implement"、"review" 或 "nested-claude")、phase、command、startedAt(ISO 8601)、description。使用 jq 进行追加(通过临时文件读取、修改并写入)。进程完成后,按 taskId 筛选并移除对应条目。 | — |
| 迭代完成一个用户故事 | — | tmp/ship/spec.json:将用户故事的 passes: true。tmp/ship/progress.txt:追加迭代日志。 |
| 阶段 6 QA 规划 | — | /qa-plan 创建 tmp/ship/qa-progress.json,其中包含计划的场景、缺口和补充内容 |
| 阶段 7 QA 执行 | — | /qa 更新 tmp/ship/qa-progress.json — 场景状态、bootstrapResult、证据 |
| 阶段 7 退出关卡(解决阻塞项) | — | 对于 /qa 退出后由协调器解决的场景,Ship 会更新 tmp/ship/qa-progress.json,将状态从 blocked 改为 validated,并设置 resolvedBy: "parent" |
| 阶段 9 → 已完成 | 设置 currentPhase: "completed"。将 "Phase 9" 追加到 completedPhases。停止钩子的三部分关卡会验证:(1) 输出中包含完成承诺,(2) currentPhase === "completed",(3) completedPhases 中包含阶段 2–9 的所有阶段。 | 停止钩子删除 loop.md |
| 停止钩子重新进入 | — | loop.md:迭代次数递增。根据 state.json + SKILL.md 重新注入提示词。 |
/cancel-ship | 保留以供检查 | 删除 loop.md |
工作流
阶段转换
从任一阶段进入下一阶段之前:
-
确认当前阶段的所有未决问题均已解决。
-
确认你对当前阶段的产出有较高把握。
-
无头模式下:所有阶段均自主运行。不要输出
<input>或请求确认。根据证据做出最合理的判断,并在完成报告中记录。 -
交互式协作阶段(用户正在积极提供输入):明确询问用户是否准备好继续。收到确认前不要继续。
-
交互式自主阶段:自行判断,但如果某项决策需要你无法自主做出的人类判断,应暂停并咨询用户(例如存在重大权衡的架构选择、面向产品或客户的决策、范围变更,以及猜错代价较高的模糊需求)。 暂停前: 彻底研究当前情况——收集所有相关背景,探索各种方案并评估权衡。应向用户提供完整的决策简报,而不是含糊地提问。
暂停时: 在消息开头输出
<input>Input required</input>,然后列出:- 情况:发生了什么,以及为什么需要做出决定
- 已收集的背景:你研究了什么、发现了什么、尝试了什么
- 方案:具体选项及各自的权衡
- 你的建议:你会选择哪个选项,以及原因(如果有建议)
- 提示:"Would you like me to research any of these options more deeply before you decide?"
stop hook 会检测
<input>,并让你等待用户回复。循环会保持活动状态——用户回复后,你完成相应操作,循环便会自动恢复。不要因以下情况暂停: 你能够依据证据自行决定的常规工程决策、通过阅读代码或文档即可回答的问题,以及可以通过
/research或/explore解决的任何事项。判断标准:该团队的高级工程师会自行做出决定,还是会将问题升级给产品负责人? -
根据上方的“When to update what”表更新
tmp/ship/state.json(Phase 1 结束前该文件不存在)。- 修订: 当用户要求原始规范中未包含的变更——临时任务、改进、调整,或经用户批准的评审反馈范围扩展——在执行前将其追加到
amendments:{ "description": "<简要说明内容>", "status": "pending" }。完成后将status设为"done"。此日志会在上下文压缩后保留,并告知恢复后的 Agent 规范之外还收到过哪些工作请求。
- 修订: 当用户要求原始规范中未包含的变更——临时任务、改进、调整,或经用户批准的评审反馈范围扩展——在执行前将其追加到
-
更新任务列表:将已完成阶段的任务标记为
completed,并将下一阶段的任务标记为in_progress。 -
累积延期范围和发现的机会。 每次阶段转换时,留意本阶段出现但本次 ship 流程不会处理的事项,并将其追加到
state.json。分为两类:deferredScope[]— 已确认需要处理但有意暂不处理的工作(原则上接受但推迟的评审建议、发现的相邻 Bug、已知但未处理的边缘情况、实现过程中发现的后续工作)。追加:{ "description": "<需要完成的工作>", "phase": "Phase N", "source": "<发现来源>" }。- 纳入评审结果: 每个评审关卡后(Phase 5
/review-cloud、Phase 4/Phase 8/review-local),读取评审结果中与未来相关但被拒绝的发现。对于/review-local:读取review-status.json中的deferredFindings[]。对于/review-cloud:读取完成输出中的被拒绝发现列表。将每项与未来相关的内容追加到deferredScope[],source设为"review-cloud"或"review-local",phase设为当前阶段。
- 纳入评审结果: 每个评审关卡后(Phase 5
surfacedOpportunities[]— 深入代码后发现但并非必须完成的想法、改进或架构观察。追加:{ "description": "<观察内容>", "phase": "Phase N", "source": "<发现来源>" }。
立即将这些内容持久化到
state.json——与amendments[]使用相同的做法。持久化到state.json的条目会在上下文压缩后保留;仅记录在对话中的条目不会保留。Phase 9 的 Ship Summary 会读取这些数组。
创建阶段任务列表(每次全新运行的第一个操作)
开始 Phase 0 之前,使用 TaskCreate 为每个阶段创建任务。这样可以提前展示完整工作流,并确保不会跳过任何阶段。
按以下顺序创建这些任务:
- Phase 0:检测上下文和起始点 — 恢复检查、功能名称、工作树、能力检测、范围校准
- Phase 1:编写规范并交接(/spec) — 搭建规范框架、调查、加载
/spec、验证 - Phase 1 退出:启用自主执行(ship-init-state.sh) — 运行初始化脚本以创建
state.json+loop.md,确认两个文件均存在。这会启用停止钩子,让 Agent 持续完成所有剩余阶段。 - Phase 2:分解(/decompose) — 加载带有 SPEC.md 路径的
/decompose,生成 spec.json - Phase 3:实现(/implement) — 建立理解、加载带有 spec.json 的
/implement、实现后审查 - Phase 4:文档(/docs) (嵌套子进程) — 启动嵌套 Claude,编写或更新所有受影响的文档部分
- Phase 5:审查关卡 — QA 前(/review-local) — 运行本地审查收敛循环、评估发现的问题、修复已验证的问题
- Phase 6:QA 规划(/qa-plan) (嵌套子进程) — 启动嵌套 Claude,通过
/qa-plan根据 spec.json + 代码 + 差异生成 qa-progress.json - Phase 7:测试 / QA(/qa) (嵌套子进程) — 启动嵌套 Claude,通过
/qa根据 qa-progress.json 执行 - Phase 8:审查关卡 — QA 后(/review-local) — 对最终代码(包括 QA 修复)运行本地审查收敛循环
- Phase 9:完成 — 执行完成检查清单、向用户汇报、输出完成承诺
每个阶段开始时,将其任务标记为 in_progress。阶段完成时,将其标记为 completed。
重新进入 Ship Loop([SHIP-LOOP])时: 先检查 TaskList。如果任务已存在,则恢复执行——将已完成阶段的任务标记为 completed(如果尚未标记),然后从当前阶段的任务继续。如果不存在任务(会话早于此步骤),则创建任务,并根据 state.json 中的 completedPhases 将已完成阶段标记为 completed。
Phase 0:检测上下文和起始点
从上一次会话恢复
首先,检查 tmp/ship/state.json 是否存在。如果存在:
无头模式: 自动恢复。加载状态并跳转到记录的阶段。不要询问。
交互模式:
- 读取状态文件,并向用户展示恢复的状态:功能名称、当前阶段、已完成阶段和任何待处理的修订。
- 询问:“之前针对 [feature] 的
/ship会话在 [phase] 阶段中断。要从那里恢复,还是重新开始?” - 如果恢复:加载状态(规范路径、分支、工作树路径、质量关卡、能力、修订),并跳转到记录的阶段。重新读取 SPEC.md 以及状态文件中引用的任何产物。检查 amendments 数组中的待处理项——这些是用户在编写规范后提出、可能仍需处理的更改。如果
tmp/ship/loop.md不存在(循环未启用),则按照 Phase 1 第 3 步重新启用。 - 如果重新开始:删除状态文件;如果
tmp/ship/loop.md存在,也将其删除,然后照常继续。
第 1 步:确定功能名称和起点
确定用户想构建什么,以及是否已有规格说明。在此处快速探索即可——调用几次 Grep/Glob/Read 来熟悉情况(例如,查找相关目录、确认模块是否存在)。但不要进行长时间调查、启动 Explore 子 Agent 或加载技能。深入调查将在脚手架搭建完成后的第 1 阶段进行。
| 条件 | 操作 |
|---|---|
| 用户提供了现有 SPEC.md 的路径(或内联规格说明内容) | 加载它。从规格说明中提取功能名称。启用无头模式——提供规格说明意味着工作流将端到端运行,无需交互(参见“无头模式”部分)。如果输入是内联内容,请先将其写入 specs/<feature-name>/SPEC.md。 |
用户传入了 --headless 标志(并提供功能描述) | 启用无头模式。从描述中提取功能名称。在第 1 阶段根据描述生成 SPEC.md 脚手架,然后自主继续。 |
用户提供了功能描述(没有 SPEC.md,也没有 --headless) | 可以快速探索相关区域以熟悉情况。然后提取一个简短的功能名称(例如,revoke-invite、org-members-page、auth-flow)。如果描述过于含糊,无法命名,请提出 1–2 个有针对性的问题——只需足以确定语义名称,无需深入界定范围。 |
| 存在歧义 | 询问:“你是否已有 SPEC.md,还是要从头编写规格说明?” |
第 2 步:创建隔离的工作环境
现在已有功能名称,请建立一个隔离的工作目录,以便从一开始就将所有构件放在功能工作区中。
默认行为:除非另有指定,/ship 会从 origin/main 创建一个全新的工作树。这样可以确保并发运行的 /ship 实例不会相互冲突——每个工作树都有自己的 tmp/ship/ 状态目录。可通过以下选项覆盖:
--local— 跳过工作树创建,直接使用当前检出状态--branch <name>— 跳过工作树创建,检出指定的现有分支
加载:references/worktree-setup.md — 包含完整的决策表、设置流程和依赖安装说明。
优先使用辅助脚本,而不是临时运行 git worktree 命令:
<path-to-skill>/scripts/ship-worktree.sh ensure --feature "<feature-name>"
辅助脚本会创建一个全新的同级工作树,让每个 /ship 请求都拥有自己的工作区。只有当你已经位于工作树中(而非主检出目录)时,它才会复用当前检出目录。
规格说明移交:如果提供了 --spec <path>,请在创建工作树之前将路径解析为绝对路径,然后在 cd 进入工作树后将其复制进去。操作流程请参见 references/worktree-setup.md。
脚本会通过 git rev-parse --show-toplevel 动态解析 ship 目录——进入工作树后无需手动重新导出变量。
第 3 步:检测执行环境
加载:references/capability-detection.md — 列出所有能力(质量门禁、浏览器、macOS、Docker、技能)的探测表及降级方案。
记录结果。**在交互模式下:**如果有任何能力不可用,请简要说明缺少的内容,作为协商检查点——用户可能可以在工作继续之前解决问题。**在无头模式下:**记录不可用的能力并继续——每项子技能中都已预先规划降级方案。
步骤 4:根据范围校准工作流
评估任务,并确定每个阶段的适当深度。始终执行每个阶段——范围校准调整的是严谨程度,而不是是否执行某个阶段。
| 任务范围 | 规格深度(阶段 1) | 实现深度(阶段 3) | 文档深度(阶段 4) | 审查深度(阶段 5、8) | 测试深度(阶段 7) |
|---|---|---|---|---|---|
| 功能(新能力、多文件、面向用户) | 完整 /spec → SPEC.md → spec.json | 完整 /implement 迭代循环 | 完整文档流程——产品文档 + 内部文档 | 完整本地审查收敛循环 | 完整 /qa |
| 增强(扩展现有功能,范围适中) | SPEC.md,包含问题 + 验收标准 + 测试用例;/spec 可选 | /implement 迭代循环 | 如有影响,更新现有文档 | 完整本地审查收敛循环 | /qa(根据范围校准) |
| Bug 修复 / 配置更改 / 基础设施(范围较小、针对性更强的更改) | SPEC.md,包含问题陈述 + 对“已修复”状态的定义 + 验收标准 | /implement 迭代循环(根据范围校准) | 仅在行为发生变化时更新文档 | 本地审查收敛循环 | 如面向用户,则进行有针对性的 /qa |
始终生成 SPEC.md——仅通过对话得出的结论无法在上下文丢失后保留。
在内部记录范围级别——它决定了各阶段的深度。此处不要给出详细的逐阶段计划,也不要等待批准;直接进入阶段 1,让 SPEC.md 的框架记录初始范围。用户通过规格交接(阶段 1,步骤 2)确认范围,而不是通过单独的计划批准步骤。
阶段 1:编写规格并交接(/spec,交互模式下协作完成)
**在提供了规格的无头模式下:**完全跳过步骤 1——规格已存在。跳转到步骤 2(验证)。验证后,直接进入步骤 3(激活状态),无需等待确认。
**在使用 --headless 标志但未提供规格的无头模式下:**根据功能描述搭建 SPEC.md 的框架(将其写入 specs/<feature-name>/SPEC.md),执行以下调查步骤,然后进入步骤 2,无需等待确认。
**在交互模式下:**用户是产品负责人——你的工作是帮助他们清晰地梳理要构建的内容,指出他们可能遗漏的考量,并与他们共同制定严谨的规格。
步骤 1:编写规格说明
先搭建脚手架,再逐步完善。 如果用户的描述确实过于模糊,无法搭建脚手架(例如只说“改进系统”,没有具体说明),最多提出 1~2 个范围界定问题。如果请求足够具体,可以写出问题陈述——即使还不完整——就跳过提问,立即编写脚手架。不要在脚手架成形前进行冗长的范围界定对话。
将其写入 specs/<feature-name>/SPEC.md(相对于仓库根目录)。这是 /spec 技能默认的路径约定——完整的覆盖优先级(环境变量、AI 仓库配置、用户覆盖)请参阅 /spec 中的“Where to save the spec”。脚手架应包含:
- 问题陈述(目前你对问题的理解)
- 初步需求和验收标准(即使还不完整)
- 已知约束或技术方向
- 待解答问题(仍需澄清的事项)
脚手架不必完整,但必须写入磁盘,以便在上下文压缩后仍能保留,并为后续完善对话提供依据。深入探索(调查、待解答问题、决策、/spec)应在脚手架成形后进行,而不是之前。
脚手架成形后——进行调查。 现在,脚手架已为对话提供依据,可以开展深入调查,为规格说明提供参考:
- 追踪现有系统。 加载
/explore技能,了解相关部分当前的工作方式——模式、共享抽象、数据流和影响范围。对于 Bug 修复,使用系统追踪的视角,从入口点开始跟踪执行过程,直至出错位置,并找出根本原因(而非仅仅症状)。 - 研究第三方依赖。 如果功能涉及第三方库、框架、包、API 或外部服务,请加载
/research技能,在设计解决方案之前,先核实其功能、约束和正确用法。每次都要这样做,而不只是觉得依赖陌生时才做。即使你之前用过某项依赖,它也可能已经发生变化、存在未记录的约束,或在当前上下文中表现不同。不要依据假设的 API 形式编写规格说明——务必先核实。 - 更新脚手架。 根据调查结果修订 SPEC.md,补充根本原因(针对 Bug)、系统约束、API 形式、依赖能力,以及以调查结果为依据的完善后验收标准。
这项调查不可省略——它能让规格说明立足于现实,而不是建立在假设之上。假设某个 API 以特定方式工作,或某个模块具有特定接口,都会导致实现过程中出现意外,而这些问题之后修复的成本更高。
然后完善规格说明。 加载 /spec 技能,通过交互流程深化并完成规格说明。脚手架和调查结果能为 /spec 提供基于实际情况的起点,而非一张白纸。
在规格说明流程中,确保通过证据记录以下内容(而非仅凭愿望设想):
- 所有测试用例和验收标准。标准应描述可观察到的行为,而非内部机制(示例请参阅 /tdd)。
- 失败模式和边缘情况
- 第三方依赖的约束和 API 形式(通过
/research核实,而非假设)
如果范围评估表明应采用较轻量的规格说明流程(增强或 Bug 修复):直接完善脚手架,而不调用 /spec。上述调查步骤仍然适用——规格说明流程较轻量,不代表调查也可以简化。最终的 SPEC.md 仍必须记录:问题陈述、根本原因(针对 Bug 修复)、“完成”的定义(验收标准)以及计划进行的测试。
如果用户提供了现有的 SPEC.md(在第 0 阶段检测到):跳至步骤 2。
步骤 2:验证规格说明
阅读 SPEC.md。确认其中包含足够的实现细节:
- 问题陈述和目标明确
- 已定义范围、要求和验收标准
- 已列出测试用例(或可根据验收标准推导)
- 已提供技术设计(架构、数据模型、API 形式——至少说明方向)
如果缺少任何内容:**在交互模式下,**通过向用户提出有针对性的问题或给出合理的默认值来补全缺漏(明确标注为假设)。**在无头模式下,**使用合理的默认值补全缺漏——在 SPEC.md 中将其标注为假设,然后继续。
**在交互模式下:**在用户确认 SPEC.md 已可用于实现之前,不要继续。此确认即为交接——从此刻起,由你自主负责执行。
**在无头模式下:**验证完成后立即继续。提供的规格说明即视为用户的最终决定。
步骤 3:激活执行状态
加载: references/state-initialization.md — 其中包含初始化脚本的调用方式和字段参考。
使用第 0 阶段(能力、范围)和第 1 阶段(功能名称、规格说明路径、分支)的值运行 <path-to-skill>/scripts/ship-init-state.sh。传入 --session-id 和你的会话 ID(可从钩子输入 JSON 中获取),以将所有权写入 loop.md——这可防止并行 ship 会话同时认领此循环。**不要手动编写 state.json 或 loop.md——始终使用该脚本。**手写 JSON/YAML 是导致停止钩子失败的头号原因。完整参数列表和默认值请参阅参考文档。
脚本运行后,确认这两个文件都存在:
test -f tmp/ship/state.json && test -f tmp/ship/loop.md && echo "State initialized" || echo "ERROR: state files missing"
如果缺少任一文件,请检查脚本输出中的错误并重新运行。两个文件都存在之前,不要进入第 2 阶段。
该脚本会激活用于自主执行的停止钩子。循环将持续运行,直到出现 <complete>SHIP COMPLETE</complete> 或达到 20 次迭代。可使用 /cancel-ship 手动取消。
第 2 阶段:分解(/decompose)
使用 SPEC.md 路径加载 /decompose 技能。/decompose 会读取规格说明、分析代码库,并生成 tmp/ship/spec.json——其中包含按依赖关系排序的结构化用户故事、可验证的验收标准和 QA 场景。
进入第 3 阶段之前,确认 tmp/ship/spec.json 存在。
第 3 阶段:实现(/implement)
步骤 1:了解代码库
确认你真正理解了该功能——而不只是确认规格说明包含正确的章节。检验自己:你能否清楚说明该功能的作用、重要性、技术实现方式、风险最高的部分,以及你会优先测试的内容?如果不能,请重新阅读规格说明并调查代码库,直到能够回答。针对目标区域加载 /explore 技能(目的:实现),以了解你需要使用的模式、约定和共享抽象。根据 /explore 的发现和 SPEC.md 建立理解——不要漫无目的地浏览实现文件;让 /explore 引导你的探索。如果需要深入了解特定子系统,可将有针对性的问题委派给子 Agent(例如:“src/middleware/ 中的身份验证中间件链如何运作?遵循哪些约定?”)。你的理解应着眼于架构,而非逐行分析。这些理解将用于之后评估实现输出和审查者的反馈。
步骤 2:加载 /implement 技能
使用 Phase 2 中的 spec.json 路径加载 /implement 技能。由于 spec.json 已存在,/implement 会从 Phase 2(Prepare)开始,跳过其内部转换步骤。无论范围大小,提示词编写和迭代循环都由 /implement 负责。不要直接编写实现代码——所有实现都必须通过 /implement 及其子进程(implement.sh)完成,即使变更看起来简单到可以直接内联处理。
加载 /implement 技能以处理完整的实现生命周期——从规范转换(SPEC.md → spec.json)到提示词编写和执行。向它提供以下内容:
- SPEC.md 的路径——这是优先级最高的输入。不得省略。
- 第 1 步中获取的代码库上下文——你通过
/explore识别出的模式、约定和共享抽象 - Phase 0 中覆盖质量门禁命令的设置(可能与 pnpm 默认值不同)
- Phase 0 中的浏览器可用性(如果浏览器工具不可用,请传递
--no-browser,让/implement调整验收标准) - Phase 0 中的 Docker 执行设置(如果传递了
--implement-docker,请将其作为--docker转发给/implement;如果提供了 compose 文件路径,也一并传递)
等待 /implement 完成。如果它报告自动执行不可用并将任务交给用户,请等待用户表示已完成。用户表示完成后,重新读取 SPEC.md、spec.json 和 progress.txt,以重新掌握上下文。
后台进程跟踪: 当 /implement 通过 Bash(run_in_background: true) 启动 implement.sh 时,立即根据状态更新表中“Background process launched”一行的要求,将后台进程记录到 state.json 中。使用类型 "implement",描述 "Implementation iteration loop"。implement.sh 完成后,移除对应条目。
步骤 3:实现后审查
实现完成后,在继续之前确认输出令你满意。你要对这段代码负责——实现输出只是起点,而不是终点。不要自己逐一阅读每个变更文件来审查输出;请委派子 Agent 进行有针对性的验证:“实现是否符合 SPEC.md 的验收标准?是否存在遗漏、死代码或尚未解决的 TODO?每项验收标准是否都有对应测试?”根据发现采取行动。对于较小且明显的问题,直接修复。对于根因不明确的问题,加载带有 --headless 的 /debug 技能进行诊断——/debug 将返回结构化发现(根因、建议修复方案、影响范围),但不会自行实施修复。根据其发现应用修复。对于需要重新实现某个 story 的大型返工,请根据具体反馈重新加载 /implement 技能。
如果你进行了任何代码更改(无论是直接修复,还是重新调用 /implement):请重新运行质量门禁(测试套件、类型检查、lint),并确认全部通过。/implement 会以通过状态退出,但其迭代循环之外的实现后修复由你负责验证。
阶段 4:文档(/docs,嵌套子进程)
启动一个嵌套 Claude Code 实例(通过 /nest-claude 子进程模式启动干净的子实例)来编写或更新文档。子进程会加载 /docs,并独立完成整个文档生命周期。尽早编写文档,以便两个评审关卡(阶段 5 和阶段 8)都能评估文档的质量和准确性——完整的评审人员名单(包括 pr-review-docs)会在文档已就绪的情况下运行。
向子进程提供:
- SPEC.md 的路径(了解已构建内容及其原因的主要来源)
后台进程跟踪: 通过 Bash(run_in_background: true) 启动嵌套 Claude 子进程时,按照状态更新表中的“已启动后台进程”行将其记录到 state.json 中。使用类型 "nested-claude",描述 "Documentation subprocess (/docs)"。完成后移除。
子进程退出后,确认文档更改已提交到分支。
文档维护规则
在后续所有阶段中,文档都必须保持最新:
- 阶段 5 或阶段 8(评审)之后: 如果评审反馈导致代码更改,请评估这些更改是否会影响本阶段编写的文档。继续之前先更新文档。
- 用户请求修改之后: 如果用户在阶段 4 之后请求更改,请在修改代码的同时更新受影响的文档。
- 阶段 9(完成)检查点: 确认文档仍准确反映最终实现。
阶段 5:评审关卡——QA 前(/review-local)
运行本地评审收敛循环。这是两个评审关卡中的第一个——它会在 QA 测试前评审实现和文档。不要假设目标仓库 vendored 了评审插件——先将插件包暂存到 tmp/ship/,然后执行暂存的副本。
通过此技能的辅助脚本,在仓库根目录运行。评审会并行调度 17 个评审人员,并最多运行 5 轮修复——这通常会超过 Bash 工具的 600 秒超时时间。务必使用 run_in_background: true 运行。 启动后,按照状态更新表中的“已启动后台进程”行将后台进程记录到 state.json 中(类型 "review",描述 "Pre-QA local review gate")。完成后移除。
Bash(command: "<path-to-skill>/scripts/run-local-review.sh",
run_in_background: true,
description: "Local review gate")
如果分支的目标不是自动检测到的基分支,请显式传入 --target <branch>。
如果本次 /ship 运行启用了 Docker 执行,请在 Docker 模式下运行同一辅助脚本,以便评审在仓库沙盒内运行,而不是在主机上运行:
Bash(command: "<path-to-skill>/scripts/run-local-review.sh --docker [compose-file]",
run_in_background: true,
description: "Local review gate (Docker)")
评审完成时,你会收到 <task-notification>。等待期间可以处理轻量任务,但不要修改代码。如果需要在运行期间检查进度,请使用后台 Bash 调用返回的输出文件路径执行 Read。预计耗时:10-30 分钟,具体取决于差异大小和修复轮数。
辅助脚本会将可移植的评审插件暂存到 tmp/ship/pr-review-plugin/,然后在主机上或 Docker 沙盒内运行 tmp/ship/pr-review-plugin/scripts/pr-review.sh。这与 /implement 模式一致:容器会使用绑定挂载仓库中的暂存文件,而不是主机上的插件安装。
默认情况下,辅助脚本会自动检测目标分支(如果存在则使用 PR 基分支,否则使用仓库默认分支 / origin/HEAD,然后是 main)。收到 <task-notification> 后,脚本的标准输出包含结构化返回载荷——直接解析该载荷,不要手动读取文件:
退出信封(=== LOCAL REVIEW EXIT ===):始终存在。包含 exit_code、exit_reason、轮次计数、修复提交 SHA、最后一条建议、阻塞状态、持续时间以及取证文件的路径。首先读取此项以确定结果。
评审状态(=== REVIEW STATUS ===):已解析的 review-status.json 内容——包括建议、风险、问题数量和阻塞原因。所有非崩溃退出都会提供此项。
迭代日志(=== REVIEW ITERATION LOG ===):审查轮次和修复响应的完整时间顺序记录(发现了什么、修复者处理了什么/拒绝了什么/推迟了什么)。仅在退出码非零时包含(阻塞、致命)——编排器需要这些上下文来决定如何补救。退出码为 0(已收敛)时,迭代日志会保留在磁盘上(信封中包含文件指针),以免占用父级上下文。
退出原因及处理方式:
exit_reason | 含义 | 操作 |
|---|---|---|
converged | 纯粹的 APPROVE——关卡通过 | 抽查修复内容(审查信封中列出的修复提交),然后继续 |
fixer_no_changes | 修复者评估了所有发现,并拒绝/推迟了所有处理——代码未发生更改 | 迭代日志中包含修复者对每项被拒绝发现的理由。**交互模式:**将被拒绝的发现上报给用户。**无头模式:**记录剩余发现并继续——迭代日志中包含修复者基于证据给出的理由。 |
max_passes_exhausted | 所有修复轮次结束后仍存在阻塞问题 | 迭代日志会显示尝试过哪些操作。**交互模式:**在问题解决前不要继续。**无头模式:**记录剩余发现并继续。 |
allow_blocking | 存在阻塞问题,但已设置 --allow-blocking | 继续——调用方已明确接受阻塞结果 |
fatal_error | 脚本崩溃(暂存、审查调度或解析失败) | 检查 stderr 中的错误消息。如果信封中存在部分状态(审查状态或迭代日志),请用作上下文。若为暂时性错误,则重试。 |
- 收敛后,抽查修复内容——自动修复 Agent 表现不错,但也并非万无一失。
阶段 6:QA 规划(/qa-plan,嵌套子进程)
启动一个嵌套的 Claude Code 实例(干净的子实例,通过 /nest-claude 子进程模式),以生成 QA 测试计划。该子进程会加载 /qa-plan,并检查 spec.json + 代码 + 差异,生成内容更完善的 tmp/ship/qa-progress.json。
**后台进程跟踪:**按照“已启动后台进程”行的要求,在 state.json 中记录此子进程(类型 "nested-claude",描述 "QA planning subprocess (/qa-plan)")。完成后移除该记录。
向子进程提供:
- SPEC.md 的路径
- spec.json 的路径(
tmp/ship/spec.json) - 如果 ship 在无头模式下运行,则传入
--headless
子进程退出后,继续之前先检查 qa-progress.json:
- 读取
planMetadata——检查是否存在矛盾(scenarios[].enrichment.gapType === "contradiction")和关键实现缺口(scenarios[].enrichment.gapType === "fixable_gap")。 - **如果存在矛盾:****交互模式:**通过
<input>暂停——矛盾意味着规格假设了不可能实现的内容。向用户说明这些矛盾,并请其在继续前解决。**无头模式:**尽力合理解决(选择最符合规格问题陈述的解释)。在完成报告中记录矛盾及所选解释。不要暂停。 - 如果存在关键缺口(主要用户旅程无法测试——没有路由、身份验证失效、主页返回 500):**交互模式:**通过
<input>暂停——说明这些缺口,并询问是继续还是先修复。**无头模式:**如果可能,尝试直接修复。如果无法修复,则记录并继续——QA 将确认该缺口是否确实存在。 - **如果仅存在可修复缺口:**继续——
/qa会在执行期间解决这些问题(/qa 的步骤 5b)。 - **如果没有问题:**继续进入阶段 7。
Phase 7:测试 / QA(/qa,嵌套子进程)
启动一个嵌套 Claude Code 实例(干净的子实例,通过 /nest-claude 子进程模式)执行 QA 测试。该子进程加载 /qa,并根据 tmp/ship/qa-progress.json 运行完整的手动 QA 生命周期:环境引导、差距解决、使用可用工具(浏览器、macOS、bash)执行测试、记录结果以及记录差距。
后台进程跟踪: 根据“已启动后台进程”这一行,将此子进程记录到 state.json 中(类型 "nested-claude",描述 "QA execution subprocess (/qa)")。完成后移除记录。
向子进程提供:
- SPEC.md 的路径
- 如果范围校准表明范围较轻(错误修复 / 配置变更),请传递此上下文,以便
/qa相应地校准测试深度 - 传递
--headless,让/qa跳过工具可用性协商检查点并自主运行
Phase 7 退出门槛 — 进入 Phase 8 前请确认:
-
/qa已完成:子进程已退出,qa-progress.json 已更新测试结果。剩余差距和无法解决的问题均已记录——它们不会阻止进入 Phase 8。 - 如果
/qa修改了任何代码:重新运行质量门禁(测试套件、类型检查、lint)并确认全部通过。/qa会修复发现的错误——你需要验证这些修复不会引发其他问题。 - 解决受阻场景(见下文)。
- 你能够向另一位工程师说明实现:测试了什么、存在哪些边界情况,以及如何处理这些情况
解决受阻场景(适用时):
如果 qa-progress.json 中有 status: "blocked" 的场景,且你能够解决(例如,编写 /qa 子进程无法编写的测试、修复环境问题,或提供缺失的依赖项),请予以解决:
- 编写测试、验证代码或修复。
- 更新 qa-progress.json 中的场景:
{ "status": "validated", "resolvedBy": "parent", "resolvedAt": "<ISO 8601 timestamp>", "resolvedNote": "Covered by <test-file-path> via <approach>", "previousStatus": "blocked", "previousNotes": "<original blocked reason from /qa>" } - 保留
previousStatus和previousNotes以供审计——下游使用者(例如/pr)会利用它们区分由父进程解决的场景和经/qa验证的场景。
如果受阻场景确实无法解决(需要外部服务、生产凭据或硬件访问),请保持其状态为 blocked——该场景会作为需要人工验证的事项进入 PR。
Phase 8:审查门禁 — QA 后(/review-local)
再次运行本地审查收敛循环。此轮将以全新视角审查最终完整状态——实现、文档以及 QA 所做的任何代码变更。
使用与 Phase 5 相同的脚本,并设置 run_in_background: true。根据“已启动后台进程”这一行,将后台进程记录到 state.json 中(类型 "review",描述 "Post-QA local review gate")。完成后移除记录。
Bash(command: "<path-to-skill>/scripts/run-local-review.sh",
run_in_background: true,
description: "Post-QA review gate")
每次调用都是独立运行的——脚本会在开始时清理之前的审查状态。适用相同的 --docker 选项。等待 <task-notification>,然后解析 stdout 中的结构化返回载荷——完整的退出原因表和响应协议请参见 Phase 5。
交互模式: 在此审查门禁通过前,不要进入 Phase 9。无头模式: 与 Phase 5 相同——如果经过最大轮次后门禁仍未收敛,请记录情况并继续。
第 8 阶段退出门槛:QA 过时检查
在 post-QA 审查门禁实施自动修复后,检查这些修复是否使之前的任何 QA 场景失效。读取 tmp/ship/qa-progress.json,并将已验证的场景与第 8 阶段提交进行比较。
识别第 8 阶段提交:使用 qa-progress.json 中的 qaCompletedAtCommit 字段(由 /qa 作为最后一步写入)。运行 git log <qaCompletedAtCommit>..HEAD,准确获取 QA 之后的提交。检查每个提交修改了哪些文件。
全局失效条件:
- CSS/样式文件发生变更 → 将所有视觉场景标记为过时
- API 路由/处理程序发生变更 → 将所有集成场景标记为过时
路径启发式规则:
- 文件位于
src/pages/settings/(或等效路径模式)→ 将名称或路由中包含 "settings" 的场景标记为过时 - 文件变更涉及某个组件 → 将引用该组件页面/路由的场景标记为过时
标记过时场景:在 qa-progress.json 中为该场景添加 staleness 元数据:
{
"staleness": {
"stale": true,
"staleAfterCommit": "<commit-hash>",
"validatedAtCommit": "<original-validation-commit>",
"reason": "CSS changes in src/styles/settings.css may invalidate visual verification"
}
}
对过时场景的处理:
- 过时的视觉、集成或错误状态场景 → 触发选择性 QA 重跑(仅重新执行这些类别中的过时场景,而非完整计划)
- 过时的可用性或边缘情况场景 → 仅提供建议(在 qa-progress.json 中记录,但不重跑)
如果第 8 阶段没有提交修改与任何 QA 场景相关的文件,则完全跳过过时检查。
第 9 阶段:完成
加载: references/completion-checklist.md — 完整的验证清单(质量门槛、文档、本地审查)和完成报告模板。
逐项执行清单。向用户汇报后,输出完成承诺以结束 ship 循环:
SHIP COMPLETE
所有权原则
以下原则指导你在整个过程中的行为:
-
你是工程师,而不是传话人。
/implement生成代码;审查者提出修改建议;CI 报告失败。你要决定如何处理每一项。 -
**结果优先于流程。**工作流阶段旨在组织你的工作,而不是强迫你不断推进。完成当前步骤后,绝不要仅仅因为完成了就进入下一步;只有当你对目前构建的内容真正有信心时才继续。如果有任何不确定之处,就停下来调查。行动之前,应先深入了解代码库、产品、规范意图以及你的决策所带来的影响。
-
**委派调查;深入完成每个阶段。**信息收集工作默认交由子 Agent 处理:探索代码库、诊断测试失败、分析 CI 日志、审查实现结果中的代码,以及发现模式。这是提升效率的策略,而非配额限制。委派能让你专注于协调和决策,同时由子 Agent 处理范围明确的研究任务。向每个子 Agent 提出清晰的问题,提供相关文件路径或错误消息,并说明所需的输出格式。依据调查结果采取行动,而不是直接依据原始代码或日志。只有在任务很简单时(一个小文件、一条快速命令),才直接调查。判断标准:如果需要超过 2-3 次工具调用,或会产生超过约 100 行输出,就应委派。如果任何时候上下文不足,ship 循环的自动保存/重启机制会确保工作连续性;不要为了追求速度而牺牲阶段深度。 该委派什么、在顶层运行什么、以及该嵌套什么: 三种执行模型:
- 顶层(Skill 工具,共享上下文):管理状态或做出升级决策的编排阶段——
/spec、评审关卡、完成阶段。这些阶段需要编排器上下文(状态文件、规范路径、阶段感知能力,以及使用<input>暂停的能力)。 - 嵌套 Claude——干净子进程(
/nest-claude子进程模式):适合使用全新上下文并保持独立性的执行阶段——/implement(已通过 implement.sh 使用子进程)、/qa-plan、/qa、/docs。干净子进程会加载自己的技能,从磁盘读取产物(而非父进程上下文),不会受到前序阶段的偏见影响。所有通信都通过磁盘产物进行(spec.json、qa-progress.json、progress.txt)。每个子进程退出后,编排器都会读取输出产物。 - Task 子代理(临时,不继承技能):范围明确的调查——代码库探索、测试失败诊断、CI 日志分析、模式发现。绝不要将流水线阶段委派给 Task 子代理——它会失去工具、技能和上下文。
子代理机制: 子代理不会继承你的技能。对于普通调查,这并不重要——只需提供明确的问题和文件路径。如果子代理需要调查技能(例如
/explore),请使用general-purpose类型(它具备 Skill 工具),并在提示词开头写上Before doing anything, load /skill-name skill——这样就能可靠地触发 Skill 工具。接着提供上下文和任务:Before doing anything, load /explore skill Explore src/middleware/auth/ for pattern discovery (purpose: implementing). We're adding role-based access control — report existing auth conventions, shared abstractions, and middleware chain composition. Return a pattern brief. - 顶层(Skill 工具,共享上下文):管理状态或做出升级决策的编排阶段——
-
重证据,不凭直觉。 决策前使用
/research调查代码库、API 和模式——不只是在遇到陌生内容时才这么做。直接检查代码库。必要时进行网络搜索。标准是:你能否向资深工程师解释自己的推理,并用证据为其辩护?如果不能,说明调查还不够充分。 -
把握回应尺度。 研究、规范制定和评审可能会提出许多方法、顾虑和选项。你的任务不是处理每一种可能性,而是评估哪些与当前情境相关,并采取行动。对于每个重要决策,请权衡:
- 必要性: 这是在解决已验证的问题,还是假设性问题?
- 适度性: 解决方案的复杂度是否与问题的复杂度相匹配?
- 证据: 有什么具体证据支持这种方法,而非其他方案?
- 可逆性: 如果判断有误,之后能否更改?
- 副作用: 这项决策还会影响什么?
- 最佳实践: 代码库和生态系统中已确立的模式给出了什么建议?
如果证据不足以支撑这种复杂度,就优先选择更简单的方法——但“更简单”是指减少环节,而非减少要求。跳过已验证要求的方案并不简单,而是有缺陷。
过度倾向的表现:实现研究中提出的每一种方案,为假设性问题构建可配置性。
过度简化的表现:对不熟悉的代码路径不做调查就跳过,缺乏证据却宣称有把握。
-
明确指出,不要隐瞒。 如果发现异常之处——设计异味、测试缺口、与规范相矛盾的评审建议——请明确提出。如果问题较为重要,请暂停并征求用户意见。
-
优先采用正式测试。 只有在场景确实难以自动化时才进行手动测试。每当你说“我手动测试过”,都应该追问:“这能否改为测试?”
反模式
- 在设置前进行深入调查。 在 Phase 0 期间启动 Explore 子 Agent、加载技能或对代码库进行扩展探索。可以快速探索一下(进行几次 Grep/Glob/Read 调用)以熟悉情况,但深入调查——
/explore、/research、子 Agent——应在 Phase 1(脚手架搭建完成后)进行。用户说“添加邀请撤销”时,你立即就有了功能名称(revoke-invite);无需先梳理整个邀请系统。 - 未充分理解就开始实现。 尚未建立对功能、代码库相关部分或规范意图的整体认识,就直接开始编写代码。
- 使用与仓库指定不同的包管理器
- 未经用户确认就强制推送或执行破坏性 Git 操作
- 离开工作树前未进行清理。合并后或拆除已放弃的请求时,使用
ship-worktree.sh cleanup。 - 以“工作很小”为由绕过 /ship。 范围校准(Phase 0,Step 4)会针对各种任务规模调整深度——修复 Bug 时会使用精简的 SPEC.md,并按任务校准测试。工作流始终会运行;严谨程度则按需调整。在 /ship 之外直接实现,就意味着没有规范(需求会在上下文压缩时丢失)、没有状态持久化、没有 QA,也没有评审关卡。即使是涉及 4 个文件的安全修复,也仍然需要规范来定义“修复完成”的标准、验证该标准的测试,以及记录相关内容的 PR。
- 以“改动很简单”为由跳过
/implement。/implement始终会运行——它负责将规范转换为 spec.json、生成实现提示词并执行迭代循环。即使是小改动,也能从结构化提示词和验证周期中受益。在/implement之外直接实现,就会失去 spec.json 跟踪、进度日志和质量关卡循环。 - 手动编写状态文件。 切勿直接以原始 JSON/YAML 格式手动编写
tmp/ship/state.json或tmp/ship/loop.md。始终使用ship-init-state.sh。手动编写的文件是停止钩子故障的首要原因——JSON 格式错误、字段缺失、YAML frontmatter 错误——而由此产生的 Bug(钩子静默退出、循环从未启动)在上下文压缩前都无法察觉,届时就太晚了。 - 虚假宣称已完成。 在所有阶段确实完成且 Phase 8 的所有验证检查均通过之前,切勿输出
<complete>SHIP COMPLETE</complete>。Ship 循环旨在持续运行直至真正完成——不要谎称完成来提前退出。 - 因担心上下文不足而赶进度或跳过阶段。 切勿因为觉得上下文快用完了,就压缩、简略处理或跳过 Phase 3-8。Ship 循环的停止钩子会自动保存状态,并在重启后以完整上下文将你带回正确阶段。重启后从正确阶段重新开始,比在上下文所剩无几时压缩处理多个阶段效果更好。每个阶段都会加载技能、运行检查清单并完整完成——上下文压力绝不是跳过或简略处理的正当理由。如果你发现自己在想“上下文快用完了,我快速处理完剩余阶段吧”——请停下。这种想法正是反模式。
- 以项目特性为由为跳过 QA 阶段找借口。 切勿因为项目是“没有 UI 的后端 SDK”、“已有全面的测试”或“不需要手动 QA”就跳过 Phase 6 或 7。这些都是借口,不是正当的跳过理由。
/qa-plan和/qa会测试所有类型的项目——后端 SDK 存在 API 契约、错误处理、边界情况和集成行为,而现有单元测试往往会漏掉这些内容。“全面的测试覆盖”恰恰是/qa-plan的模拟检测和覆盖率实况检查要验证的内容——如果覆盖真实,/qa会很快确认;如果覆盖是模拟的或浅层的,/qa就会发现你可能漏掉的问题。无头模式中的标志表示“自主运行”,而非“简化流程”。如果你发现自己在写“QA 主要是检查我们已有的测试覆盖率”——请停下。这句话正是反模式。加载技能。启动子进程。让/qa-plan和/qa完成各自的工作。 - 委派给子进程时,擅自假定所有阶段都已运行。 当
/ship作为嵌套的claude -p子进程运行时,由于上下文压缩会丢失子进程状态跟踪,Phase 5-9 过去经常被跳过(参见 Headless mode 部分中的“Known bug”)。如果将/ship委派给子进程,完成后务必检查state.json中的completedPhases,并手动运行缺失阶段(通常是 QA 和第二轮评审)。
附录:参考资料和脚本索引
| 路径 | 适用场景 | 跳过的影响 |
|---|---|---|
/decompose 技能 | 将 SPEC.md 转换为结构化的 spec.json,其中包含用户故事、依赖项排序和 QA 场景(阶段 2) | 规范缺乏结构、没有依赖项排序,也没有 QA 场景 |
/implement 技能 | 编写实现提示词并执行迭代循环(阶段 3) | 没有实现提示词,也没有自动化执行 |
/qa-plan 技能 | 根据 spec.json、代码和差异推导 QA 测试计划(阶段 6) | QA 场景没有以实现为依据、没有双向追踪,也无法检测差距 |
/qa 技能 | 使用可用工具进行 QA 验证(阶段 7) | 遗漏面向用户的 Bug、视觉问题、失效的 UX 流程以及未记录的差距 |
/docs 技能 | 编写或更新文档——产品和内部层面(阶段 4) | 未编写文档、格式错误、遗漏文档涉及的层面,或与项目惯例不一致 |
references/worktree-setup.md | 创建工作树(阶段 0,步骤 1) | 工作内容会混入主目录 |
references/capability-detection.md | 检测执行上下文(阶段 0,步骤 2) | 子技能会收到错误标志、阶段被跳过,或基于错误假设运行 |
references/state-initialization.md | 激活执行状态(阶段 1,步骤 3) | Stop hook 无法恢复上下文,循环无法激活 |
references/completion-checklist.md | 最终验证(阶段 9) | 未完成的工作会被当作“已完成”交付 |
scripts/run-local-review.sh | 运行本地审查收敛循环(阶段 5、阶段 8),可选执行有限次数的修复 | 明显的审查问题会被遗漏,或 Ship 因缺少确定的下一步而停滞 |
scripts/build-local-review-fix-prompt.sh | 将阻塞性的本地审查结果转换为有限范围的修复提示词,供人工或自主后续处理 | 修复循环无法根据审查结果自动生成交接内容并进入修复步骤 |
scripts/ship-worktree.sh | 复用或创建请求专用的工作树,并在合并后清理 | 工作内容会混入主检出目录、过期工作树不断堆积、已完成的分支长期遗留 |
scripts/ship-upload-pr-asset.js | 将现有截图或录屏上传到 Bunny CDN(单独使用) | 即使有可用的程序化 CDN 路径,PR 图片流程仍依赖手动上传到 GitHub |
/debug 技能 | 诊断实现过程中(阶段 3)或测试过程中(阶段 7)遇到的故障根因——当无法从错误中直接看出原因时 | 盲目调试:不理解根因就修复表象,浪费迭代周期 |