首页
/ Spec Kit `specify` 命令深度解析:从自然语言描述到质量验证的功能规格书

Spec Kit `specify` 命令深度解析:从自然语言描述到质量验证的功能规格书

2026-09-06 13:07:43作者:谭伦延

Spec Kit 的 specify 命令模板 是 Spec-Driven Development(SDD)工作流的第一个核心环节:它接收一段自然语言的功能描述,生成短名称、创建特性目录、基于模板写出 spec.md,并通过质量清单进行多轮自我验证。读完本文,你将掌握 specify 命令的完整执行流程——包括扩展钩子(extension hooks)、特性目录解析规则、规格书质量标准与澄清问题(clarification)机制——并能在自己的项目中正确配置和调试这条链路。

一、命令定位:SDD 工作流的第一环

在 Spec Kit 中,每个核心命令(specifyplantasksimplement 等)都以 Markdown 命令模板的形式分发。项目根目录下的 specify.md 会被 specify init 安装到各 AI 编码工具的命令/技能目录中,其中的 __SPECKIT_COMMAND_SPECIFY__ 等占位符会在安装时按目标工具的调用风格被替换为真实的命令调用串——这一替换逻辑实现于 integrations/base.py,它用正则 __SPECKIT_COMMAND_([A-Z][A-Z0-9_]*)__ 匹配占位符并完成渲染。

模板开头的 YAML frontmatter 声明了这条命令的“交接”(handoffs)关系:

---
description: Create or update the feature specification from a natural language feature description.
handoffs:
  - label: Build Technical Plan
    agent: speckit.plan
    prompt: Create a plan for the spec. I am building with...
  - label: Clarify Spec Requirements
    agent: speckit.clarify
    prompt: Clarify specification requirements
    send: true
---

这说明 specify 的产出(spec.md)是后续 clarify 命令plan 命令 的输入。整个链条是:specify(写规格)→ clarify(消除模糊)→ plan(技术计划)→ tasks(任务拆解)→ implement(实现)。理解这一点,才能理解 specify 模板里为什么反复强调“只写 WHAT/WHY,不写 HOW”。

二、用户输入与执行前的扩展钩子检查

2.1 用户输入

命令模板首先读取用户输入($ARGUMENTS),并规定:如果用户输入非空,必须先考虑它specify 的触发消息中,跟在命令关键字后面的文本就是功能描述(feature description);即使模板里出现了字面的 {ARGS},也应假设描述就在当前会话中,除非用户发出了空命令,否则不应要求用户重复。

2.2 before_specify 前置钩子

在写任何规格之前,模板要求执行“Pre-Execution Checks”,核心是检查项目根目录下的 .specify/extensions.yml

  • 若文件存在,读取并查找 hooks.before_specify 下的条目;
  • 若 YAML 无法解析或无效,静默跳过钩子检查,正常继续;
  • 过滤掉 enabled 显式为 false 的钩子;没有 enabled 字段的钩子视为默认启用;
  • 不解释、不评估钩子的 condition 表达式:无 condition(或为 null/空)的钩子视为可执行;定义了非空 condition 的钩子跳过,把条件求值交给 HookExecutor 实现。

对于每个可执行钩子,按 optional 标志分两种输出:

  • 可选钩子optional: true):输出说明块,包含扩展名、命令 /{command}、描述和 prompt,提示用户如何手动执行;
  • 强制钩子optional: false):输出说明块并附带 EXECUTE_COMMAND: {command},模板明确要求“发出块之后必须真正调用该钩子并等待其完成”,且调用方式可能与字面 {command} 不同(例如 skills 模式下的 agent 会以 /skill:speckit-...$speckit-... 运行)。

典型的前置钩子来自 git 扩展的 feature 命令:它只负责创建/切换到特性分支并输出含 BRANCH_NAMEFEATURE_NUM 的 JSON,底层脚本为 create-new-feature-branch.sh(Bash)或 create-new-feature-branch.ps1(PowerShell)。若用户显式提供了 GIT_BRANCH_NAME,要透传给钩子,让分支脚本绕过所有前缀/后缀生成、直接使用该值。

三、特性目录解析:SPECIFY_FEATURE_DIRECTORY 的确定规则

这是 specify 命令最容易踩坑的部分。规格文件默认存放在 specs/ 目录下,目录名由“前缀 + 短名称”构成,解析顺序为:

  1. 若用户显式提供了 SPECIFY_FEATURE_DIRECTORY(环境变量、参数或配置),原样使用;
  2. 否则自动在 specs/ 下生成:
    • 检查 [.specify/init-options.json] 中的 feature_numbering(首选)或 branch_numbering(已弃用,仅为迁移兼容,未来版本会移除);
    • "timestamp" 模式:前缀为 YYYYMMDD-HHMMSS(当前时间戳);
    • "sequential" 或缺省:前缀为 NNN(扫描 specs/ 下已有目录后取下一个可用三位数);
    • 目录名形如 <prefix>-<short-name>,例如 003-user-auth20260319-143022-user-auth
    • SPECIFY_FEATURE_DIRECTORY 设为 specs/<directory-name>
    • 若实际使用的是 branch_numbering(而 feature_numbering 不存在),需输出一行弃用警告:⚠️ branch_numbering in init-options.json is deprecated. Rename to feature_numbering.

短名称(short name)的生成规则是 2–4 个词的 action-noun 格式,需保留技术术语与缩写:

  • “I want to add user authentication” → user-auth
  • “Implement OAuth2 integration for the API” → oauth2-api-integration
  • “Create a dashboard for analytics” → analytics-dashboard
  • “Fix payment processing timeout bug” → fix-payment-timeout

3.1 创建目录与持久化 feature.json

解析完成后,命令执行:

  • mkdir -p SPECIFY_FEATURE_DIRECTORY
  • 通过 Spec Kit 的 preset/模板解析栈(等价于 specify preset resolve spec-template)解析当前生效的 spec-template
  • 将解析出的模板拷贝为 SPECIFY_FEATURE_DIRECTORY/spec.md,并将 SPEC_FILE 指向该文件;
  • 把解析后的真实路径写入 .specify/feature.json
{
  "feature_directory": "specs/003-user-auth"
}

这里模板特别强调:写入的是实际解析后的路径值(如 specs/003-user-auth),而不是字面量 SPECIFY_FEATURE_DIRECTORY。这样下游命令(plantasks 等)就能通过 feature.json 定位特性目录,而不必依赖 git 分支命名约定。

模板解析的底层实现见 resolve_template.py:它调用 common.resolve_template_content(template_name, repo_root),按项目模板覆盖栈(override stack)返回最终内容,支持 --json 输出 TEMPLATE_NAME / TEMPLATE_CONTENT 两个字段;模板栈的调试方法在 docs/reference/presets.md 中也有说明(specify preset resolve <name> 可追踪哪个文件胜出)。

三条 IMPORTANT 约束值得单独记住:

  • 每次 specify 调用只创建一个特性
  • 规格目录名与 git 分支名相互独立——两者可以相同,但那是用户的选择;
  • 规格目录和文件永远由本命令创建,钩子从不创建它们(分支创建才归钩子管)。

四、执行流程:从描述到规格书的八个步骤

模板定义了如下执行流(该列表的编号连续性与无重复性由回归测试 tests/test_specify_template_numbering.py 守护——它断言主执行列表的序号必须是从 1 到 8 无缺口的连续序列):

  1. 解析用户描述:从参数中提取功能描述;若为空,报错 No feature description provided
  2. 提取关键概念:识别 actors(参与者)、actions(动作)、data(数据)、constraints(约束)。
  3. 处理不明确之处
    • 基于上下文与行业标准做有依据的推测(informed guesses);
    • 仅当满足以下条件之一时才标记 [NEEDS CLARIFICATION: 具体问题]:该选择显著影响特性范围或用户体验;存在多种合理诠释且影响不同;不存在合理默认值;
    • 上限 3 个 [NEEDS CLARIFICATION] 标记;
    • 按影响力排序:范围 > 安全/隐私 > 用户体验 > 技术细节。
  4. 填写 User Scenarios & Testing 章节:若无法确定任何用户流,报错 Cannot determine user scenarios
  5. 生成功能需求:每条需求必须可测试;未指明的细节使用合理默认值,并把假设记录到 Assumptions 章节。
  6. 定义成功标准:可度量、技术无关(technology-agnostic),同时包含定量指标(时间、性能、容量)与定性度量(用户满意度、任务完成率),且每条标准不依赖实现细节即可验证。
  7. 识别关键实体(如果涉及数据)。
  8. 返回 SUCCESS:规格已准备好进入 plan 阶段。

五、规格书结构:spec-template 的强制章节

specify 写出的规格书基于 spec-template.md,其骨架如下(必须保持章节顺序与标题):

  • 头部元信息:Feature Branch([###-feature-name])、Created 日期、Status(Draft)、Input(用户原始描述);
  • User Scenarios & Testing(mandatory):用户故事按优先级 P1/P2/P3 排列,且每个故事必须可独立测试——单独实现其中任何一个都应得到可交付价值的 MVP。每个故事包含:优先级理由(Why this priority)、独立测试方式(Independent Test)、验收场景(Given/When/Then 三段式);末尾是 Edge Cases(边界条件与错误场景);
  • Requirements(mandatory):功能需求以 FR-001FR-002……编号,措辞为 "System MUST …";模板同时示范了如何用 [NEEDS CLARIFICATION: …] 标注未定的需求(如认证方式、数据保留期);若特性涉及数据,还需 Key Entities 小节,描述实体及其关系但不涉及实现;
  • Success Criteria(mandatory):以 SC-001 起编号的可度量结果,例如 “Users can complete account creation in under 2 minutes”;
  • Assumptions:记录描述未指明时所选的合理默认(目标用户、范围边界、数据/环境、对既有系统的依赖)。

六、质量验证闭环:checklist + 三轮迭代

写规格只是起点,specify 模板的核心竞争力在于其内建的验证闭环:

  1. 生成质量清单:在 SPECIFY_FEATURE_DIRECTORY/checklists/requirements.md 生成清单文件,结构固定为三组:
    • Content Quality:无实现细节(语言、框架、API)、聚焦用户价值与业务需求、面向非技术干系人、所有强制章节已填写;
    • Requirement Completeness:无残留 [NEEDS CLARIFICATION]、需求可测试且无歧义、成功标准可度量且技术无关、验收场景与边界情况已定义、范围有界、依赖与假设已识别;
    • Feature Readiness:每条功能需求有清晰验收标准、用户场景覆盖主流程、特性满足成功标准、无实现细节泄漏。
    • 清单末尾注明:未完成项在进入 clarifyplan 之前必须更新规格。
  2. 逐项验证:对每个清单项判定 pass/fail,并记录具体发现的问题(引用相关规格段落)。
  3. 处理验证结果
    • 全部通过 → 标记清单完成,进入后置钩子阶段;
    • 存在失败项(不含 [NEEDS CLARIFICATION])→ 列出失败项、更新规格、重跑验证(最多 3 轮迭代),3 轮后仍失败则把遗留问题写入清单备注并警告用户;
    • 仍有 [NEEDS CLARIFICATION] 标记 → 进入澄清问答流程(见下节)。
  4. 每轮迭代后更新清单文件中的当前 pass/fail 状态。

注意与自定义清单的区别:checklist-template.md 中的注释明确说明,checklists/requirements.md 拥有由 specifyclarify 维护的独立内建生命周期,而 checklist 命令生成的清单是审阅者拥有的需求质量评审产物,implement 命令会读取其勾选状态作为门禁且不得修改标记。二者不要混淆。

6.1 澄清问答:最多 3 问、批量呈现

当规格中残留 [NEEDS CLARIFICATION] 标记时,命令要求:

  • LIMIT CHECK:若标记超过 3 个,只保留最关键的 3 个(按范围/安全/UX 影响排序),其余做有依据的推测;
  • 对每个问题(最多 3 个,编号 Q1、Q2、Q3),按统一格式呈现,包含 Context(引用相关规格段落)、What we need to know(具体问题)与一张 Suggested Answers 表格——A/B/C 三个建议答案加各自的 Implications,外加一行 Custom 供用户提供自定义答案;
  • 模板对 Markdown 表格格式有硬性要求:竖线对齐、单元格内容两侧留空格(| Content | 而非 |Content|)、表头分隔符至少 3 个连字符,并在预览中确认可正常渲染;
  • 所有问题一次性批量呈现后等待用户统一回复(如 Q1: A, Q2: Custom - [details], Q3: B);
  • 用用户的选择替换对应标记,然后重跑验证

七、后置钩子与完成报告

7.1 after_specify 后置钩子

模板把“Mandatory Post-Execution Hooks”标为完成前必须执行的章节:检查 .specify/extensions.yml 中的 hooks.after_specify。规则与前置钩子对称——YAML 无效则静默跳过、过滤 enabled: false、不评估非空 condition;区别在于输出措辞:强制钩子标注 “Automatic Hook” 且必须发出 EXECUTE_COMMAND: 并真实调用等待结束,可选钩子标注 “Optional Hook” 并给出手动执行提示。

7.2 Completion Report

向用户报告的内容包括:SPECIFY_FEATURE_DIRECTORY(特性目录路径)、SPEC_FILE(规格文件路径)、清单结果摘要、以及是否具备进入下一阶段(clarifyplan)的就绪度。模板最后注明:分支创建由 before_specify 钩子(git 扩展)负责,规格目录与文件的创建永远由核心命令负责。

八、写作守则:只写 WHAT 与 WHY

模板的 “Quick Guidelines” 与 “For AI Generation” 两节共同定义了规格书的写作标准,这也是 SDD 方法论的精髓:

  • 聚焦用户需要什么(WHAT)和为什么(WHY),避免如何实现(HOW)——不写技术栈、API、代码结构;
  • 面向业务干系人而非开发者;
  • 不要在规格内嵌清单(清单是独立命令/独立文件的事);
  • 强制章节必须填满,可选章节仅在相关时保留,不适用的章节整体删除而不是留 "N/A"

AI 生成时的具体守则:做有依据的推测并把默认值记入 Assumptions;澄清问题只留给“显著影响范围或体验、存在多种合理解释、且无合理默认”的关键决策。模板还给出了不该提问的合理默认示例:数据保留期按行业标准、性能目标按常规 Web/移动应用预期、错误处理用友好提示与兜底、Web 应用默认会话或 OAuth2 认证、集成模式按项目形态选择(Web 服务用 REST/GraphQL、库用函数调用、工具用 CLI 参数)。

成功标准必须满足四条:可度量(含具体时间、百分比、数量、比率)、技术无关(不出现框架/语言/数据库/工具)、用户视角(从业务结果而非系统内部描述)、可验证(无需了解实现即可测试)。模板给的对照示例很直观——

  • 好:“Users can complete checkout in under 3 minutes”“95% of searches return results in under 1 second”;
  • 坏:“API response time is under 200ms”(太技术,应改为面向用户的表述)、“Database can handle 1000 TPS”(实现细节)、“React components render efficiently”(框架特定)、“Redis cache hit rate above 80%”(技术特定)。

九、Done When:完成判据

模板以三个可核对的完成项收尾,也可作为自动化验收 specify 执行的检查表:

  • 规格已写入 SPEC_FILE 并通过质量清单验证;
  • 扩展钩子已按 “Mandatory Post-Execution Hooks” 规则分发或跳过;
  • 已向用户报告特性目录、规格文件路径与清单结果。

十、小结与实操要点

回到 templates/commands/specify.md 这份模板本身,可以把它概括为一条“受控流水线”:输入守卫(空描述即报错)→ 外部协作(before/after 钩子协议,条件求值外包给 HookExecutor)→ 命名与落位(短名称、specs/NNN-xxx 或时间戳目录、feature.json 持久化)→ 内容生成(按 spec-template.md 的强制章节)→ 质量闭环checklists/requirements.md + 最多 3 轮迭代 + 最多 3 问的批量澄清)。

实操中有四个配置点值得逐一确认:

  1. .specify/init-options.jsonfeature_numbering 决定目录前缀是三位序号还是时间戳,弃用的 branch_numbering 会触发警告;
  2. .specify/extensions.ymlhooks.before_specify / hooks.after_specify 决定分支创建等自动化是否介入;
  3. git 扩展的 branch_template(见 speckit.git.feature.md)控制分支名形态,monorepo 场景可用 {author}/{app}/{number}-{slug} 这类模板;
  4. 规格目录名与分支名相互独立——排查“找不到特性目录”问题时,优先看 .specify/feature.json 而非分支名。

掌握这条链路后,你就能在任意 AI 编码工具中稳定地跑通 Spec Kit 的第一步:一句话功能描述进去,一份经过自我验证、可交给 clarify/plan 的结构化 spec.md 出来。

登录后查看全文
热门项目推荐
相关项目推荐