SKILL.md 9.9 KB

name: feature-spec description: 统一功能循环第 1 步(后端 REQ / 前端 FE 共用,由 phase 参数区分)。交互式 Q&A → 产出"规格 + 任务级 TDD 计划"合并文档到 docs/superpowers/specs/,链入 feature-tdd。 user-invocable: false

allowed-tools: Read Write Grep Glob Skill AskUserQuestion Bash(mysql *)

所有输出必须使用中文。

feature-spec

统一功能循环第 1 步,后端(REQ-XXX-NNN)和前端(FE-NN)共用,由 phase 参数区分范围与上下文。交互式 Q&A → 产出"规格 + 任务级 TDD 计划"合并文档 → 链入 feature-tdd

入参(由上游 skill 传入):

  • phasebackend | frontend
  • idREQ-XXX-NNN(backend)或 FE-NN(frontend)
  • name:功能名称
  • associated_reqs[]:(仅 frontend)关联的 REQ 卡片 id 列表
  • associated_prototypes[]:(仅 frontend)关联的 prototype 文件路径列表

占位符规则

本 skill 写的 spec 是 CC 内部推理产物,不是用户审阅文档。不允许 【人工填写:...】 占位符——A 阶段标记只在 docs/01~10 / CLAUDE.md / .env.local 使用。需要具体值时:

  1. 先查 .env.local + docs/04 §零环境 / CLAUDE.md / 现有代码 / 关联 prototype(frontend 时)。值已落地某处 → spec 中引用源(例 "JWT_SECRET 从 .env.local 读取,application.yml${JWT_SECRET} 注入")
  2. 再问:查不到 → AskUserQuestion 问用户,记录答案到 spec
  3. 绝不【人工填写:】 占位符;若 1 + 2 都解决不了,spec 必须写出具体阻塞点(不是泛化占位符),Q&A 继续直到解决

阶段范围

phase=backend

产出范围限定为:controller / service / repository / DTO / 校验 / SQL migration / REST 契约。

docs/01-需求清单/<module>/<req_id>.md忽略 UI 描述(输入控件类型、按钮位置、列表布局等),但校验规则、业务规则仍要落到后端 DTO + service。UI 实现统一推迟到前端阶段(phase=frontend)。

上下文来源:

  • REQ 卡片 docs/01-需求清单/<module>/<id>.md
  • 涉及的数据表定义(取自 docs/03-数据库设计文档.md 或实时 mysql 查询)

phase=frontend

产出范围限定为:组件树 / 页面状态机 / 交互流程 / API 调用 / Design Tokens 引用 / 业务校验前端复刻。不涉及 SQL / migration / controller / service / DTO(后端阶段已完成)。

一个 FE 是业务功能粒度,可能关联多个 prototype 文件区域和多个 REQ。

上下文来源:

  • 页面骨架:Read 所有 associated_prototypes[](含 anchor 时聚焦相应区域),作为布局权威
  • 业务规则:Read 所有 associated_reqs[] 对应的 docs/01-需求清单/<module>/<REQ-id>.md,提取业务校验规则、acceptance、UI 描述
  • API 契约:Read docs/05-API接口契约.md,按 associated_reqs[] 过滤出本 FE 消费的端点
  • Design Tokens / 交互约定:Read docs/04-技术规范.md「前端 Design Tokens / 交互约定」段(lite 已把原 docs/06 内容并入 docs/04),作为色值 / 状态色 / 交互规范的引用源
  • 前端组件库:Read docs/04-技术规范.md § 零frontend.ui_lib(如 Ant Design / Element Plus),决定组件选型

执行步骤

步骤 1:收集上下文

按上方"阶段范围"对应的上下文来源读取所有相关文档。

步骤 2:评估 scope

  • 单 spec 容纳得下吗?
  • phase=backend:跨多个独立子系统(如"含登录 + 文件存储 + 计费 + 分析")→ 先提示分解,每个子项目独立 brainstorm
  • phase=frontend:跨多页 / 多业务 → 提示拆分,每个 FE 应独立可测试

步骤 3:交互式 Q&A

参考下方"Q&A 原则"进行交互式问答:

  • phase=backend:聚焦 goal / 输入输出 / 业务规则 / 约束 / schema / API 引用 / acceptance criteria
  • phase=frontend:聚焦组件树、页面状态机、交互流程、API 调用一致性、Design Tokens 引用、业务校验前端复刻。不要讨论 SQL / migration / controller / service / DTO

一次一问 AskUserQuestion,仅对真模糊点;多选题优先。决策完成后挑一种 approach;trade-off 直接内嵌 spec,不设确认 gate

步骤 4:写合并文档

写到 docs/superpowers/specs/<YYYY-MM-DD>-<id>.mdid = REQ-XXX-NNNFE-NN):

  • ${CLAUDE_SKILL_DIR}/templates/feature-spec-plan-template.md 渲染
  • 只填写当前 phase 对应的规格小节(另一 phase 的小节留空或删除)
  • 规格后紧接任务级计划(plan 部分)
  • 计划粒度:每任务 2-5 分钟,= 一个 red-green-commit 单元

计划写作原则(两 phase 通用):

  • Plan 告诉 TDD 执行者做什么,不是怎么写代码
  • Plan 锁定文件边界 + 测试意图 + API / Props 形状 + 完成判据;代码由 TDD 红绿循环产出
  • 禁止 dump 整个文件内容到 plan(pom.xml / entity 类 / vue 组件源码 / config 文件)
  • phase=backend 任务:impl_file 禁止以 frontend/ 开头;phase=frontend 任务:impl_file 必须以 frontend/ 开头
  • 每个任务含 4 步:写失败测试 → 实现最小代码 → 子会话验证 PASS → commit
  • phase=frontend 每个任务必须标注"测试先行类型":jsdom 组件测试Playwright E2E

文件已存在 → 征求用户确认后覆盖。

步骤 5:Spec + Plan 自审(inline 修,无须用户等待)

Spec 部分:

  • 占位符扫描TBD / TODO / 【人工填写:】 / 含糊段 → 修(按"占位符规则"流程解决)
  • 内部一致性:节与节是否矛盾?架构是否匹配功能描述?
  • 范围检查:单 plan 能消化吗?还是需要分解
  • 歧义检查:任何 requirement 两种解读?挑一个写明
  • phase=frontend 额外检查:全文不得出现 TBD / @todo / controller / SQL / service / migration → 命中则修正后重渲染

Plan 部分:

  • 占位符扫描TBD / TODO / implement later / fill in details / 【人工填写:】 → 修
  • Spec coverage:skim spec 每节,能指向至少一个 task 吗?list gaps 并补 task
  • 类型一致性:tasks 之间签名 / 方法名 / 属性名 / 错误码一致(Task 3 的 clearLayers() 和 Task 7 的 clearFullLayers() 是 bug)
  • phase=frontend:每个任务的 impl_file 路径必须以 frontend/ 开头;命中 backend/ / sql/ / scripts/ → 修正后重渲染

步骤 6:输出 + 链 feature-tdd

直接做这两件事,不要输出"回交父 skill / 交给 caller / 等下一步 / 准备好了请检查"之类的桥接叙述——那些会被解读为 turn 结束信号)

  • 输出一行 feature-spec: <id> → <path>
  • 同一 turn 内立即 Skill(feature-tdd) 传入 { phase, id }

Q&A 原则

  • 一次一问 — 不堆问题
  • 多选题优先 — 答更快
  • 仅对真模糊点问 — 不造确认问题
  • YAGNI — 删 spec 中不必要的功能
  • 渐进理解 — 不明白就问
  • 无审批 gate — 写 spec 即 commit;分歧落地为具体 Q&A 项,不靠"等用户确认"

任务原则

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`(或 `frontend/src/...`- Modify: `exact/path/to/Existing.java:123-145`
- Test: `tests/exact/path/to/FileTest.java`
- 测试先行类型: jsdom 组件测试(仅 phase=frontend 需标注)

**API shape / Props shape**(只写需要约束实现的签名;内部实现留给 TDD):
- `LoginService#login(LoginRequest req) : LoginResponse`

- [ ] **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 文件(phase=backend):V_n__*.sql 的 ALTER/CREATE 语句——schema 是事实源
  • 合同级常量:API 错误码表、JWT claim 名、Redis key 模式——跨模块消费,必须锁定
  • 路由配置(phase=frontend):routes.ts 中 path 注册(路径是契约级)
  • API client 契约(phase=frontend):fetch 包装函数签名 + headers + 错误码 mapping
  • Design Tokens 名称(phase=frontend):var(--color-primary) 列表
  • 测试断言形状(可选):一句话说不清"测什么"时,给个 3-5 行断言 sketch

除此之外一律散文 + 签名描述,不贴完整文件

记住

  • 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-spec-plan-template.md
  • 上游(backend):module-start
  • 上游(frontend):frontend-start
  • 下游:feature-tdd