Speckit Tasks 是怎么把技术方案拆成可执行任务的?
先梳理一下 Spec Kit 的整体流程,这样才能理解 Tasks 这个环节到底处在什么位置:

Specify → Clarify → Plan → Tasks → Implement
Tasks 夹在 Plan 和 Implement 中间,承上启下。
它的输入,是前面已经生成好的设计文档:
spec.md
plan.md
research.md
data-model.md
contracts/
quickstart.md
输出只有一份:tasks.md,也就是可以直接拿去执行的任务清单。
这个环节的分量很重——它直接决定了后续 /speckit-implement 是按计划稳步推进,还是走到哪算哪。
一、Tasks 在整个流程里的位置
简单来说:
技术方案
↓
/speckit-tasks
↓
可执行任务清单
二、Tasks 阶段解决什么问题?
很多时候,plan.md 虽然已经把技术方案交代清楚了,但离“直接上手干”还有距离。
拿忘记密码功能来举例。Plan 里已经明确:
- 前端只调用
services/backend backend作为中间层调用auth-serviceauth-service是认证事实源- 当前阶段验证码免校验
- 新密码使用 Argon2id
- 重置成功后 Refresh Token 失效
- 不生成任务级单元测试
但这些都是“方案层面的描述”。真要动手开发,还得回答一系列更具体的问题:
- 先建哪些 DTO?
- 先改 auth-service 还是 backend?
- 前端 API 什么时候接入?
- 哪些任务可以并行?
- 哪些任务之间存在前置依赖?
- 每个用户故事怎么独立验收?
这正是 /speckit-tasks 要解决的问题——把方案级描述,翻译成可执行的任务颗粒。
三、Tasks 的核心产物长什么样?
在忘记密码案例里,生成的任务文件路径是:
specs/20260605-104356-forgot-password/tasks.md
开头会清晰标注输入来源:
Input: Design documents from specs/20260605-104356-forgot-password/
Prerequisites: plan.md, spec.md, research.md, data-model.md, contracts/forgot-password-api.md, quickstart.md
这说明 tasks.md 不是凭空生成的——它是从前面的所有设计文档推导出来的。这一点很重要。如果 plan.md 没写清楚,tasks.md 也很难拆得干净利落。
四、任务格式:每一条都要可执行
忘记密码案例里的任务遵循这样的格式:
[ID] [P?] [Story] Description
各标记的含义:
| 标记 | 含义 |
|---|---|
ID | 任务编号,例如 T001、T002 |
[P] | 可并行执行(不修改同一文件、不依赖未完成任务) |
[Story] | 所属用户故事,例如 [US1]、[US2] |
| Description | 明确动作和文件路径 |
举个例子:
- [ ] T016 [US1] 在 AuthService 中实现 resetForgotPassword 方法并按手机号查询 Users in services/auth-service/src/auth/auth.service.ts
这条任务包含了完整信息:
- 编号:
T016 - 用户故事:
US1 - 动作:实现
resetForgotPassword方法 - 精确到文件路径:
services/auth-service/src/auth/auth.service.ts
这才是一条合格的任务。它不像“实现忘记密码功能”这种泛泛而谈的表述,而是能直接指导开发者或 AI 去改哪个文件、做什么事。
五、Phase 1:Setup,先读现有代码
Tasks 不是一上来就让 AI 写代码。在忘记密码案例里,第一阶段叫:
## Phase 1: Setup (Shared Infrastructure)
这个阶段的目标不是实现功能,而是先摸清现有代码的结构和风格。
比如:
- [ ] T001 阅读并确认 auth-service 认证接口现有风格 in services/auth-service/src/auth/auth.controller.ts
- [ ] T002 阅读并确认 auth-service 现有密码哈希、缓存和 Token 处理 in services/auth-service/src/auth/auth.service.ts
- [ ] T003 [P] 阅读并确认前端调用 backend 认证 API 的封装方式 in apps/web/src/api/auth/index.ts
- [ ] T004 [P] 阅读并确认忘记密码页面 store 当前 mock 行为 in apps/web/src/pages/ForgotPassword/useStore.ts
- [ ] T005 [P] 阅读并确认 backend 认证袋里控制器风格 in services/backend/src/auth/auth.controller.ts
- [ ] T006 [P] 阅读并确认 backend 调用 auth-service 的 AuthClientService 封装 in services/backend/src/shared/auth-client.service.ts
这个设计非常实用。很多 AI 写错代码,不是不会写,而是没先看现有代码风格。Setup 阶段强制做的事情包括:确认 auth-service 现有 Controller 风格、确认其密码和 Token 处理逻辑、摸清 backend 封装 auth-service 的方式、了解前端 ForgotPassword 页面的 mock 行为——这样一来,后续实现更容易复用已有代码,而不是另起炉灶造一套。
六、Phase 2:Foundational,先建公共基础
第二阶段是:
## Phase 2: Foundational (Blocking Prerequisites)
这些是阻塞性基础任务。
在忘记密码案例里,基础任务包括:
- [ ] T007 创建 auth-service 发送验证码请求 DTO
- [ ] T008 创建 auth-service 重置密码请求 DTO
- [ ] T009 [P] 创建 auth-service 忘记密码通用响应 DTO
- [ ] T010 [P] 创建 backend 发送验证码请求 DTO
- [ ] T011 [P] 创建 backend 重置密码请求 DTO
- [ ] T012 [P] 创建 backend 忘记密码通用响应 DTO
- [ ] T013 在 auth-service 认证服务错误码中补充忘记密码相关错误码和消息
- [ ] T014 在 backend 认证错误码或异常映射中补充忘记密码袋里失败相关错误处理
- [ ] T015 在前端认证 API 中定义调用 backend 的忘记密码请求/响应类型
这些任务不属于某一个具体的用户故事,而是所有故事都要依赖的基础设施。DTO、响应类型、错误码、前端 API 类型——先把这些准备好,后面 US1、US2、US3 才能顺利推进。这也是 Tasks 阶段的核心价值。
七、Phase 3:US1,先做 MVP 主链路
第三阶段对应第一个用户故事:
## Phase 3: User Story 1 - 通过手机号重置密码 (Priority: P1) MVP
目标是:用户可提交手机号、新密码和确认密码完成密码重置,能使用新密码登录、旧密码失效;前端只调用 backend,backend 调用 auth-service 完成认证处理。
这是 MVP 级别的用户故事。也就是说,只要 US1 完成,忘记密码的主链路就基本可用了。
它拆出的任务非常具体:
- [ ] T016 [US1] 在 AuthService 中实现 resetForgotPassword 方法并按手机号查询 Users
- [ ] T017 [US1] 在 AuthService resetForgotPassword 中校验账号可用状态和新旧密码不能相同
- [ ] T018 [US1] 在 AuthService resetForgotPassword 中使用 Argon2id 更新 password_hash、password_algorithm 和 updated_at
- [ ] T019 [US1] 在 AuthService resetForgotPassword 中清理密码缓存和用户预加载缓存
- [ ] T020 [US1] 在 AuthService resetForgotPassword 中调用 RefreshTokenRedisService 删除用户全部 Refresh Token
- [ ] T021 [US1] 在 auth-service AuthController 中新增 POST /auth/forgot-password/reset 内部认证接口
- [ ] T022 [US1] 在 backend AuthController 中新增 POST /auth/forgot-password/reset 前端入口并调用 AuthClientService
- [ ] T023 [US1] 在前端认证 API 中新增调用 backend 的 resetForgotPassword 请求方法
- [ ] T024 [US1] 将 ForgotPassword store 的 submitResetPassword 改为调用 resetForgotPassword API
- [ ] T025 [US1] 移除 ForgotPassword store 中重置密码时的 localStorage 验证码匹配逻辑
- [ ] T026 [US1] 调整 ForgotPassword 页面提交失败文案,避免把免校验阶段误提示为验证码错误
可以看到,这里不是简单地按“前端、后端”分组,而是围绕“用户故事可独立验收”来拆。US1 完成后,就能验证:已注册手机号可以重置密码、新密码可以登录、旧密码不能登录、前端入口是 backend、backend 调用 auth-service——整个主链路就通了。
八、Phase 4:US2,处理验证码未接入阶段
第二个用户故事是:
User Story 2 - 在验证码未接入阶段完成可用恢复流程
它来自 Clarify 阶段的一个关键澄清:当前验证码能力未接入,暂不校验验证码;只要手机号和密码字段合法即可重置。
所以 Tasks 里专门拆了一组任务:
- [ ] T027 [US2] 在 AuthService 中实现 sendForgotPasswordCode 模拟成功方法
- [ ] T028 [US2] 在 auth-service AuthController 中新增 POST /auth/forgot-password/send-code 内部认证接口
- [ ] T029 [US2] 在 backend AuthController 中新增 POST /auth/forgot-password/send-code 前端入口并调用 AuthClientService
- [ ] T030 [US2] 在前端认证 API 中新增调用 backend 的 sendForgotPasswordCode 请求方法
- [ ] T031 [US2] 将 ForgotPassword store 的 sendCode 改为调用 sendForgotPasswordCode API 并保留倒计时
- [ ] T032 [US2] 移除 ForgotPassword store 中发送验证码时写入 localStorage 的逻辑
- [ ] T033 [US2] 根据当前阶段免校验策略调整 ForgotPassword schema 中 code 字段规则
这组任务解决的是:验证码暂时没接入,但前端页面已经有“获取验证码”按钮。它不会直接删除验证码 UI,而是保留页面交互,用模拟成功或友好提示来保证流程不被阻断。这就是 Tasks 阶段对 Clarify 结果的具体承接。
九、Phase 5:US3,处理安全和账号枚举保护
第三个用户故事是关于安全的:
User Story 3 - 保护账号存在性和敏感信息
目标是:忘记密码流程不向用户侧暴露手机号是否注册,不泄露密码、验证码、Token 或内部错误细节。
对应任务包括:
- [ ] T034 [US3] 在 AuthService 忘记密码流程中统一账号不存在和账号不可用的用户侧错误行为
- [ ] T035 [US3] 在 AuthService 忘记密码流程中增加脱敏安全日志且不记录明文密码、完整验证码或完整 Token
- [ ] T036 [US3] 在 backend AuthController 忘记密码袋里中统一外部失败提示并隐藏 auth-service 内部错误细节
- [ ] T037 [US3] 在前端 ForgotPassword 页面统一重置失败提示,避免暴露账号存在性
- [ ] T038 [US3] 确认 logout 相关敏感日志不影响本功能并记录后续治理项
这类任务在普通 AI 编码中很容易被忽略。如果只说“实现忘记密码”,AI 可能只写成功路径。但 Tasks 阶段会把安全需求拆成明确的任务项,确保它不是一句口号,而是真正进入执行清单。
十、Phase 6:Polish,统一验证和收尾
最后一个阶段是:
## Phase 6: Polish & Cross-Cutting Concerns
它处理跨用户故事的收尾和验证。比如:
- [ ] T039 [P] 对照契约检查 backend 对前端接口路径、请求字段和响应字段
- [ ] T040 [P] 对照契约检查 auth-service 内部接口路径、请求字段和响应字段
- [ ] T041 [P] 对照 quickstart 执行并补充手工验收结果记录
- [ ] T042 在 services/auth-service 执行 npm run lint 并修复发现的问题
- [ ] T043 在 services/auth-service 执行 npm run build 并修复发现的问题
- [ ] T044 在 services/backend 执行 npm run lint 并修复发现的问题
- [ ] T045 在 services/backend 执行 npm run build 并修复发现的问题
- [ ] T046 在 apps/web 执行 npm run lint 并修复发现的问题
- [ ] T047 在 apps/web 执行 npx tsc --noEmit 并修复发现的问题
- [ ] T048 更新 quickstart 中最终验证结果、backend 中间层调用链和当前阶段验证码免校验风险提示
这一步不是锦上添花,而是质量闭环。考虑到这个 feature 已经明确“不生成任务级单元测试”,那 lint、build、typecheck 和 quickstart 手工验收就更加重要了。
十一、Tasks 如何表达依赖关系?
tasks.md 里不仅有任务列表,还有依赖顺序。
忘记密码案例里的 Phase 依赖关系是:
Phase 1 Setup:无依赖,可立即开始
Phase 2 Foundational:依赖 Phase 1,阻塞所有用户故事
Phase 3 US1:依赖 Phase 2,是 MVP 主链路
Phase 4 US2:依赖 Phase 2,可与 US1 部分并行,但要注意同文件冲突
Phase 5 US3:依赖 Phase 2,建议在 US1 后进行
Phase 6 Polish:依赖目标用户故事完成
用户故事之间的依赖关系也明确:
US1:MVP,可在 Phase 2 后独立实现
US2:可在 Phase 2 后独立实现,但与 US1 存在同文件协调
US3:依赖忘记密码服务方法和 backend 袋里方法存在,以便统一错误和日志
这个依赖说明很关键——它告诉执行者:哪些任务必须先做、哪些可以并行、哪些虽然理论上可并行但会改同一个文件需要避免冲突。
十二、[P] 标记:哪些任务可以并行?
在 tasks 中,[P] 表示可并行。
比如 Setup 阶段:
- [ ] T003 [P] 阅读并确认前端调用 backend 认证 API 的封装方式
- [ ] T004 [P] 阅读并确认忘记密码页面 store 当前 mock 行为
- [ ] T005 [P] 阅读并确认 backend 认证袋里控制器风格
- [ ] T006 [P] 阅读并确认 backend 调用 auth-service 的 AuthClientService 封装
这些任务读取不同文件,不互相依赖,所以可以并行。
Foundation 阶段也有并行任务:
- [ ] T009 [P] 创建 auth-service 忘记密码通用响应 DTO
- [ ] T010 [P] 创建 backend 发送验证码请求 DTO
- [ ] T011 [P] 创建 backend 重置密码请求 DTO
- [ ] T012 [P] 创建 backend 忘记密码通用响应 DTO
因为它们创建的是不同文件,可以并行完成。
但像修改 services/auth-service/src/auth/auth.service.ts、services/backend/src/auth/auth.controller.ts、apps/web/src/pages/ForgotPassword/useStore.ts 这类任务,就不能随便并行——这些是热点文件,多个任务都可能修改它们,容易产生冲突。Tasks 阶段会在 Parallel Team Strategy 中明确提醒这一点。
十三、Implementation Strategy:先做 MVP,再增量交付
忘记密码的 tasks 里还给出了明确的实现策略。
MVP First
1. 完成 Phase 1 和 Phase 2
2. 完成 Phase 3 的 US1 后暂停
3. 验证:前端调用 backend,backend 调用 auth-service;已注册手机号可重置密码,新密码可登录,旧密码不可登录
4. MVP 验证通过后再进入 US2/US3
这是一种很实用的交付方式——先把最核心的“重置密码主链路”做通,再处理验证码模拟和安全增强。
Incremental Delivery
1. Setup + Foundational:准备 DTO、错误码、前端 API 类型
2. US1:完成真实密码重置主链路
3. US2:完成验证码未接入阶段的模拟发送和免校验一致性
4. US3:完成账号枚举保护和敏感信息保护
5. Polish:执行 lint、build、typecheck 和 quickstart 手工验收
这样一来,功能可以分阶段验收,而不是等所有任务堆在一起最后才发现问题。
十四、Tasks 阶段最容易踩的坑
1. 任务太大,不可执行
不好的任务:- [ ] 实现忘记密码功能
好的任务:- [ ] 在 AuthService 中实现 resetForgotPassword 方法并按手机号查询 Users in services/auth-service/src/auth/auth.service.ts
差别在于后者精确到文件和动作,可以直接执行。
2. 没有先拆基础任务
如果不先拆 DTO、错误码、响应类型这些基础任务,后面写业务时就会边写边补,任务依赖会变得混乱。所以 Foundation 阶段很重要。
3. 没有按用户故事拆分
如果只按“前端任务、后端任务”拆,很容易出现一个故事做不完整的情况。更好的方式是围绕用户价值来拆:US1 能重置密码、US2 验证码未接入也不阻断、US3 保护账号存在性和敏感信息——这样每个故事都能独立验收。
4. 忽略验证任务
实现任务写完不代表功能完成。像忘记密码这种功能,最后必须要有契约检查、lint、build、typecheck、quickstart 手工验收、风险提示更新——缺一不可。
十五、总结
/speckit-tasks 的本质,是把一份技术方案翻译成一份可执行的任务清单。
它通常做这几件事:
读取 spec/plan/research/data-model/contracts/quickstart
↓
拆出 Setup 阶段
↓
拆出 Foundational 基础任务
↓
按 User Story 拆实现任务
↓
补充依赖关系和并行机会
↓
补充验证与收尾任务
在忘记密码案例里,tasks.md 最终拆出了:
- Setup:先阅读和确认现有结构
- Foundational:创建 DTO、错误码、前端 API 类型
- US1:完成手机号重置密码 MVP 主链路
- US2:完成验证码未接入阶段的模拟发送和免校验一致性
- US3:完成账号枚举保护和敏感信息保护
- Polish:契约核对、lint/build/typecheck、quickstart 手工验收
这一步完成之后,AI 或开发者就不再需要猜“下一步该做什么”了。
下一篇会继续讲 /speckit-implement:当任务清单已经生成,Spec Kit 是如何按任务真正落地代码的。
