实现规范
它的作用¶
implement-spec 接收一个 spec 及其 tickets,并在一次运行中将整个事情落地。编排 agent 将每个 ticket 交给一个在独立 git worktree 中工作的实现 subagent,将每个已完成的分支合并到一个 集成分支,对结果运行 code-review,并解决这些 tickets。
它将 tickets 视为一个 任务图,而不是列表。阻塞边决定哪些可以开始,因此在任何时刻都会有一个 前沿(frontier),其中的 tickets 其阻塞项都已落地,并且前沿上的每个 ticket 都会同时运行。这就是与逐个处理 tickets 的区别。决定节奏的是图的形状,而不是 tickets 在跟踪器上的顺序。
何时使用它¶
你通过输入 /implement-spec 来调用它,agent 不会自行使用它。
| 你的情况 | 使用 |
|---|---|
| 一个 spec,已拆分为带阻塞边的 tickets,并且你想在一次运行中全部落地 | /implement-spec |
| 一次处理一个 ticket,在自己的 上下文窗口 中,并在 ticket 之间 清空 上下文 | implement |
| 尚未拆分为 tickets 的 spec | 先用 to-tickets |
| 没有真正图结构的一小块工作 | 直接使用 implement |
前置条件¶
- 一个 issue 跟踪器。 该技能从 setup-matt-pocock-skills 配置的跟踪器中读取 tickets,并在其上解决它们。如果尚未配置,它会停下来,告诉你先运行 setup-matt-pocock-skills,而不是自行猜测。
- 带阻塞边的 tickets,正如 to-tickets 生成的那样。没有边时,图是平坦的,所有 tickets 会同时开始。
- 一个能够在后台运行 subagents 并为每个 subagent 提供 git worktree 的 harness。 该技能的存在是为了同时运行 tickets,因此在逐个运行 subagents 的 harness 上,它只是一个更慢的
implement。
集成分支¶
所有内容都落地在同一个分支上。每个实现者:
- 在开始之前,确认其 worktree 基于集成分支;
- 使用 tdd 构建其 ticket,一次一个切片地进行红-绿循环;
- 在报告完成之前,将集成分支的最新提交合并到自己的分支中,因此落地时是快进合并。
究竟是否存在拉取请求,由跟踪器决定。如果你的跟踪器通过 PR 关闭工作,或者你要求创建一个 PR,该技能会在第一次合并后打开一个草稿 PR,并在最后将其标记为就绪。否则,运行会在集成分支上结束,每个 ticket 都按照你的跟踪器关闭工作的方式被解决,这可以完全离线地配合本地 markdown 跟踪器工作。
实现者通过 上下文指针(spec、ticket、共享的探索笔记、早期提交)与编排者交流,而不是粘贴摘要。这使每个 subagent 的 prompt 保持精简,并在编排者的窗口内为图留出空间。
常见问题¶
这和我自己对每个 ticket 运行 /implement 有什么不同?
这个技能的存在正是为了回答这个问题。在它发布之前,人们一直在构建自己的版本。一位用户描述了这种需求:他们希望“由 subagents 实现这些 tickets”,而不是不得不“逐个创建新会话,告诉它们一个接一个地实现 ticket,而一个 spec 可能包含超过 5 个 tickets”。使用 implement 时,你就是调度者:每个 ticket 一个 会话,中间清空上下文,并自己跟踪哪些 tickets 已解除阻塞。implement-spec 则把这个工作交给一个编排会话。代价是你不再在每个 ticket 落地时阅读它的成果;你会在最后审查集成分支。要开始一次运行,请清空上下文并输入 /implement-spec,同时带上指向 spec 的指针(issue 编号或文件路径)。对于没有真正图结构的小改动,跳过它,直接使用 implement。
它需要 GitHub 吗?我希望它停在分支上。
不,不再需要了。一位喜欢进行中版本的用户正是这样抱怨的:“它最后会创建一个 PR,这需要一个像 GitHub 这样的在线仓库。我希望它能离线完成同样的工作,并停在所有工作都已合并的分支上。”现在,运行会在集成分支上结束。只有当配置的跟踪器通过 PR 关闭工作,或者你要求创建 PR 时,才会打开 PR。因此在本地 markdown 跟踪器上,运行结束时所有 tickets 都已解决,工作也已合并到分支上。
它的审查和修复循环持续了数小时,或者一直在“修复”尚未构建的 tickets。
这两种情况都是因为 code-review 在技能指定的唯一时机之外运行。它会把代码与整个 spec 对比,因此只有所有 tickets 都落地后才有意义。如果它在运行中途运行,每个未构建的 ticket 都会被当作失败。随后 agent 会去构建那个 ticket,而这会触发另一次审查。在最后,该技能会运行一次 code-review,并将所有发现发送给一个修复 subagent,但它还没有说明修复之后何时停止。一位用户报告了一个包含五个 tickets 的功能,其中“审查和修复循环大约花了四个小时”。如果你看到第二轮全面审查开始,请告诉它针对已修复的发现运行有针对性的检查,然后停止。请预期第一次审查会发现真实的问题。运行的输出是一个由审查来完善的草稿,而不是可以单独交付的东西。
它是否像 implement 一样驱动 tdd?
现在会了,虽然一开始不会。运行进行中版本的用户注意到,“实现 subagents 不会继承 /tdd 指令”,因此一旦他们从一个 ticket 扩展到整个 spec,红-绿循环就停止了。现在,每个实现者都会用 tdd 构建其 ticket。仍然没有一个步骤,让你像在 implement 会话中那样交互式地确定接缝(seams)。因此,如果你希望接缝固定下来,请在 spec 或 tickets 中命名它们。
两个并行运行的实现者在同一个文件上发生冲突,或者为同一事物选择了不同的名称。
Worktree 不会消除冲突;它们只是把冲突推迟到合并时。根据工单文本写出的阻塞边,只是对每个工单将触及哪些文件的一种猜测;即使两个工单位于“代码库的不同部分”,它们仍可能共享一个消息目录、配置注册表或类型。每个实现者只能看到自己的工单和共享笔记,永远看不到另一个实现者正在进行的工作,因此某个用户的 Web 和移动端工单将同一个字符串分别添加为 blockedSince 和 blockedOn。当两个前沿工单触及同一个共享文件时,要么在它们之间添加一条阻塞边,让它们依次运行,要么让探索笔记确定每个工单要添加的确切名称。
被阻塞的工单永远不会开始,即使其阻塞项已经合并。
这是 GitHub 上的一个已知问题。跟踪器的 blocked-by 计数只有在阻塞项关闭时才会下降,而工单通常在 PR 合并时关闭,也就是运行的结束。跟踪器是起始图的正确来源,但在运行中途它是过时的。告诉编排器自行跟踪哪些工单已合并到集成分支,并据此计算前沿。
这会取代 Sandcastle 或 AFK 脚本吗?
不会。人们会这样问,是因为这些技能现在延伸到了实现层面:“Sandcastle 还有意义吗?你的技能现在似乎也能处理实现了。” implement-spec 让一个代理在一个 harness 会话内负责编排,它不需要基础设施,并且让你能够观察和引导。对于真正 AFK 的工作,确定性循环(Sandcastle、shell 脚本、CI 任务)更快、更便宜、更可靠,因为没有代理来做编排决策。
某个工单的关键测试在其 worktree 内被跳过,但它报告为绿色。
worktree 只包含 git 跟踪的内容。读取被 gitignore 的 fixtures、本地数据库或凭据的测试可能会在那里静默跳过。对于验证依赖于未跟踪内容的工单,告诉编排器改为在主 checkout 中运行它。
如果满足以下条件¶
- 只要图允许,多个实现者就会同时运行,而不是一个接一个。
- 一个工单在其最后一个阻塞项落到集成分支时立即开始,而不是在整个运行结束时开始。
- 每个工单的 trace 都显示
tdd正在运行,并且在代码之前有一个失败的测试。 - 合并到集成分支的操作是 fast-forward,而不是冲突解决。
- 运行在一个分支上结束,所有工单都已解决;只有当你的跟踪器需要 PR 时才创建 PR。
它适合的位置¶
implement-spec 是主链中的构建步骤,作为对每个工单运行一次 implement 的并行替代方案:
它的相邻技能是 to-tickets,它声明了作为任务图读取的阻塞边;以及 code-review,implement-spec 会在收尾前对集成分支运行它。当你不确定自己处于哪个流程时,ask-matt 是整个集合的路由器。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 skills13/skills