跳转到正文

撰写计划

在写任何代码之前,先把工作写清楚。


为什么计划优先于代码

实现计划是一份文档,它详细描述你打算构建什么以及如何构建——在写任何代码之前。

这与"先规划、后实施"这句话的通常含义不同。Superpowers 中的计划足够具体,以至于任何胜任的工程师(或 AI agent)都可以执行其中的任何任务,而无需猜测意图或做出未记录的架构决策。

如果你的计划需要执行者自行解读,那就不够好。


计划结构

每份计划都以一个头部区块开始,然后是编号的任务列表。

头部格式

# 实现计划:[功能名称]

## 上下文
[1–3 句话描述这解决了什么问题]

## 方案
[所选方案的简短描述,来自头脑风暴]

## 超出范围
[明确列出我们*不*在这次实现中做的事]

## 前置条件
[开始之前必须为真的事]

任务结构

每项任务必须包含:

1. 任务编号和标题

任务 3:为用户登录创建失败测试

2. 目标 一句话描述这项任务完成了什么。

3. 精确的文件路径 不是"在 auth 文件夹中",而是 src/auth/login.test.ts

4. 完整代码 不是"添加一个登录函数",而是确切的代码,完整且可运行。

5. 验证步骤 这项任务完成后如何验证。通常是运行测试套件的命令。

6. 预期输出 运行验证命令后你期望看到什么。


每项任务 2–5 分钟规则

计划中的每项任务都应该小到足以在 2–5 分钟内完成。

这个规则有两个目的:

第一: 它迫使任务足够小,以至于一个 subagent(一个新的、没有其他上下文的 AI 实例)可以完成它而不需要理解整个代码库。

第二: 它创造了一个自然的检查点节奏。每项任务完成后,都有一个明确的时刻来评估:计划还有效吗?有什么意外吗?

如果你发现自己在写一项"实现完整认证系统"的任务,那是一个信号:这项任务需要分解。


TDD 在计划中的体现

每项实现任务前面都必须有一项测试任务。计划结构强制执行 TDD:

任务 N:为 [行为] 编写失败测试        ← RED
任务 N+1:实现 [行为]               ← GREEN
[如果范围需要,重构在任务 N+1 内或作为任务 N+2]

没有测试任务前置的实现任务是计划缺陷。

当你审查计划时,检查这个配对是否对每项功能任务都成立。如果一项实现任务没有对应的测试任务,要么添加测试任务,要么拒绝计划。


YAGNI 和 DRY 在计划中

YAGNI(你不会需要它)

计划中的每项任务都应该有明确的当前需求理由。问:

"这项任务是当前功能所需的,还是我们在为可能的未来需求提前构建?"

如果答案是"为了以后"——删除这项任务。当以后到来时,再计划和实现它。未来的功能有未来的需求;今天你不知道那些需求是什么。

DRY(不要重复自己)

在撰写计划时,查找可以提取的重复模式。如果三项任务都"在类似位置添加类似内容",可能有一个单一的任务可以把它们全部做完,或者一个你应该先创建的共享工具函数。

DRY 是在计划层面处理的,而不是在执行中途发现的。


范围管理信号

以下信号表明计划需要修剪或重构:

信号问题是什么
超过 12 项任务计划可能太大,无法安全地作为单一分支交付
任何任务估计超过 10 分钟分解这项任务
任务依赖同一功能的并行任务重新排序或分离依赖项
"重构现有系统"的任务这应该是单独的计划
任务说"更新所有 X 以支持 Y"枚举具体的文件和更改
任务需要读者填补空白添加精确的代码和路径

计划审查流程

在执行开始之前,计划要经过三阶段审查:

阶段 1:完整性检查

  • 每项任务是否有精确的文件路径?
  • 每项任务是否有完整的、可运行的代码?
  • 每项实现任务是否有前置的测试任务?
  • 是否枚举了验证步骤?

阶段 2:设计对齐检查

  • 这份计划是否实现了头脑风暴中批准的设计?
  • 是否有任何任务超出了头脑风暴文档中明确的范围?
  • 超出范围的内容是否真的没有出现在任何任务中?

阶段 3:可执行性检查

  • 如果一个对代码库一无所知的工程师拿到这份计划,他们能够执行每项任务吗?
  • 任务之间是否存在未记录的依赖关系?
  • 是否有任何任务的成功标准含糊不清?

只有在三个阶段都通过后,计划才能进入执行阶段。


一份精心撰写的计划示例

# 实现计划:用户登录

## 上下文
用户目前必须手动输入凭据才能访问应用程序。
我们正在添加带有标准电子邮件/密码验证的登录表单。

## 方案
简单的服务器端会话,没有 JWT(来自头脑风暴,方案 A)

## 超出范围
- OAuth / 社交登录
- 记住我(持久化会话)
- 密码重置流程

## 前置条件
- 数据库迁移 #42(用户表)必须已运行
- AUTH_SECRET 环境变量必须已设置

---

任务 1:为登录表单验证编写失败测试
文件:src/auth/login.test.ts
目标:确认有一个失败测试捕获验证逻辑
代码:
  test('rejects empty email', () => {
    expect(validateLogin({ email: '', password: 'abc' })).toEqual({
      valid: false,
      error: 'Email is required'
    });
  });
验证:npm test -- --testPathPattern=login
预期输出:1 个失败(validateLogin 不存在)

任务 2:实现登录验证函数
文件:src/auth/login.ts
目标:使任务 1 的测试通过
代码:
  export function validateLogin({ email, password }) {
    if (!email) return { valid: false, error: 'Email is required' };
    if (!password) return { valid: false, error: 'Password is required' };
    return { valid: true };
  }
验证:npm test -- --testPathPattern=login
预期输出:1 通过,0 失败

[以此类推...]

计划是对你意图的正式声明。 如果你无法写清楚,你还没有准备好实现。如果你可以写清楚,实现就变成了执行一系列明确步骤的问题——而不是在代码中发现架构。