关于 implement
implement 是一项 Agent 技能,可将 SPEC.md 转换为结构化用户故事并运行实现循环。它将转换、准备和执行分为独立阶段,并支持配置质量检查。
主要功能
- 01将 SPEC.md 转换为 spec.json
- 02验证用户故事与验收标准
- 03生成实现提示词
- 04通过脚本执行故事迭代
- 05配置测试、类型检查和 lint 命令
适用场景
- 01将功能规格拆分为可验证的用户故事
- 02为现有 spec.json 准备实现流程
- 03使用项目指定的检查运行实现迭代
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ inkeep/ team-skills --skill implement安装后在 Claude Code 中输入/implement确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/execution.mdscripts/implement.shvalidate-spec.tstemplates/implement-prompt.template.md详细介绍
实现
将 SPEC.md 转换为可直接用于实现的产物,并执行迭代循环。此技能分为三个阶段:
- 转换 — 将 SPEC.md 转换为结构化的 spec.json
- 准备 — 验证 spec.json,编写实现提示词,并将其保存到文件
- 执行 — 运行
scripts/implement.sh,通过子进程迭代处理用户故事
每个阶段都可以独立进入。如果已有 spec.json,请从阶段 2 开始。如果产物已准备就绪,只需执行,请从阶段 3 开始。如果只需要转换,请在阶段 1 后停止。
由 /ship 组合调用时,Ship 会在完整生命周期中调用 /implement,并在之后审查输出。独立运行时,/implement 会端到端执行并直接报告结果。
Ship 工作目录
所有实现产物都存储在 tmp/ship/ 中,该目录由 git rev-parse --show-toplevel 动态确定。Docker、CI 或隔离环境可通过 CLAUDE_SHIP_DIR_OVERRIDE 覆盖。implement.sh 脚本会自动解析该目录。
输入
| 输入 | 必需 | 默认值 | 说明 |
|---|---|---|---|
| SPEC.md 或 spec.json 路径 | 是 | — | 源产物。使用 SPEC.md 时:用于阶段 1 转换,并在阶段 2 中作为迭代参考传递(参见“Spec 路径传递”)。使用 spec.json 时:直接从阶段 2 开始。 |
--test-cmd | 否 | pnpm test --run | 质量门禁使用的测试运行命令 |
--typecheck-cmd | 否 | pnpm typecheck | 质量门禁使用的类型检查命令 |
--lint-cmd | 否 | pnpm lint | 质量门禁使用的代码检查命令 |
--no-browser | 否 | 默认认为浏览器可用 | 从 UI 故事的验收标准中移除“在浏览器中验证”,并替换为可通过 Bash 验证的标准 |
--docker [compose-file] | 否 | — | 在阶段 3 执行时使用 Docker。可选地接受 compose 文件路径(例如 --docker .ai-dev/docker-compose.yml)。未指定路径时,会自动查找 compose 文件。完全省略此选项时,将在主机上执行。 |
由 /ship 组合调用时,会根据阶段 0 的上下文检测结果传入这些覆盖项。独立运行时,使用默认值。
Spec 路径传递
提供 SPEC.md 时(无论是直接提供还是由调用方提供),其路径都会在阶段 1 转换后继续保留。在阶段 2 中,此技能会在实现提示词中嵌入文件路径引用,确保每轮迭代的 Agent 都会将完整 SPEC.md 作为首要操作读取。提示词中不会嵌入 spec 内容,只包含文件路径。
只要有 spec 路径,就必须执行此操作。spec 包含 spec.json 的 implementationContext 无法完整涵盖的关键实现上下文:
- 非目标(不应构建的内容)——spec.json 中完全没有
- 当前状态代码追踪(文件路径、行号、现有模式)——在
implementationContext中已压缩为文字说明 - 决策依据——仅保留了结论
- 风险和故障模式——验收标准仅部分涵盖
仅提供 spec.json(没有可用的 SPEC.md)时,implementationContext 是唯一的实现上下文来源。有关如何调整深度,请参阅阶段 1 的 implementationContext 指南。
创建工作流任务(首要操作)
开始任何工作之前,使用 TaskCreate 为每个阶段创建一个任务,并通过 addBlockedBy 强制执行顺序。根据各阶段自身的工作流文本推导任务描述和完成标准。
- Implement:检测起始点
- Implement:阶段 1 — 将 SPEC.md 转换为 spec.json
- Implement:阶段 2 — 验证并编写提示词
- Implement:阶段 3 — 执行迭代循环
开始某个阶段时,将对应任务标记为 in_progress;满足该阶段的退出标准后,将其标记为 completed。重新进入时,先检查 TaskList,再从第一个未完成任务继续。
检测起始点
| 条件 | 从以下阶段开始 |
|---|---|
| 存在 SPEC.md,不存在 spec.json | 阶段 1(转换) |
| 存在 spec.json,需要验证/提示词 | 阶段 2(准备) |
存在 spec.json + tmp/ship/implement-prompt.md,准备执行 | 阶段 3(执行) |
| 仅收到转换请求 | 阶段 1,然后停止 |
阶段 1:转换(SPEC.md 转换为 spec.json)
将 SPEC.md 转换为 tmp/ship/spec.json。如果 tmp/ship/ 不存在,则创建它(mkdir -p tmp/ship)。
输出格式
{
"project": "[Project Name]",
"branchName": "implement/[feature-name-kebab-case]",
"description": "[Feature description from SPEC.md title/intro]",
"implementationContext": "[Concise prose summary of architecture, constraints, key decisions, and current state from the SPEC.md — everything the implementer needs to know that doesn't fit in individual stories]",
"userStories": [
{
"id": "US-001",
"title": "[Story title]",
"description": "As a [user], I want [feature] so that [benefit]",
"acceptanceCriteria": [
"Criterion 1",
"Criterion 2",
"Typecheck passes"
],
"priority": 1,
"passes": false,
"notes": ""
}
]
}
故事规模:首要规则
每个故事必须能在一次迭代(一段上下文窗口)内完成。
每次迭代收到的提示词都相同,且不会记得之前的工作——只有文件和 Git 历史记录会保留下来。如果故事太大,大模型会在完成前耗尽上下文,产出有问题的代码。
恰当规模的故事:
- 为数据库添加一列并编写迁移
- 为现有页面添加一个 UI 组件
- 使用新逻辑更新一个服务端操作
- 为列表添加一个筛选下拉菜单
规模过大(应拆分):
- “构建整个仪表板”——拆分为:架构、查询、UI 组件、筛选器
- “添加身份验证”——拆分为:架构、中间件、登录 UI、会话处理
- “重构 API”——按端点或模式拆分,每个故事处理一项
**经验法则:**如果无法用 2-3 句话描述变更,说明规模过大。
故事排序:依赖项优先
故事按优先级顺序执行。靠前的故事不得依赖靠后的故事。
正确顺序:
- 架构/数据库变更(迁移)
- 服务端操作/后端逻辑
- 使用后端的 UI 组件
- 汇总数据的仪表板/摘要视图
错误顺序:
- UI 组件(依赖尚不存在的架构)
- 架构变更
验收标准:必须可验证
每项标准都必须是迭代 Agent 可以检查的内容,而不是含糊的描述。
良好标准(可验证):
- “为 tasks 表添加
status列,默认值为 'pending'” - “筛选下拉菜单包含以下选项:All、Active、Completed”
- “点击删除时显示确认对话框”
- “类型检查通过”
- “测试通过”
不良标准(含糊):
- “运行正常”
- “用户可以轻松完成 X”
- “良好的 UX”
- “能够处理边缘情况”
与实现耦合的标准(脆弱):
- “handleStatusChange 使用正确的枚举调用 db.update”
- “组件通过调用 useTaskList hook 进行渲染”
- “API 处理程序在处理请求前调用 validateInput”
行为标准(稳健):
- “状态已更改的任务可通过新状态检索”
- “任务列表仅显示符合所选筛选条件的任务”
- “无效的状态值返回 400,并附带明确的错误消息”
与实现耦合的标准会导致测试在重构时失效,即使行为未变也是如此。行为标准则能让测试在内部结构调整后继续有效。参见 /tdd。
始终将以下内容作为最后一项标准:
"Typecheck passes"
对于包含可测试逻辑的故事,还应添加:
"Tests pass"
对于会更改 UI 的故事——如果浏览器自动化可用(未设置 --no-browser 标志):
"Verify in browser using browser skill"
前端故事只有经过视觉验证后才算完成。进行视觉验证时,优先使用 agent-browser(agent-browser open <url>、agent-browser screenshot)——对于简单的导航和检查流程,它更轻量、速度更快。如果验收标准需要更深入的验证,请加载 /browser 技能(Playwright 脚本):监控控制台错误(startConsoleCapture / getConsoleErrors)、验证网络请求(startNetworkCapture / getFailedRequests)或进行无障碍审计(runAccessibilityAudit)。
如果浏览器不可用(--no-browser):省略浏览器标准。改为添加可通过 Bash 验证的标准,通过 API 响应或渲染输出涵盖 UI 行为(例如,“API 响应包含更新后的状态徽标标记”,“服务端渲染的 HTML 包含筛选下拉菜单,选项为:All、Active、Completed”)。
转换规则
- 每个用户故事对应一个 JSON 条目
- ID:按顺序编号(US-001、US-002 等)
- 优先级:先按依赖顺序,再按文档顺序
- 所有故事:
passes: false,且notes为空 - branchName:根据功能名称生成,使用 kebab-case,并以
implement/为前缀 - 始终添加:"Typecheck passes" 到每个故事的验收标准中
从 SPEC.md 提取实现上下文
implementationContext 字段用于记录适用于所有故事的规格级知识——实施者每次迭代都需要了解、但不属于任何单个故事验收标准的内容。
从 SPEC.md 的以下章节提取:
| SPEC.md 章节 | 提取内容 | 重要原因 |
|---|---|---|
| §9 Proposed solution — System design | 架构概述、数据模型、API 结构、身份验证/权限模型 | 否则,实施者可能会猜测架构,或与规格中的设计相矛盾 |
| §6 Non-functional requirements | 性能目标、安全约束、可靠性要求、可运维性需求 | 这些约束的是每个故事的实现方式,而非实现内容 |
| §10 Decision log | 已确定的决策(尤其是单向门决策)及简要理由 | 防止实施者重新审视或违背规格阶段已作出的决策 |
| §8 Current state | 系统当前的工作方式、关键集成点、已知差距 | 实施者需要了解已有内容,才能正确集成 |
撰写内容: 简洁的散文摘要。不要复制粘贴规格章节,而要提炼出实施者处理每个故事时都需要牢记的内容。
根据规格是否可用调整深度:
| 实施期间规格是否可用? | implementationContext 的作用 | 建议深度 |
|---|---|---|
是 — 规格路径已传递到 Phase 2(由 /ship 组合调用或用户同时提供两者时的默认情况) | 快速了解背景。完整的 SPEC.md 会提供深入的上下文——迭代 Agent 会将其作为第 1 步阅读。 | 3-5 句话——仅包含架构概述和关键约束 |
否 — spec.json 是唯一产物(用户仅使用 spec.json 调用 /implement,或规格不可用) | 主要且唯一的实现上下文来源。内容必须能够独立完整。 | 5-10 句话——包含架构、非目标、当前状态下的集成点、附有理由的关键决策,以及重要约束 |
如果不确定规格届时是否可用,请撰写较长版本——多提供上下文总不会错,但较短版本可能导致迭代 Agent 掌握的信息不足。
好例子:
"此功能会在 tasks 表中添加一个
status列,使用枚举类型。API 遵循/api/tasks/中现有的 RESTful 模式。身份验证由现有的租户级中间件处理——不要添加新的身份验证逻辑。当前任务列表通过数据访问层中的getTasksByProject()获取数据;新筛选器必须使用相同的查询模式。决策 D3:我们选择服务端筛选,而非客户端筛选,因为数据集可能超过 10k 行。"
反面例子(过于模糊):
"遵循良好实践,实现任务状态功能。"
拆分大型规格
如果 SPEC.md 包含大型功能,请将其拆分:
原始内容:
"添加用户通知系统"
拆分为:
- US-001:在数据库中添加 notifications 表
- US-002:创建用于发送通知的通知服务
- US-003:在页眉中添加通知铃铛图标
- US-004:创建通知下拉面板
- US-005:添加标记为已读的功能
- US-006:添加通知偏好设置页面
每项都是一个聚焦的变更,可以独立完成和验证。
将失败路径转化为验收标准
SPEC.md §5(用户旅程)按用户角色列出了失败/恢复路径和调试体验。这些往往是区分仅能在演示中运行的功能与可在生产环境中运行的功能的关键。
转换时不要丢弃失败路径。针对规范中的每种失败场景:
- 确定它属于哪个用户故事——将失败场景与实现相关功能的用户故事对应起来。
- 将其转化为该用户故事中可验证的验收标准。
示例:
SPEC.md 失败路径:
失败:用户通过 API 设置了无效的状态值 → 系统返回 400,并显示错误消息“Invalid status. Allowed values: pending, in_progress, done”
转化为相关用户故事中的一项验收标准:
"API returns 400 with descriptive error when status value is not in [pending, in_progress, done]"
如果某个失败场景涉及多个用户故事(例如,“保存时发生网络错误,应显示重试按钮”),则将该标准添加到体现用户可见行为的用户故事中(即 UI 用户故事,而非后端用户故事)。
将非功能性需求作为横切标准
SPEC.md §6 包含非功能性需求:性能、可靠性、安全/隐私、可运维性和成本。这些需求约束用户故事的实现方式。
针对规范中的每项非功能性需求:
- 确定其是否普遍适用(例如,“所有端点都必须验证租户隔离”),还是仅适用于特定用户故事(例如,“列表查询必须在 <200ms 内返回 10k 行数据”)。
- 通用约束:将其作为标准添加到适用的每个用户故事中。
- 特定用户故事的约束:仅将其作为标准添加到相关用户故事中。
示例:
| 非功能性需求 | 转化为以下用户故事中的标准 |
|---|---|
| “所有 API 端点都必须验证租户隔离” | 所有新增或修改 API 端点的用户故事 |
| “列表查询必须分页,并在 <200ms 内返回” | 实现列表/筛选功能的用户故事 |
| “状态变更必须记录审计日志” | 实现状态切换功能的用户故事 |
不要单独创建“非功能性”用户故事。这些约束应融入实现相关功能的用户故事中。
推导 qaScenarios(实现上下文)
转换用户故事后,根据 SPEC.md 的结构化章节推导 qaScenarios[] 数组。这些场景为迭代 Agent 在实现过程中提供 QA 上下文,帮助实现者了解将要验证的内容。它们不会约束或限定 /qa-plan——qa-plan 会直接根据 SPEC.md 源材料推导自己的场景。
每个场景都遵循 Given/When/Then 格式,并可追溯至一个或多个用户故事。
映射表:SPEC.md 章节 → 场景类别 → 推导规则
| SPEC.md 章节 | 场景类别 | 推导规则 |
|---|---|---|
| §6 验收标准 | ux-flow、error-state | 每项标准 → 一个正常路径场景;每种失败情况 → 一个错误变体 |
| §5 交互状态矩阵 | visual、edge-case | 每个非空单元格 → 一个状态验证场景 |
| §9 数据流图——影子路径 | edge-case、failure-mode | 每条影子路径 → 一个边界情况场景 |
| §9 失败模式表 | error-state、failure-mode | 每一行 → 一个涵盖检测、恢复和用户影响的错误状态场景 |
| §9 受影响的路由/页面 | visual、ux-flow | 每一行 → 一个视觉/导航验证场景 |
| §5 用户旅程(正常路径 + 失败路径) | ux-flow、cross-system | 每个旅程步骤 → 一个端到端场景;涉及多个服务的旅程 → cross-system 类别 |
| §13 部署/发布注意事项 | integration | 每一行 → 一个部署/集成验证场景 |
oracleType 赋值
每个场景都会分配一个 oracleType,用于定义如何判定通过或失败:
| oracleType | 使用场景 | 示例 |
|---|---|---|
specified | 确定性的通过/失败判定——规范定义了确切的预期结果 | “API 返回 400 和错误消息” |
derived | 与基线或参考进行比较——正确性是相对的,而非绝对的 | “页面与设计模型渲染一致” |
human | 需要主观判断——不存在自动化判定方式 | “错误消息有帮助且可据此采取行动” |
示例
输入 SPEC.md(缩略版):
# Task Status Feature
Add ability to mark tasks with different statuses.
## Requirements
- Toggle between pending/in-progress/done on task list
- Filter list by status
- Show status badge on each task
- Persist status in database
## Non-functional requirements
- Status changes must be tenant-scoped
## User journeys — Failure paths
- Invalid status value via API → return 400 with descriptive error
## Current state
- Tasks stored in tasks table, accessed via getTasksByProject()
- API uses RESTful patterns under /api/tasks/
- UI uses TaskCard component in components/tasks/
输出 spec.json:
{
"project": "TaskApp",
"branchName": "implement/task-status",
"description": "Task Status Feature - Track task progress with status indicators",
"implementationContext": "Tasks are stored in a tasks table accessed via getTasksByProject() in the data-access layer. The API follows RESTful patterns under /api/tasks/. Auth uses existing tenant-scoped middleware. The status field should be an enum column with a database-level constraint. UI components use the existing TaskCard component in components/tasks/.",
"userStories": [
{
"id": "US-001",
"title": "Add status field to tasks table",
"description": "As a developer, I need to store task status in the database.",
"acceptanceCriteria": [
"Add status column: 'pending' | 'in_progress' | 'done' (default 'pending')",
"Generate and run migration successfully",
"Typecheck passes"
],
"priority": 1,
"passes": false,
"notes": ""
},
{
"id": "US-002",
"title": "Display status badge on task cards",
"description": "As a user, I want to see task status at a glance.",
"acceptanceCriteria": [
"Each task card shows colored status badge",
"Badge colors: gray=pending, blue=in_progress, green=done",
"Typecheck passes",
"Verify in browser using browser skill"
],
"priority": 2,
"passes": false,
"notes": ""
},
{
"id": "US-003",
"title": "Add status toggle to task list rows",
"description": "As a user, I want to change task status directly from the list.",
"acceptanceCriteria": [
"Each row has status dropdown or toggle",
"Changing status saves immediately",
"UI updates without page refresh",
"API returns 400 with descriptive error when status value is not in [pending, in_progress, done]",
"Status update is tenant-scoped (uses existing tenant middleware)",
"Typecheck passes",
"Verify in browser using browser skill"
],
"priority": 3,
"passes": false,
"notes": ""
},
{
"id": "US-004",
"title": "Filter tasks by status",
"description": "As a user, I want to filter the list to see only certain statuses.",
"acceptanceCriteria": [
"Filter dropdown: All | Pending | In Progress | Done",
"Filter persists in URL params",
"Typecheck passes",
"Verify in browser using browser skill"
],
"priority": 4,
"passes": false,
"notes": ""
}
],
"qaScenarios": [
{
"id": "QA-001",
"priority": "P0",
"category": "ux-flow",
"name": "User can toggle task status from list",
"given": "A task exists with status 'pending' on the task list",
"when": "User changes status to 'in_progress' via the dropdown",
"then": "Status updates immediately, UI reflects the change without page refresh",
"tracesTo": ["US-003"],
"derivedFrom": "spec",
"oracleType": "specified",
"route": "/tasks"
},
{
"id": "QA-002",
"priority": "P0",
"category": "error-state",
"name": "Invalid status value returns descriptive error",
"given": "A task exists in the system",
"when": "API receives an invalid status value via PUT /api/tasks/:id",
"then": "API returns 400 with message 'Invalid status. Allowed values: pending, in_progress, done'",
"tracesTo": ["US-003"],
"derivedFrom": "spec",
"oracleType": "specified"
},
{
"id": "QA-003",
"priority": "P1",
"category": "visual",
"name": "Status badge colors match spec for all states",
"given": "Tasks exist with each status value (pending, in_progress, done)",
"when": "User views the task list",
"then": "Badges show correct colors: gray=pending, blue=in_progress, green=done",
"tracesTo": ["US-002"],
"derivedFrom": "spec",
"oracleType": "derived",
"route": "/tasks"
}
]
}
归档之前的运行
编写新的 spec.json 之前,检查是否已有属于其他功能的文件:
- 如果存在,读取当前的
tmp/ship/spec.json - 检查
branchName是否与新功能的分支名称不同 - 如果不同,且
tmp/ship/progress.txt中除标题外还有内容:- 创建归档文件夹:
tmp/ship/archive/YYYY-MM-DD-feature-name/ - 将当前的
tmp/ship/spec.json和tmp/ship/progress.txt复制到归档文件夹 - 使用新的标题重置
tmp/ship/progress.txt
- 创建归档文件夹:
阶段 1 检查清单
编写 spec.json 之前,请确认:
- 已归档之前的运行(如果
tmp/ship/spec.json存在且branchName不同,请先归档) - 每个故事都能在一次迭代中完成(规模足够小)
- 故事按照依赖顺序排列(从 schema 到后端,再到 UI)
- 每个故事都包含“Typecheck passes”作为验收标准
- UI 故事包含“使用 browser skill 在浏览器中验证”作为验收标准(如果有浏览器),或使用可通过 Bash 验证的替代方案(如果使用
--no-browser) - 验收标准可验证且不含糊;功能标准描述可观察到的行为,而不是内部机制(参见 /tdd)
- 没有故事依赖后续故事
- 已从 SPEC.md §8、§9、§10、§6 提取
implementationContext——使用简洁的说明文字,而非直接复制粘贴 - 已将 SPEC.md §5 中的失败/恢复路径转化为相关故事的验收标准
- 已将 SPEC.md §6 中的非功能性需求酌情应用为贯穿各项的标准
- 已从 SPEC.md 的结构化章节推导出
qaScenarios[]——每个场景都包含 id(QA-NNN)、given/when/then、tracesTo 和 oracleType
阶段 2:准备
验证 spec.json,编写实现提示词,并将其保存到文件以供执行。
根据 SPEC.md 验证 spec.json
将每个用户故事与 SPEC.md 中对应的需求进行比较:
- 故事的范围恰当(每个故事都能在一次迭代中完成)
- 故事顺序恰当(依赖项优先)
- 验收标准具体且可验证
- spec.json 未遗漏 SPEC.md 中的任何需求
- 故事范围未超出 SPEC.md 的要求
开始执行之前修正差异——此处的错误会在每次迭代中累积放大。
验证 spec.json schema
如果有 bun,运行 schema 验证器:
bun <path-to-skill>/scripts/validate-spec.ts tmp/ship/spec.json
此验证器会检查结构完整性:必填字段、ID 格式(US-NNN)、优先级顺序、重复项,以及是否包含“Typecheck passes”标准。无外部依赖——任何已安装 bun 的环境都可以运行。
如果没有 bun,请手动验证 spec.json 结构是否符合阶段 1 中的 schema。
放置 spec.json
将 spec.json 放在 tmp/ship/spec.json。如果 tmp/ship/ 不存在,则创建它(mkdir -p tmp/ship)。
验证分支安全性
如果当前位于 main 或 master,请在继续之前发出警告——通常应在功能分支上运行 implement skill。如果没有分支模型(例如,没有 PR 工作流的容器环境),请谨慎继续,并确保提交彼此隔离。
编写实现提示词
加载: templates/implement-prompt.template.md
模板包含两个完整的提示词变体,使用 {{PLACEHOLDER}} 语法。选择一个变体并填入所有占位符。
选择变体:
- 变体 A — 有 SPEC.md 路径可用时(直接提供或来自阶段 1)
- 变体 B — 只有 spec.json 可用时(没有 SPEC.md)
条件判断在这里进行(阶段 2 的构建过程),不在迭代提示词中。 迭代 Agent 看到的是单一、无条件的工作流——绝不包含两个变体,也不包含“如果有 spec”的条件逻辑。
填写 {{CODEBASE_CONTEXT}}: 包含正在修改的区域的具体模式、共享词汇和抽象——这些内容要比通用的 CLAUDE.md 指南更具可操作性。示例:“API 遵循 /api/tasks/ 下的 RESTful 模式”“身份验证使用 auth.ts 中按租户划分作用域的中间件”“数据访问采用 data-access/ 中的仓储模式”。还应包含迭代 Agent 需要了解的 CLAUDE.md 中的仓库规范(测试模式、文件位置、格式)。
填写质量门禁命令: 使用 Inputs 中的命令(默认值:pnpm typecheck、pnpm lint、pnpm test --run)——如果提供了 --typecheck-cmd、--lint-cmd、--test-cmd,则使用这些命令覆盖默认值。
填写 {{SPEC_PATH}}(仅限变体 A):使用相对于工作目录的路径(例如 .claude/specs/my-feature/SPEC.md)。相对路径适用于不同的执行环境(主机、Docker、worktree)。不要使用绝对路径——在不同环境中执行提示词时,绝对路径会失效。不要将 spec 内容嵌入提示词——迭代 Agent 每轮都会通过 Read 工具读取它。
将代码库上下文保存为独立文件
还要将填好的 {{CODEBASE_CONTEXT}} 内容保存到 tmp/ship/codebase-context.md,以供下游使用者(修复提示词、审阅者)使用:
mkdir -p tmp/ship
# Write codebase context as standalone file (same content that gets inlined in implement-prompt.md)
清理过时的执行产物
写入新文件前,移除先前运行生成的产物。这些文件会在每次运行时被完全替换——Write 工具的“尚未读取文件”保护机制会阻止覆盖已有文件,导致流程停滞并反复重试。
rm -f tmp/ship/implement-prompt.md tmp/ship/codebase-context.md
保存提示词
将编写好的实现提示词保存到 tmp/ship/implement-prompt.md。阶段 3(scripts/implement.sh)会使用此文件进行自动执行,用户也可用它进行手动迭代(claude -p)。
复制 implement.sh 以供 Docker 执行(仅限 Docker)
传入 --docker 时,将 scripts/implement.sh 复制到 tmp/ship/implement.sh,以便容器通过绑定挂载访问它:
cp <path-to-skill>/scripts/implement.sh tmp/ship/implement.sh
chmod +x tmp/ship/implement.sh
主机执行时跳过此步骤。 在主机上,阶段 3 会直接调用技能目录中的 scripts/implement.sh——无需复制。此副本仅供无法访问插件缓存路径的 Docker 容器使用(参见 references/execution.md)。
阶段 2 检查清单
- spec.json 已根据 SPEC.md 验证(如有)
- spec.json 架构已验证(如有 bun,则通过
scripts/validate-spec.ts验证) - 故事范围、排序均正确,且包含可验证的验收标准
- 已根据模板编写实现提示词,并选择了正确的变体(A 或 B)
- 所有
{{PLACEHOLDERS}}均已填写(spec 路径、质量门禁、代码库上下文) - 已保存的提示词中包含完成信号(模板中已包含——请确认未被意外移除)
- 代码库上下文已保存到
tmp/ship/codebase-context.md - 提示词已保存到
tmp/ship/implement-prompt.md -
implement.sh已复制到tmp/ship/implement.sh并设为可执行(仅限 Docker——主机执行时跳过)
阶段 3:执行
通过 scripts/implement.sh 运行迭代循环。每次迭代都会启动一个全新的 Claude Code 子进程——功能完整,迭代之间不共享上下文。
加载: references/execution.md
步骤 1:确保依赖项和构建环境就绪
开始迭代前,请确保工作目录中有可正常运行的开发环境。迭代 Agent 需要先安装依赖项并确保构建正常,才能运行质量检查。
- 检测包管理器:查看
package.json中的packageManager字段(例如[email protected])。如果指定了固定版本,请使用npx <pm>@<version> install,以避免锁文件不匹配。 - 安装依赖项:如果缺少
node_modules/或其中内容已过时:# Example for pnpm-pinned repos: npx pnpm@<version> install - 如果仓库根目录中存在
conductor.json,请运行 conductor 设置。 - 验证构建正常:
如果类型检查失败,这属于现存问题——请记录,但不要因此阻止执行。迭代循环可能会修复它。<typecheck-cmd> # e.g., pnpm typecheck
此步骤具有幂等性——如果依赖项已安装且构建正常,此步骤会立即完成。如果在 Docker 中运行(--docker),请完全跳过此步骤,因为容器镜像已提供所需环境。
步骤 2:探测 Claude CLI
检查是否可以进行自动化执行:
env -u CLAUDECODE -u CLAUDE_CODE_ENTRYPOINT claude --version
如果失败,则无法进行自动化执行——请跳至下方的备用方案。
步骤 3:选择执行环境(主机或 Docker)
如果未传入 --docker: 在主机上执行(默认)。继续执行步骤 4。
如果传入了 --docker: 使用 Docker 执行。
-
确定 compose 文件。 如果提供了路径(例如
--docker .ai-dev/docker-compose.yml),请使用该路径。否则,请搜索仓库中的**/docker-compose.yml或**/compose.yml文件,筛选出内容定义了sandbox服务的文件。使用第一个匹配项。如果未找到,请报错:"No compose file with a sandbox service found in this repo." -
确保容器正在运行:
docker compose -f <compose-file> ps --status running sandbox如果容器未运行,请启动它:
docker compose -f <compose-file> up -d。 -
继续执行——步骤 6 将使用 Docker 调用方式。
步骤 4:执行前质量检查基线
开始迭代循环前,运行质量检查以建立基线:
<typecheck-cmd> # e.g., pnpm typecheck
<lint-cmd> # e.g., pnpm lint
<test-cmd> # e.g., pnpm test --run
如果任何检查失败,请警告操作人员:"Quality gates are failing before implementation starts. Pre-existing failures will cost iterations to diagnose. Consider fixing them first."
无论结果如何,都将基线记录到 tmp/ship/progress.txt:
## Pre-execution baseline - [timestamp]
- Typecheck: PASS/FAIL
- Lint: PASS/FAIL
- Test: PASS/FAIL
不要阻止执行——操作人员可能正是为了修复失败项才运行 /implement。不过,基线日志有助于迭代 Agent 区分现存失败与它们引入的回归问题。
步骤 5:调用 implement.sh
在后台运行,以避免 Bash 工具的 600 秒超时。不要设置 --max-iterations——让模型不限次数地运行。迭代循环具有自然停止条件:所有用户故事均通过(完成信号)、用户故事陷入停滞(连续 3 次运行失败后继续)以及上下文耗尽(子进程退出,下一次迭代从头开始)。人为设置上限会截断仍在取得进展的运行。
在主机上执行(默认):
Bash(command: "<path-to-skill>/scripts/implement.sh --force",
run_in_background: true,
description: "Implement execution run 1")
使用 Docker 执行(传入 --docker 时——compose 文件已在步骤 3 中确定):
Bash(command: "docker compose -f <compose-file> exec sandbox tmp/ship/implement.sh --force",
run_in_background: true,
description: "Implement Docker execution run 1")
始终传入 --force——后台执行没有可用于交互式提示的 TTY。
后台 Bash 调用会返回任务 ID 和输出文件路径。implement.sh 完成时,你会自动收到 <task-notification>——不要使用 TaskOutput 轮询(已弃用)。等待通知时,可以进行轻量级工作(重新阅读规范、检查任务列表),但不要进行可能产生冲突的代码更改。如果需要在运行期间查看进度,请直接使用 Read 查看输出文件路径或 tmp/ship/progress.txt。
实现过程较慢——每次迭代都会启动一个完整的 Claude Code 子进程来处理一个用户故事。预计耗时如下:
| 功能复杂度 | 预计耗时 |
|---|---|
| 小型(1-3 个用户故事) | 总计 10-20 分钟 |
| 中型(4-8 个用户故事) | 总计 30-60 分钟 |
| 大型(9 个或更多用户故事) | 总计 60-120 分钟 |
第 7 步:评估结果
implement.sh 完成后,阅读 tmp/ship/spec.json 和 tmp/ship/progress.txt:
- 所有故事均为
passes: true→ 执行成功。继续执行第 3 阶段清单。 - 部分故事未完成 → 检查
tmp/ship/progress.txt中的阻碍。按照卡住的故事处理方法(参见references/execution.md)处理,然后再次调用 implement.sh 运行。 - implement.sh 以错误退出 → 阅读输出以了解详情。如果是暂时性错误(网络、速率限制),重试一次。如果问题持续存在,则回退到手动说明。
第 8 步:卡住的故事处理方法(两次运行之间)
如果同一个故事连续 2 次 implement.sh 运行都因相同的阻碍而失败:
- 故事太大 → 在 spec.json 中拆分成更小的故事
- 标准含糊不清 → 重写标准,使其更加具体
- 外部依赖造成阻碍 → 跳过该故事,并设置
notes说明阻碍 - 实现方法有误 → 在
tmp/ship/progress.txt中添加建议替代方案的指导 - 代码缺陷导致故事受阻(测试失败、运行时错误、迭代 Agent 无法解决的类型错误)→ 在两次运行之间加载
/debug技能以诊断根本原因。应用修复,然后再次调用 implement.sh。
如果同一个故事连续 3 次运行失败,请停止并咨询用户。
应用补救措施后,再次调用 implement.sh。升级给用户前,implement.sh 最多总共运行 3 次。
回退:Claude CLI 不可用
如果第 1 步中的 Claude CLI 探测失败,则无法自动执行。/implement 仍可通过第 1-2 阶段充分发挥作用——相关产物已准备就绪。
告知用户:
- 实现提示词已保存到
tmp/ship/implement-prompt.md - 如需使用迭代循环手动执行,请复制脚本并运行:
cp <path-to-skill>/scripts/implement.sh tmp/ship/implement.sh && chmod +x tmp/ship/implement.sh tmp/ship/implement.sh --force
第 3 阶段清单
-
tmp/ship/spec.json中的所有故事均为passes: true(或已通过notes记录卡住的故事) - 已检查
tmp/ship/progress.txt,没有未解决的阻碍 - 质量门禁通过:类型检查、lint、测试
第 3 阶段之后:
- 如果由
/ship组合调用:Ship 将继续进行实现后的审查和测试。 - 如果单独调用:阅读所有新建或修改的文件。实现输出只是起点,而非终点。手动运行质量门禁。