name: feature-plan description: 功能循环第 2 步。将 spec 转任务级 TDD 计划(每任务 2-5 分钟),产出到 docs/superpowers/plans/,链入 feature-tdd。 user-invocable: false
allowed-tools: Read Write Grep Skill AskUserQuestion
所有输出必须使用中文。
feature-plan
阶段范围(后端)
本 skill 服务于后端阶段。任务粒度限定为后端模块文件:controller / service / repository / DTO / 校验 / SQL migration。禁止生成 frontend/ 路径下的实现任务——UI 实现统一推迟到前端阶段(fe-feature-*)。
计划写作原则
- Plan 告诉 TDD 执行者做什么,不是怎么写代码——执行者是
feature-tdd(同一模型,全上下文),不是机械复制粘贴员 - Plan 锁定文件边界 + 测试意图 + API 形状 + 完成判据;代码由 TDD 红绿循环产出
- 禁止 dump 整个文件内容(build.gradle.kts / entity 类 / config 文件)到 plan——plan 和代码会成为两个 source of truth 并漂移;2000+ 行 plan 浪费上下文
- DRY、YAGNI、TDD、frequent commits
占位符规则
每个 step 必须写实际内容。以下属于 plan failures,绝不出现:
-
TBD/TODO/implement later/fill in details -
【人工填写:】— 这是 A 阶段标记(docs/01~10/CLAUDE.md/.env.local),B 阶段 plan 绝不能出现。需要具体值时:- 先查
.env.local/docs/07-环境配置.md/CLAUDE.md/ 现有代码并在 plan 中引用源 - 查不到 → 按
docs/04-技术规范.md/ 现有代码模式 / 框架官方推荐 / 最简实现 的优先级自主选定,在 plan 中以自动选用 X(来源: ...)注明 - 仅在四级都给不出合理推荐 + 决策影响重大时(核心契约 / 安全合规 / 不可逆架构)才
AskUserQuestion并记录答案
- 先查
- "Add appropriate error handling" / "add validation"(要具体到哪些错误码 / 哪些字段)
- "Similar to Task N"(相似任务各自写清楚测试意图 + 完成判据,不互相链接)
- 未在任何 task 定义的 types / functions / methods(类/方法首次出现的 task 必须给出 API 签名)
散文级"做什么"是 OK 的——执行器(
feature-tdd)会在 TDD 循环里决定"怎么写"。plan 的义务是约束范围,不是替 TDD 写代码。
执行步骤
-
收集输入:
- spec 文件
docs/superpowers/specs/<YYYY-MM-DD>-<REQ-id>.md(不存在则报错) - 相关代码指针(通过
Grep在现有代码定位待修改文件) -
docs/04-技术规范.md与docs/09-项目目录结构.md(编码规范 + 目录规范)
- spec 文件
范围检查:spec 跨多个独立子系统 → 提示拆分,每个 plan 应能独立产出可工作、可测试的软件
-
文件结构推导:
- 哪些文件 create / modify
- 每个文件单一职责,well-defined interface
- 一起变化的文件放一起;不按技术层切分
-
任务粒度推导(参考下方"任务原则"):
- 每个任务 = 一个 red-green-commit 单元
- 4 个 step:写失败测试 → 实现最小代码 → 子会话验证 PASS → commit
- 任务粒度 2-5 分钟
-
写 plan 到
docs/superpowers/plans/<YYYY-MM-DD>-<REQ-id>.md:- 按
${CLAUDE_SKILL_DIR}/templates/feature-plan-template.md渲染 - 文件已存在 → 征求用户确认后覆盖
- 按
-
Plan 自审(inline 修,无须用户等待):
- 占位符扫描:按"占位符规则"清单逐项 grep;命中即修
- Spec coverage:skim spec 每节,能指向至少一个 task 吗?list gaps 并补 task
-
类型一致性:tasks 之间签名 / 方法名 / 属性名 / 错误码是否一致(Task 3 的
clearLayers()和 Task 7 的clearFullLayers()是 bug)
-
输出 + 链 feature-tdd(直接做这两件事,不要输出"回交父 skill / 交给 caller / 等下一步 / 准备好了请检查"之类的桥接叙述——那些会被解读为 turn 结束信号):
- 输出一行
feature-plan: <REQ> → <path> -
同一 turn 内立即
Skill(feature-tdd)
- 输出一行
任务原则
Plan 文件头
每个 plan 必须以以下头部开始:
# [Feature Name] Implementation Plan
> **Execution:** Parent skill `feature-tdd` executes this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** [一句话描述]
**Architecture:** [2-3 句方法论]
**Tech Stack:** [关键技术 / 库]
---
Task 结构
每个 task 是 red-green-commit 单元。捕获意图和边界,代码留给 TDD:
### Task N: [组件名]
**Files:**
- Create: `exact/path/to/File.java`
- Modify: `exact/path/to/Existing.java:123-145`
- Test: `tests/exact/path/to/FileTest.java`
**API shape**(只写需要约束实现的签名;内部实现留给 TDD):
- `LoginService#login(LoginRequest req) : LoginResponse`
- `throws AccountLockedException when iLoginFailCount ≥ 5 within tLockUntil window`
- [ ] **Step 1: 写失败测试**
- 测试名: `LoginServiceTest#loginWithBadPassword_incrementsFailCount_returns40101`
- 意图: 错误密码 → `iLoginFailCount += 1`;第 5 次 → 设置 `tLockUntil = now + 15min`;返回码 40101
- 子会话确认 FAIL(函数/类不存在)
- [ ] **Step 2: 实现最小代码**
- 目标: 让 Step 1 测试通过;不多做
- 涉及文件: `LoginService.java`, `SftLoginInfoMapper.java`
- [ ] **Step 3: 子会话验证 PASS**
- [ ] **Step 4: Commit**
- `git add <文件>`
- `git commit -m "feat(sys): 登录失败计数 + 锁定 REQ-SYS-001"`
允许的代码块场景
少数例外,需要写死而非让 TDD 自由发挥:
-
DDL / migration 文件:
V_n__*.sql的 ALTER/CREATE 语句——schema 是事实源、不是 TDD 红绿产物 - 合同级常量:API 错误码表、JWT claim 名、Redis key 模式——跨模块消费,必须在 plan 锁定
- 测试断言形状(可选):一句话说不清"测什么"时,给个 3-5 行断言 sketch 是 OK 的
除此之外一律散文 + 签名描述,不贴完整文件。
记住
- Exact file paths always
- Exact commands with expected output(测试运行 + git 操作)
- API signatures / class names / error codes / contract values — 必须写死
- Internal implementation code — 不写;留给 TDD 阶段
- DRY、YAGNI、TDD、frequent commits
参考
${CLAUDE_SKILL_DIR}/templates/feature-plan-template.md- 上游:
feature-brainstorm - 下游:
feature-tdd