hookehuyr

feat: 添加Specify框架模板与脚本

添加Specify框架的核心模板文件,包括:
- 功能规格说明模板(spec-template.md)
- 实现计划模板(plan-template.md)
- 任务清单模板(tasks-template.md)
- 检查清单模板(checklist-template.md)
- 代理文件模板(agent-file-template.md)

添加支持脚本:
- 创建新功能的create-new-feature.sh
- 检查前置条件的check-prerequisites.sh
- 设置计划的setup-plan.sh
- 通用函数库common.sh

添加Cursor命令文件:
- speckit.specify
- speckit.plan
- speckit.tasks
- speckit.checklist
- speckit.clarify
- speckit.implement
- speckit.analyze
- speckit.constitution
- speckit.taskstoissues

更新项目宪法文件(constitution.md),增加治理与管理章节
1 +---
2 +description: 在生成 tasks.md 之后,对 spec.md、plan.md、tasks.md 做一次非破坏性的跨文件一致性与质量分析。
3 +---
4 +
5 +## 用户输入
6 +
7 +```text
8 +$ARGUMENTS
9 +```
10 +
11 +在继续之前,你**必须**先考虑用户输入(如果不为空)。
12 +
13 +## 目标
14 +
15 +在开始实现之前,识别三份核心产物(`spec.md``plan.md``tasks.md`)之间的不一致、重复、歧义和说明不足之处。本命令**必须**`/speckit.tasks` 成功生成完整的 `tasks.md` 之后才运行。
16 +
17 +## 运行约束
18 +
19 +**严格只读****不要**修改任何文件。输出结构化的分析报告。可以提供可选的修复方案(用户必须明确同意后,才可以人工触发后续的编辑命令)。
20 +
21 +**宪法优先级**:在本分析范围内,项目宪法(`.specify/memory/constitution.md`**不可协商**。任何与宪法冲突的问题都自动视为 CRITICAL,并要求调整 spec/plan/tasks,而不是淡化、重新解释或悄悄忽略原则。如果确实需要修改原则本身,必须在 `/speckit.analyze` 之外,通过单独、明确的宪法更新来完成。
22 +
23 +## 执行步骤
24 +
25 +### 1. 初始化分析上下文
26 +
27 +在仓库根目录只运行一次 `.specify/scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks`,并解析 JSON 中的 FEATURE_DIR 和 AVAILABLE_DOCS。推导出绝对路径:
28 +
29 +- SPEC = FEATURE_DIR/spec.md
30 +- PLAN = FEATURE_DIR/plan.md
31 +- TASKS = FEATURE_DIR/tasks.md
32 +
33 +如果缺少任何必需文件,直接报错并提示用户运行缺失的前置命令。
34 +当参数里包含单引号(例如 "I'm Groot")时,使用转义写法:如 'I'\''m Groot'(或尽量用双引号:"I'm Groot")。
35 +
36 +### 2. 加载产物(渐进式披露)
37 +
38 +每个产物只加载最少且必要的上下文:
39 +
40 +**来自 spec.md:**
41 +
42 +- 概览/背景
43 +- 功能需求
44 +- 非功能需求
45 +- 用户故事
46 +- 边界情况(如存在)
47 +
48 +**来自 plan.md:**
49 +
50 +- 架构/技术栈选择
51 +- 数据模型引用
52 +- 阶段划分
53 +- 技术约束
54 +
55 +**来自 tasks.md:**
56 +
57 +- 任务 ID
58 +- 任务描述
59 +- 阶段分组
60 +- 并行标记 [P]
61 +- 引用到的文件路径
62 +
63 +**来自宪法:**
64 +
65 +- 加载 `.specify/memory/constitution.md` 用于原则校验
66 +
67 +### 3. 构建语义模型
68 +
69 +创建内部表示(输出中不要包含原始产物全文):
70 +
71 +- **需求清单**:每条功能/非功能需求都要有稳定的 key(根据祈使句短语生成 slug;例如 “用户可以上传文件” → `user-can-upload-file`
72 +- **用户故事/动作清单**:离散的用户动作及其验收标准
73 +- **任务覆盖映射**:将每个任务映射到一个或多个需求/故事(通过关键字推断或显式引用模式,比如 ID、关键短语)
74 +- **宪法规则集**:提取原则名称以及 MUST/SHOULD 等规范性语句
75 +
76 +### 4. 检测遍历(Token 高效分析)
77 +
78 +聚焦高信号问题。总计最多输出 50 条发现;其余聚合到溢出摘要中。
79 +
80 +#### A. 重复检测
81 +
82 +- 识别近似重复的需求
83 +- 标记表达质量较低的需求,建议合并收敛表述
84 +
85 +#### B. 歧义检测
86 +
87 +- 标记缺少可度量标准的模糊形容词(fast、scalable、secure、intuitive、robust 等)
88 +- 标记未解决的占位符(TODO、TKTK、???、`<placeholder>` 等)
89 +
90 +#### C. 说明不足
91 +
92 +- 有动词但缺少对象或可度量结果的需求
93 +- 用户故事缺少与验收标准对齐的说明
94 +- 任务引用了 spec/plan 中未定义的文件或组件
95 +
96 +#### D. 宪法对齐
97 +
98 +- 任意与宪法 MUST 原则冲突的需求或计划要素
99 +- 缺失宪法要求的必填章节或质量门禁
100 +
101 +#### E. 覆盖缺口
102 +
103 +- 没有关联任务的需求
104 +- 未映射到任何需求/故事的任务
105 +- 未在任务中体现的非功能需求(例如性能、安全)
106 +
107 +#### F. 不一致
108 +
109 +- 术语漂移(同一概念在不同文件中用不同名称)
110 +- plan 引用的数据实体在 spec 中缺失(或反之)
111 +- 任务顺序自相矛盾(例如未注明依赖却在基础初始化之前安排集成任务)
112 +- 需求相互冲突(例如一处要求 Next.js,另一处指定 Vue)
113 +
114 +### 5. 严重级别判定
115 +
116 +使用以下启发式规则为发现排序:
117 +
118 +- **CRITICAL**: 违反宪法 MUST、缺失核心产物,或关键需求零覆盖导致基线功能无法实现
119 +- **HIGH**: 重复或冲突的需求、含糊的安全/性能属性、不可测试的验收标准
120 +- **MEDIUM**: 术语漂移、缺少非功能需求的任务覆盖、边界情况说明不足
121 +- **LOW**: 风格/措辞改进、不影响执行顺序的轻微冗余
122 +
123 +### 6. 产出精简分析报告
124 +
125 +按以下结构输出 Markdown 报告(不写文件):
126 +
127 +## 规格说明分析报告
128 +
129 +| ID | 类别 | 严重级别 | 位置 | 摘要 | 建议 |
130 +|----|----------|----------|-------------|---------|----------------|
131 +| A1 | 重复 | HIGH | spec.md:L120-134 | 两条相似需求…… | 合并表述;保留更清晰的版本 |
132 +
133 +(每条发现一行;生成稳定 ID,并以类别首字母作为前缀。)
134 +
135 +**覆盖摘要表:**
136 +
137 +| 需求 Key | 是否有任务 | 任务 ID | 备注 |
138 +|-----------------|-----------|----------|-------|
139 +
140 +**宪法对齐问题:**(如有)
141 +
142 +**未映射任务:**(如有)
143 +
144 +**指标:**
145 +
146 +- 需求总数
147 +- 任务总数
148 +- 覆盖率(至少关联 1 个任务的需求占比)
149 +- 歧义数量
150 +- 重复数量
151 +- 严重问题数量
152 +
153 +### 7. 给出下一步动作
154 +
155 +在报告末尾输出精炼的“下一步动作”区块:
156 +
157 +- 若存在 CRITICAL:建议在进入 `/speckit.implement` 之前先解决
158 +- 若只有 LOW/MEDIUM:可继续推进,但应给出改进建议
159 +- 给出明确命令建议:例如“用更精炼描述重新运行 /speckit.specify”“运行 /speckit.plan 调整架构”“手动编辑 tasks.md 为 ‘performance-metrics’ 补齐覆盖”
160 +
161 +### 8. 提供修复建议
162 +
163 +询问用户:“你希望我为前 N 个问题给出具体的修复编辑建议吗?”(不要自动应用。)
164 +
165 +## 运行原则
166 +
167 +### 上下文效率
168 +
169 +- **最小高信号 token**:聚焦可执行发现,不做穷举式文档复述
170 +- **渐进式披露**:逐步加载产物,不把全文倾倒进分析
171 +- **token 高效输出**:发现表最多 50 行,其余做溢出摘要
172 +- **确定性结果**:在无变更前提下重复运行应得到一致的 ID 与统计
173 +
174 +### 分析准则
175 +
176 +- **禁止修改文件**(严格只读分析)
177 +- **禁止臆造缺失章节**(缺失就如实报告)
178 +- **优先处理宪法违规则**(一律 CRITICAL)
179 +- **用例子胜过穷举规则**(引用具体实例而不是泛泛而谈)
180 +- **零问题也要输出报告**(给出覆盖统计并明确通过)
181 +
182 +## 上下文
183 +
184 +$ARGUMENTS
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 +---
2 +description: 通过交互式或提供的原则输入创建/更新项目宪法,并确保所有依赖模板保持同步。
3 +handoffs:
4 + - label: 生成规格说明
5 + agent: speckit.specify
6 + prompt: 基于更新后的宪法生成功能规格说明。我想要构建……
7 +---
8 +
9 +## 用户输入
10 +
11 +```text
12 +$ARGUMENTS
13 +```
14 +
15 +在继续之前,你**必须**先考虑用户输入(如果不为空)。
16 +
17 +## 概述
18 +
19 +你正在更新 `.specify/memory/constitution.md` 中的项目宪法。该文件是一个模板(Template),包含方括号占位符(例如 `[PROJECT_NAME]``[PRINCIPLE_1_NAME]`)。你的工作是:(a)收集/推导具体值,(b)精准填充模板,(c)将所有修订同步传播到依赖产物中。
20 +
21 +按以下流程执行:
22 +
23 +1. 加载 `.specify/memory/constitution.md` 中现有的宪法模板。
24 + - 识别所有形如 `[ALL_CAPS_IDENTIFIER]` 的占位符 token。
25 + **重要**:用户需要的原则数量可能少于或多于模板默认数量。如果用户指定了数量,必须尊重该数量,并在通用模板结构下调整文档内容。
26 +
27 +2. 收集/推导占位符的具体值:
28 + - 若用户输入(对话中)已提供取值,直接使用。
29 + - 否则从仓库上下文推断(README、文档、若存在则参考仓库内嵌的旧宪法内容)。
30 + - 治理日期规则:`RATIFICATION_DATE` 为原始生效日期(未知则询问或标记 TODO);`LAST_AMENDED_DATE` 若本次有修改则为今天,否则保留原值。
31 + - `CONSTITUTION_VERSION` 必须按语义化版本规则递增:
32 + - MAJOR:不向后兼容的治理/原则移除或重定义。
33 + - MINOR:新增原则/章节,或对既有指导做实质性扩展。
34 + - PATCH:澄清、措辞、错别字修正、非语义性的精炼。
35 + - 若版本升级类型不明确,在最终落盘前先给出判断理由。
36 +
37 +3. 起草更新后的宪法内容:
38 + - 用具体文本替换每个占位符(不应残留方括号 token;除非项目明确决定暂不定义,并对每个保留项给出理由)。
39 + - 保持标题层级不变;占位符被替换后,注释可移除,除非该注释仍对理解有帮助。
40 + - 确保每条原则包含:简短名称行、概括不可协商规则的段落(或要点列表),若理由不明显则补充明确的理由说明。
41 + - 确保治理(Governance)章节包含:修订流程、版本策略、合规审查期望。
42 +
43 +4. 一致性传播清单(把旧清单转为可执行校验项):
44 + - 阅读 `.specify/templates/plan-template.md`,确保其中的“宪法检查”或规则与更新后的原则一致。
45 + - 阅读 `.specify/templates/spec-template.md`,校验范围/需求对齐;若宪法新增/移除必填章节或约束,则同步更新模板。
46 + - 阅读 `.specify/templates/tasks-template.md`,确保任务分类能体现新增/移除的原则驱动任务类型(例如可观测性、版本策略、测试纪律)。
47 + - 阅读 `.specify/templates/commands/*.md` 下的每个命令文件(包含本文件),确保通用指导中不残留过时的 agent 特定引用(例如仅写 CLAUDE)。
48 + - 阅读运行/使用指导文档(例如 `README.md``docs/quickstart.md`,或存在的 agent 专属指导文件),同步更新与宪法变更相关的引用。
49 +
50 +5. 生成“同步影响报告”(更新后,作为 HTML 注释插入到宪法文件顶部):
51 + - 版本变更:旧版本 → 新版本
52 + - 修改过的原则列表(若重命名则写 旧标题 → 新标题)
53 + - 新增章节
54 + - 移除章节
55 + - 需要更新的模板列表(✅ 已更新 / ⚠ 待处理),并附文件路径
56 + - 若有占位符被刻意延期,列出后续 TODO
57 +
58 +6. 最终输出前校验:
59 + - 不残留任何无法解释的方括号占位符 token。
60 + - 版本行与同步影响报告一致。
61 + - 日期使用 ISO 格式 YYYY-MM-DD。
62 + - 原则陈述应可验证、可测试,避免含糊措辞(必要时将“should”替换为 MUST/SHOULD,并给出理由)。
63 +
64 +7. 将完成的宪法内容写回 `.specify/memory/constitution.md`(覆盖写入)。
65 +
66 +8. 输出给用户的最终总结应包含:
67 + - 新版本号与升级理由。
68 + - 需要人工跟进的文件(如有)。
69 + - 建议的提交信息(例如 `docs: amend constitution to vX.Y.Z (principle additions + governance update)`)。
70 +
71 +格式与样式要求:
72 +
73 +- 标题层级必须与模板完全一致(不要升/降级标题)。
74 +- 适度换行以保持可读性(理想情况下 <100 字符),但不要为了硬性限制造成生硬断行。
75 +- 章节之间保持一个空行。
76 +- 避免行尾空格。
77 +
78 +如果用户只提供部分更新(例如只修改一条原则),也要照样执行校验与版本决策步骤。
79 +
80 +如果缺少关键信息(例如确实不知道 ratification date),插入 `TODO(<FIELD_NAME>): explanation`,并在同步影响报告的延期项(deferred)中列出。
81 +
82 +不要创建新的模板;始终在现有的 `.specify/memory/constitution.md` 文件上操作。
1 +---
2 +description: 通过处理并执行 tasks.md 中定义的所有任务,落实实现计划
3 +---
4 +
5 +## 用户输入
6 +
7 +```text
8 +$ARGUMENTS
9 +```
10 +
11 +在继续之前,你**必须**先考虑用户输入(如果不为空)。
12 +
13 +## 概述
14 +
15 +1. 在仓库根目录运行一次 `.specify/scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks`,并解析 JSON 中的 FEATURE_DIR 与 AVAILABLE_DOCS 列表。所有路径必须是绝对路径。当参数里包含单引号(例如 "I'm Groot")时,使用转义写法:如 'I'\''m Groot'(或尽量用双引号:"I'm Groot")。
16 +
17 +2. **检查检查清单状态**(如果存在 FEATURE_DIR/checklists/):
18 + - 扫描 checklists/ 目录下的所有清单文件
19 + - 对每个清单统计:
20 + - 总条目:匹配 `- [ ]``- [X]``- [x]` 的所有行
21 + - 已完成条目:匹配 `- [X]``- [x]` 的行
22 + - 未完成条目:匹配 `- [ ]` 的行
23 + - 生成状态表:
24 +
25 + ```text
26 + | Checklist | Total | Completed | Incomplete | Status |
27 + |-----------|-------|-----------|------------|--------|
28 + | ux.md | 12 | 12 | 0 | ✓ PASS |
29 + | test.md | 8 | 5 | 3 | ✗ FAIL |
30 + | security.md | 6 | 6 | 0 | ✓ PASS |
31 + ```
32 +
33 + - 计算总体状态:
34 + - **PASS**:所有清单的未完成条目为 0
35 + - **FAIL**:存在至少一个清单有未完成条目
36 +
37 + - **如果存在未完成清单**
38 + - 展示状态表与未完成数量
39 + - **停止**并询问:“有些检查清单尚未完成。是否仍要继续实现?(yes/no)”
40 + - 等待用户回复后再继续
41 + - 若用户回复 “no”“wait” 或 “stop”,则终止执行
42 + - 若用户回复 “yes”“proceed” 或 “continue”,则进入第 3 步
43 +
44 + - **如果所有清单都已完成**
45 + - 展示所有清单通过的状态表
46 + - 自动进入第 3 步
47 +
48 +3. 加载并分析实现上下文:
49 + - **必须**:读取 tasks.md 获取完整任务列表与执行计划
50 + - **必须**:读取 plan.md 获取技术栈、架构与文件结构
51 + - **如果存在**:读取 data-model.md 获取实体与关系
52 + - **如果存在**:读取 contracts/ 获取 API 规范与测试要求
53 + - **如果存在**:读取 research.md 获取技术决策与约束
54 + - **如果存在**:读取 quickstart.md 获取集成场景
55 +
56 +4. **项目初始化校验**
57 + - **必须**:基于实际项目情况创建/校验 ignore 文件:
58 +
59 + **检测与创建逻辑**
60 + - 通过下列命令是否成功来判断仓库是否是 git 仓库(如果是,则创建/校验 .gitignore):
61 +
62 + ```sh
63 + git rev-parse --git-dir 2>/dev/null
64 + ```
65 +
66 + - 检查是否存在 Dockerfile* 或 plan.md 中提到 Docker → 创建/校验 .dockerignore
67 + - 检查是否存在 .eslintrc* → 创建/校验 .eslintignore
68 + - 检查是否存在 eslint.config.* → 确保配置中的 `ignores` 覆盖所需模式
69 + - 检查是否存在 .prettierrc* → 创建/校验 .prettierignore
70 + - 检查是否存在 .npmrc 或 package.json →(若要发布)创建/校验 .npmignore
71 + - 检查是否存在 terraform 文件(*.tf)→ 创建/校验 .terraformignore
72 + - 检查是否需要 .helmignore(存在 helm charts)→ 创建/校验 .helmignore
73 +
74 + **如果 ignore 文件已存在**:校验其包含关键模式,只追加缺失且重要的模式
75 + **如果 ignore 文件不存在**:按检测到的技术栈创建包含完整模式集合的文件
76 +
77 + **按技术栈的常见模式**(来自 plan.md 的技术栈):
78 + - **Node.js/JavaScript/TypeScript**: `node_modules/`, `dist/`, `build/`, `*.log`, `.env*`
79 + - **Python**: `__pycache__/`, `*.pyc`, `.venv/`, `venv/`, `dist/`, `*.egg-info/`
80 + - **Java**: `target/`, `*.class`, `*.jar`, `.gradle/`, `build/`
81 + - **C#/.NET**: `bin/`, `obj/`, `*.user`, `*.suo`, `packages/`
82 + - **Go**: `*.exe`, `*.test`, `vendor/`, `*.out`
83 + - **Ruby**: `.bundle/`, `log/`, `tmp/`, `*.gem`, `vendor/bundle/`
84 + - **PHP**: `vendor/`, `*.log`, `*.cache`, `*.env`
85 + - **Rust**: `target/`, `debug/`, `release/`, `*.rs.bk`, `*.rlib`, `*.prof*`, `.idea/`, `*.log`, `.env*`
86 + - **Kotlin**: `build/`, `out/`, `.gradle/`, `.idea/`, `*.class`, `*.jar`, `*.iml`, `*.log`, `.env*`
87 + - **C++**: `build/`, `bin/`, `obj/`, `out/`, `*.o`, `*.so`, `*.a`, `*.exe`, `*.dll`, `.idea/`, `*.log`, `.env*`
88 + - **C**: `build/`, `bin/`, `obj/`, `out/`, `*.o`, `*.a`, `*.so`, `*.exe`, `Makefile`, `config.log`, `.idea/`, `*.log`, `.env*`
89 + - **Swift**: `.build/`, `DerivedData/`, `*.swiftpm/`, `Packages/`
90 + - **R**: `.Rproj.user/`, `.Rhistory`, `.RData`, `.Ruserdata`, `*.Rproj`, `packrat/`, `renv/`
91 + - **Universal**: `.DS_Store`, `Thumbs.db`, `*.tmp`, `*.swp`, `.vscode/`, `.idea/`
92 +
93 + **工具特定模式**
94 + - **Docker**: `node_modules/`, `.git/`, `Dockerfile*`, `.dockerignore`, `*.log*`, `.env*`, `coverage/`
95 + - **ESLint**: `node_modules/`, `dist/`, `build/`, `coverage/`, `*.min.js`
96 + - **Prettier**: `node_modules/`, `dist/`, `build/`, `coverage/`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`
97 + - **Terraform**: `.terraform/`, `*.tfstate*`, `*.tfvars`, `.terraform.lock.hcl`
98 + - **Kubernetes/k8s**: `*.secret.yaml`, `secrets/`, `.kube/`, `kubeconfig*`, `*.key`, `*.crt`
99 +
100 +5. 解析 tasks.md 结构并提取:
101 + - **任务阶段**:初始化、测试、核心、集成、打磨
102 + - **任务依赖**:串行与并行的执行规则
103 + - **任务细节**:ID、描述、文件路径、并行标记 [P]
104 + - **执行流程**:顺序与依赖要求
105 +
106 +6. 按任务计划执行实现:
107 + - **按阶段执行**:完成当前阶段后再进入下一阶段
108 + - **遵守依赖**:串行任务按顺序执行;并行任务 [P] 可同时执行
109 + - **遵循 TDD**:若存在测试任务,先执行测试任务再执行对应实现任务
110 + - **按文件协调**:影响同一文件的任务必须串行执行
111 + - **阶段校验点**:进入下一阶段前先校验当前阶段是否完成
112 +
113 +7. 实现执行规则:
114 + - **先做初始化**:初始化项目结构、依赖、配置
115 + - **先写测试再写代码**:如果需要为契约、实体与集成场景编写测试
116 + - **核心开发**:实现模型、服务、CLI 命令、端点
117 + - **集成工作**:数据库连接、中间件、日志、外部服务
118 + - **打磨与校验**:单元测试、性能优化、文档
119 +
120 +8. 进度跟踪与错误处理:
121 + - 每完成一个任务都汇报进度
122 + - 任意非并行任务失败时立即停止执行
123 + - 并行任务 [P] 允许继续已成功任务,并汇报失败项
124 + - 提供带上下文的清晰错误信息,便于定位
125 + - 若实现无法继续,给出明确的下一步建议
126 + - **重要**:任务完成后,务必在 tasks 文件中用 [X] 勾掉该任务
127 +
128 +9. 完成校验:
129 + - 确认所有必需任务都已完成
130 + - 检查实现的功能是否与原始 spec 一致
131 + - 校验测试通过且覆盖率满足要求
132 + - 确认实现遵循技术计划
133 + - 汇报最终状态并总结已完成工作
134 +
135 +注意:本命令假设 tasks.md 中已存在完整的任务拆分。如果任务不完整或缺失,应建议先运行 `/speckit.tasks` 重新生成任务列表。
1 +---
2 +description: 使用计划模板执行实现规划流程,并生成设计产物。
3 +handoffs:
4 + - label: 生成任务列表
5 + agent: speckit.tasks
6 + prompt: 将实现计划拆分为可执行任务
7 + send: true
8 + - label: 生成检查清单
9 + agent: speckit.checklist
10 + prompt: 为以下领域生成一份检查清单……
11 +---
12 +
13 +## 用户输入
14 +
15 +```text
16 +$ARGUMENTS
17 +```
18 +
19 +在继续之前,你**必须**先考虑用户输入(如果不为空)。
20 +
21 +## 概述
22 +
23 +1. **准备**:在仓库根目录运行 `.specify/scripts/bash/setup-plan.sh --json`,并解析 JSON 中的 FEATURE_SPEC、IMPL_PLAN、SPECS_DIR、BRANCH。当参数里包含单引号(例如 "I'm Groot")时,使用转义写法:如 'I'\''m Groot'(或尽量用双引号:"I'm Groot")。
24 +
25 +2. **加载上下文**:读取 FEATURE_SPEC 与 `.specify/memory/constitution.md`。加载 IMPL_PLAN 模板(已复制到目标位置)。
26 +
27 +3. **执行规划流程**:按 IMPL_PLAN 模板结构完成:
28 + - 填写技术上下文(未知项标记为 “NEEDS CLARIFICATION”)
29 + - 从宪法中填写“宪法检查”小节
30 + - 评估门禁(若存在未经合理解释的违规则 ERROR)
31 + - Phase 0:生成 research.md(解决所有 NEEDS CLARIFICATION)
32 + - Phase 1:生成 data-model.md、contracts/、quickstart.md
33 + - Phase 1:通过运行 agent 脚本更新 agent 上下文
34 + - 设计完成后重新评估“宪法检查”
35 +
36 +4. **停止并汇报**:命令在 Phase 2 规划后结束。汇报分支名、IMPL_PLAN 路径与生成的产物。
37 +
38 +## 阶段
39 +
40 +### Phase 0:大纲与调研
41 +
42 +1. **从上面的技术上下文中提取未知项**
43 + - 每个 NEEDS CLARIFICATION → 一条调研任务
44 + - 每个依赖 → 一条最佳实践任务
45 + - 每个集成点 → 一条模式/方案任务
46 +
47 +2. **生成并分发调研 agent**
48 +
49 + ```text
50 + 对于技术上下文中的每个未知项:
51 + 任务:"为 {feature context} 调研 {unknown}"
52 + 对于每个技术选型:
53 + 任务:"为 {domain} 场景寻找 {tech} 的最佳实践"
54 + ```
55 +
56 +3. **在 `research.md` 中汇总结论**,格式为:
57 + - 决策(Decision):[选择了什么]
58 + - 理由(Rationale):[为什么这样选]
59 + - 备选方案(Alternatives):[还评估了什么]
60 +
61 +**输出**:research.md,且所有 NEEDS CLARIFICATION 已解决
62 +
63 +### Phase 1:设计与契约
64 +
65 +**前置条件:** `research.md` 已完成
66 +
67 +1. **从功能 spec 中提取实体**`data-model.md`
68 + - 实体名称、字段、关系
69 + - 来自需求的校验规则
70 + - 若适用:状态流转
71 +
72 +2. **从功能需求生成 API 契约**
73 + - 每个用户动作 → 一个 endpoint
74 + - 使用标准 REST/GraphQL 模式
75 + - 输出 OpenAPI/GraphQL schema 到 `/contracts/`
76 +
77 +3. **更新 agent 上下文**
78 + - 运行 `.specify/scripts/bash/update-agent-context.sh cursor-agent`
79 + - 脚本会检测当前使用的是哪个 AI agent
80 + - 更新对应的 agent 专属上下文文件
81 + - 只追加本次计划中新引入的技术
82 + - 保留标记区间内的人工补充内容
83 +
84 +**输出**:data-model.md、/contracts/*、quickstart.md、agent 专属上下文文件
85 +
86 +## 关键规则
87 +
88 +- 使用绝对路径
89 +- 门禁失败或存在未解决澄清项时直接 ERROR
This diff is collapsed. Click to expand it.
1 +---
2 +description: 基于现有设计产物,为该功能生成可执行、按依赖排序的 tasks.md。
3 +handoffs:
4 + - label: 一致性分析
5 + agent: speckit.analyze
6 + prompt: 执行项目一致性分析
7 + send: true
8 + - label: 分阶段实现
9 + agent: speckit.implement
10 + prompt: 按阶段开始实现
11 + send: true
12 +---
13 +
14 +## 用户输入
15 +
16 +```text
17 +$ARGUMENTS
18 +```
19 +
20 +在继续之前,你**必须**先考虑用户输入(如果不为空)。
21 +
22 +## 概述
23 +
24 +1. **准备**:在仓库根目录运行 `.specify/scripts/bash/check-prerequisites.sh --json` 并解析 FEATURE_DIR 与 AVAILABLE_DOCS 列表。所有路径必须是绝对路径。当参数里包含单引号(例如 "I'm Groot")时,使用转义写法:如 'I'\''m Groot'(或尽量用双引号:"I'm Groot")。
25 +
26 +2. **加载设计文档**:从 FEATURE_DIR 读取:
27 + - **必需**:plan.md(技术栈、依赖库、结构)、spec.md(带优先级的用户故事)
28 + - **可选**:data-model.md(实体)、contracts/(API 端点)、research.md(决策)、quickstart.md(测试场景)
29 + - 注意:并非所有项目都有全部文档。应基于当前可用文档生成任务。
30 +
31 +3. **执行任务生成流程**
32 + - 加载 plan.md,提取技术栈、依赖库与项目结构
33 + - 加载 spec.md,提取带优先级的用户故事(P1、P2、P3 等)
34 + - 如果存在 data-model.md:提取实体并映射到用户故事
35 + - 如果存在 contracts/:将端点映射到用户故事
36 + - 如果存在 research.md:提取决策用于初始化相关任务
37 + - 按用户故事组织生成任务(见下方“任务生成规则”)
38 + - 生成依赖图,展示用户故事的完成顺序
39 + - 为每个用户故事提供并行执行示例
40 + - 校验任务完整性(每个用户故事包含所需任务,且可独立测试)
41 +
42 +4. **生成 tasks.md**:以 `.specify/templates/tasks-template.md` 为结构,填充:
43 + - 从 plan.md 读取正确的功能名称
44 + - Phase 1:初始化任务(项目初始化)
45 + - Phase 2:基础任务(所有用户故事的阻塞前置)
46 + - Phase 3+:按 spec.md 的优先级为每个用户故事建一个阶段
47 + - 每个阶段包含:故事目标、独立测试标准、测试(如有要求)、实现任务
48 + - 最终阶段:打磨与横切关注点
49 + - 所有任务必须遵循严格的清单格式(见下方“任务生成规则”)
50 + - 每个任务都要写清楚文件路径
51 + - Dependencies 章节展示故事完成顺序
52 + - 每个故事提供并行执行示例
53 + - Implementation strategy 章节说明实现策略(先 MVP,逐步交付)
54 +
55 +5. **报告(Report)**:输出生成的 tasks.md 路径与摘要:
56 + - 任务总数
57 + - 每个用户故事的任务数
58 + - 识别到的并行机会
59 + - 每个故事的独立测试标准
60 + - 建议的 MVP 范围(通常只包含用户故事 1)
61 + - 格式校验:确认所有任务都遵循清单格式(checkbox、ID、标签、文件路径)
62 +
63 +用于任务生成的上下文:$ARGUMENTS
64 +
65 +tasks.md 应当可以直接执行——每个任务都必须足够具体,使得 LLM 在不依赖额外上下文的情况下也能完成。
66 +
67 +## 任务生成规则
68 +
69 +**关键(CRITICAL)**:任务必须按用户故事组织,以支持独立实现与独立测试。
70 +
71 +**测试是可选项**:只有在 spec 明确要求,或用户要求 TDD 时才生成测试任务。
72 +
73 +### 清单格式(必须)
74 +
75 +每个任务都必须严格遵循以下格式:
76 +
77 +```text
78 +- [ ] [TaskID] [P?] [Story?] 包含文件路径的任务描述
79 +```
80 +
81 +**格式组成**
82 +
83 +1. **勾选框(Checkbox)**:必须以 `- [ ]` 开头(Markdown checkbox)
84 +2. **任务 ID(Task ID)**:按执行顺序递增编号(T001、T002、T003...)
85 +3. **[P] 标记**:仅当任务可并行时才包含(不同文件,且不依赖未完成任务)
86 +4. **[Story] 标签**:仅用于“用户故事阶段”的任务,且必须包含
87 + - 格式:[US1][US2][US3] 等(映射 spec.md 的用户故事)
88 + - 初始化阶段:不加 story 标签
89 + - 基础阶段:不加 story 标签
90 + - 用户故事阶段:必须有 story 标签
91 + - 打磨阶段:不加 story 标签
92 +5. **描述(Description)**:清晰描述动作,并包含准确文件路径
93 +
94 +**示例**
95 +
96 +- ✅ 正确:`- [ ] T001 按实现计划创建项目结构`
97 +- ✅ 正确:`- [ ] T005 [P] 在 src/middleware/auth.py 实现认证中间件`
98 +- ✅ 正确:`- [ ] T012 [P] [US1] 在 src/models/user.py 创建 User 模型`
99 +- ✅ 正确:`- [ ] T014 [US1] 在 src/services/user_service.py 实现 UserService`
100 +- ❌ 错误:`- [ ] 创建用户模型`(缺少 ID 与 Story 标签)
101 +- ❌ 错误:`T001 [US1] 创建模型`(缺少 checkbox)
102 +- ❌ 错误:`- [ ] [US1] 创建用户模型`(缺少 Task ID)
103 +- ❌ 错误:`- [ ] T001 [US1] 创建模型`(缺少文件路径)
104 +
105 +### 任务组织方式
106 +
107 +1. **来自用户故事(spec.md)——主要组织方式**
108 + - 每个用户故事(P1、P2、P3...)对应一个阶段
109 + - 将所有相关组件映射到对应的故事:
110 + - 该故事需要的模型
111 + - 该故事需要的服务
112 + - 该故事需要的端点/UI
113 + - 若需要测试:该故事专属的测试任务
114 + - 标记故事依赖(大多数故事应尽量独立)
115 +
116 +2. **来自 contracts**
117 + - 将每个 contract/endpoint 映射到它服务的用户故事
118 + - 若需要测试:每个 contract 在该故事阶段中,先生成 contract 测试任务 [P],再实现
119 +
120 +3. **来自数据模型**
121 + - 将每个实体映射到需要它的用户故事
122 + - 若实体服务多个故事:放入最早的故事阶段或初始化阶段
123 + - 关系处理 → 放到对应故事阶段的服务层任务中
124 +
125 +4. **来自初始化/基础设施**
126 + - 共享基础设施 → 初始化阶段(Phase 1)
127 + - 基础/阻塞任务 → 基础阶段(Phase 2)
128 + - 故事特定的初始化 → 放到该故事阶段内
129 +
130 +### 阶段结构
131 +
132 +- **Phase 1**:初始化(项目初始化)
133 +- **Phase 2**:基础(阻塞前置;必须在用户故事之前完成)
134 +- **Phase 3+**:按优先级顺序的用户故事(P1、P2、P3...)
135 + - 每个故事内:测试(如需)→ 模型 → 服务 → 端点 → 集成
136 + - 每个阶段都应是一个完整且可独立测试的增量
137 +- **最终阶段**:打磨与横切关注点
1 +---
2 +description: 基于现有设计产物,将已有任务转换为可执行、按依赖排序的 GitHub issue。
3 +tools: ['github/github-mcp-server/issue_write']
4 +---
5 +
6 +## 用户输入
7 +
8 +```text
9 +$ARGUMENTS
10 +```
11 +
12 +在继续之前,你**必须**先考虑用户输入(如果不为空)。
13 +
14 +## 概述
15 +
16 +1. 在仓库根目录运行 `.specify/scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks` 并解析 FEATURE_DIR 与 AVAILABLE_DOCS 列表。所有路径必须是绝对路径。当参数里包含单引号(例如 "I'm Groot")时,使用转义写法:如 'I'\''m Groot'(或尽量用双引号:"I'm Groot")。
17 +2. 从脚本输出中提取 **tasks** 文件路径。
18 +3. 通过以下命令获取 Git 远端地址(remote):
19 +
20 +```bash
21 +git config --get remote.origin.url
22 +```
23 +
24 +> [!CAUTION]
25 +> 只有当 remote 是 GitHub URL 时才允许继续后续步骤
26 +
27 +4. 对任务列表中的每个任务,使用 GitHub MCP server 在与该 remote 相匹配的仓库中创建一个新 issue。
28 +
29 +> [!CAUTION]
30 +> 任何情况下都不要在与 remote URL 不匹配的仓库里创建 issue
1 -## 项目原则 1 +# mlaj 宪法
2 +
3 +## 核心原则
4 +
5 +### 用户需求为中心
2 6
3 - 以用户需求为中心,优先实现最小可用闭环,避免过度设计 7 - 以用户需求为中心,优先实现最小可用闭环,避免过度设计
8 +
9 +### 修改尽量小且可回滚
10 +
4 - 修改应尽量小且可回滚,避免大范围重构 11 - 修改应尽量小且可回滚,避免大范围重构
12 +
13 +### 风格一致与复用优先
14 +
5 - 保持现有代码风格与目录结构一致,优先复用已有工具与组件 15 - 保持现有代码风格与目录结构一致,优先复用已有工具与组件
16 +
17 +### 生产代码完毕后不要重启服务
18 +
6 - 生产代码完毕后不要重启服务 19 - 生产代码完毕后不要重启服务
20 +
21 +### 操作完成后不要自动打开预览
22 +
7 - 操作完成后不要自动打开预览 23 - 操作完成后不要自动打开预览
8 24
9 ## 技术与工程约束 25 ## 技术与工程约束
...@@ -26,3 +42,9 @@ ...@@ -26,3 +42,9 @@
26 42
27 - 若图片域名为 cdn.ipadbiz.cn,需要自动追加 ?imageMogr2/thumbnail/200x/strip/quality/70 43 - 若图片域名为 cdn.ipadbiz.cn,需要自动追加 ?imageMogr2/thumbnail/200x/strip/quality/70
28 44
45 +## 治理与管理
46 +
47 +- 本宪法优先级高于临时约定与个人习惯;出现冲突时以本宪法为准
48 +- 宪法变更应同步更新版本/日期信息,并确保对现有工程约束的兼容性
49 +
50 +**版本**: [CONSTITUTION_VERSION] | **批准**: [RATIFICATION_DATE] | **最后修订**: [LAST_AMENDED_DATE]
......
1 +#!/usr/bin/env bash
2 +
3 +# 前置条件检查脚本(整合版)
4 +#
5 +# 本脚本为 Spec-Driven Development 工作流提供统一的前置条件检查,
6 +# 用于替代此前分散在多个脚本中的同类功能。
7 +#
8 +# 用法:./check-prerequisites.sh [OPTIONS]
9 +#
10 +# OPTIONS:
11 +# --json 以 JSON 格式输出
12 +# --require-tasks 要求 tasks.md 必须存在(实现阶段使用)
13 +# --include-tasks 在 AVAILABLE_DOCS 列表中包含 tasks.md
14 +# --paths-only 仅输出路径变量(不做校验)
15 +# --help, -h 显示帮助信息
16 +#
17 +# 输出:
18 +# JSON 模式:{"FEATURE_DIR":"...", "AVAILABLE_DOCS":["..."]}
19 +# 文本模式:FEATURE_DIR:... \n AVAILABLE_DOCS: \n ✓/✗ file.md
20 +# 仅路径:REPO_ROOT: ... \n BRANCH: ... \n FEATURE_DIR: ... 等
21 +
22 +set -e
23 +
24 +# 解析命令行参数
25 +JSON_MODE=false
26 +REQUIRE_TASKS=false
27 +INCLUDE_TASKS=false
28 +PATHS_ONLY=false
29 +
30 +for arg in "$@"; do
31 + case "$arg" in
32 + --json)
33 + JSON_MODE=true
34 + ;;
35 + --require-tasks)
36 + REQUIRE_TASKS=true
37 + ;;
38 + --include-tasks)
39 + INCLUDE_TASKS=true
40 + ;;
41 + --paths-only)
42 + PATHS_ONLY=true
43 + ;;
44 + --help|-h)
45 + cat << 'EOF'
46 +用法:check-prerequisites.sh [OPTIONS]
47 +
48 +用于 Spec-Driven Development 工作流的前置条件检查(整合版)。
49 +
50 +选项:
51 + --json 以 JSON 格式输出
52 + --require-tasks 要求 tasks.md 必须存在(实现阶段使用)
53 + --include-tasks 在 AVAILABLE_DOCS 列表中包含 tasks.md
54 + --paths-only 仅输出路径变量(不做前置条件校验)
55 + --help, -h 显示帮助信息
56 +
57 +示例:
58 + # 检查任务前置条件(需要 plan.md)
59 + ./check-prerequisites.sh --json
60 +
61 + # 检查实现前置条件(需要 plan.md + tasks.md)
62 + ./check-prerequisites.sh --json --require-tasks --include-tasks
63 +
64 + # 仅获取功能路径(不做校验)
65 + ./check-prerequisites.sh --paths-only
66 +
67 +EOF
68 + exit 0
69 + ;;
70 + *)
71 + echo "错误:未知选项 '$arg'。使用 --help 查看用法。" >&2
72 + exit 1
73 + ;;
74 + esac
75 +done
76 +
77 +# 引入通用函数
78 +SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
79 +source "$SCRIPT_DIR/common.sh"
80 +
81 +# 获取功能路径并校验分支
82 +eval $(get_feature_paths)
83 +check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1
84 +
85 +# 若为仅路径模式:输出路径后退出(支持 --json 与 --paths-only 组合)
86 +if $PATHS_ONLY; then
87 + if $JSON_MODE; then
88 + # 最小 JSON 路径负载(不做校验)
89 + printf '{"REPO_ROOT":"%s","BRANCH":"%s","FEATURE_DIR":"%s","FEATURE_SPEC":"%s","IMPL_PLAN":"%s","TASKS":"%s"}\n' \
90 + "$REPO_ROOT" "$CURRENT_BRANCH" "$FEATURE_DIR" "$FEATURE_SPEC" "$IMPL_PLAN" "$TASKS"
91 + else
92 + echo "REPO_ROOT: $REPO_ROOT"
93 + echo "BRANCH: $CURRENT_BRANCH"
94 + echo "FEATURE_DIR: $FEATURE_DIR"
95 + echo "FEATURE_SPEC: $FEATURE_SPEC"
96 + echo "IMPL_PLAN: $IMPL_PLAN"
97 + echo "TASKS: $TASKS"
98 + fi
99 + exit 0
100 +fi
101 +
102 +# 校验必要的目录与文件
103 +if [[ ! -d "$FEATURE_DIR" ]]; then
104 + echo "错误:未找到功能目录:$FEATURE_DIR" >&2
105 + echo "请先运行 /speckit.specify 以创建功能目录结构。" >&2
106 + exit 1
107 +fi
108 +
109 +if [[ ! -f "$IMPL_PLAN" ]]; then
110 + echo "错误:在 $FEATURE_DIR 中未找到 plan.md" >&2
111 + echo "请先运行 /speckit.plan 以创建实现计划。" >&2
112 + exit 1
113 +fi
114 +
115 +# 如果需要则检查 tasks.md
116 +if $REQUIRE_TASKS && [[ ! -f "$TASKS" ]]; then
117 + echo "错误:在 $FEATURE_DIR 中未找到 tasks.md" >&2
118 + echo "请先运行 /speckit.tasks 以创建任务清单。" >&2
119 + exit 1
120 +fi
121 +
122 +# 构建可用文档列表
123 +docs=()
124 +
125 +# 固定检查这些可选文档
126 +[[ -f "$RESEARCH" ]] && docs+=("research.md")
127 +[[ -f "$DATA_MODEL" ]] && docs+=("data-model.md")
128 +
129 +# 检查 contracts 目录(仅当存在且非空)
130 +if [[ -d "$CONTRACTS_DIR" ]] && [[ -n "$(ls -A "$CONTRACTS_DIR" 2>/dev/null)" ]]; then
131 + docs+=("contracts/")
132 +fi
133 +
134 +[[ -f "$QUICKSTART" ]] && docs+=("quickstart.md")
135 +
136 +# 若要求包含 tasks.md,且文件存在,则加入列表
137 +if $INCLUDE_TASKS && [[ -f "$TASKS" ]]; then
138 + docs+=("tasks.md")
139 +fi
140 +
141 +# 输出结果
142 +if $JSON_MODE; then
143 + # 构建文档 JSON 数组
144 + if [[ ${#docs[@]} -eq 0 ]]; then
145 + json_docs="[]"
146 + else
147 + json_docs=$(printf '"%s",' "${docs[@]}")
148 + json_docs="[${json_docs%,}]"
149 + fi
150 +
151 + printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s}\n' "$FEATURE_DIR" "$json_docs"
152 +else
153 + # 文本输出
154 + echo "FEATURE_DIR:$FEATURE_DIR"
155 + echo "AVAILABLE_DOCS:"
156 +
157 + # 展示各文档的存在状态
158 + check_file "$RESEARCH" "research.md"
159 + check_file "$DATA_MODEL" "data-model.md"
160 + check_dir "$CONTRACTS_DIR" "contracts/"
161 + check_file "$QUICKSTART" "quickstart.md"
162 +
163 + if $INCLUDE_TASKS; then
164 + check_file "$TASKS" "tasks.md"
165 + fi
166 +fi
1 +#!/usr/bin/env bash
2 +# 所有脚本共用的函数与变量
3 +
4 +# 获取仓库根目录(非 git 仓库时提供兜底)
5 +get_repo_root() {
6 + if git rev-parse --show-toplevel >/dev/null 2>&1; then
7 + git rev-parse --show-toplevel
8 + else
9 + # 非 git 仓库:回退为脚本所在目录向上查找
10 + local script_dir="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11 + (cd "$script_dir/../../.." && pwd)
12 + fi
13 +}
14 +
15 +# 获取当前分支(非 git 仓库时提供兜底)
16 +get_current_branch() {
17 + # 优先使用 SPECIFY_FEATURE 环境变量
18 + if [[ -n "${SPECIFY_FEATURE:-}" ]]; then
19 + echo "$SPECIFY_FEATURE"
20 + return
21 + fi
22 +
23 + # 其次尝试从 git 读取
24 + if git rev-parse --abbrev-ref HEAD >/dev/null 2>&1; then
25 + git rev-parse --abbrev-ref HEAD
26 + return
27 + fi
28 +
29 + # 非 git 仓库:尝试找到最新的功能目录
30 + local repo_root=$(get_repo_root)
31 + local specs_dir="$repo_root/specs"
32 +
33 + if [[ -d "$specs_dir" ]]; then
34 + local latest_feature=""
35 + local highest=0
36 +
37 + for dir in "$specs_dir"/*; do
38 + if [[ -d "$dir" ]]; then
39 + local dirname=$(basename "$dir")
40 + if [[ "$dirname" =~ ^([0-9]{3})- ]]; then
41 + local number=${BASH_REMATCH[1]}
42 + number=$((10#$number))
43 + if [[ "$number" -gt "$highest" ]]; then
44 + highest=$number
45 + latest_feature=$dirname
46 + fi
47 + fi
48 + fi
49 + done
50 +
51 + if [[ -n "$latest_feature" ]]; then
52 + echo "$latest_feature"
53 + return
54 + fi
55 + fi
56 +
57 + echo "main" # 最终兜底
58 +}
59 +
60 +# 检查是否为 git 仓库
61 +has_git() {
62 + git rev-parse --show-toplevel >/dev/null 2>&1
63 +}
64 +
65 +check_feature_branch() {
66 + local branch="$1"
67 + local has_git_repo="$2"
68 +
69 + # 非 git 仓库无法强制分支命名,但仍输出提示
70 + if [[ "$has_git_repo" != "true" ]]; then
71 + echo "[specify] 警告:未检测到 Git 仓库;已跳过分支校验" >&2
72 + return 0
73 + fi
74 +
75 + if [[ ! "$branch" =~ ^[0-9]{3}- ]]; then
76 + echo "错误:当前不在功能分支。当前分支:$branch" >&2
77 + echo "功能分支命名应类似:001-feature-name" >&2
78 + return 1
79 + fi
80 +
81 + return 0
82 +}
83 +
84 +get_feature_dir() { echo "$1/specs/$2"; }
85 +
86 +# 按数字前缀查找功能目录,而不是严格按分支名匹配
87 +# 这样允许多个分支指向同一份规格(例如 004-fix-bug、004-add-feature)
88 +find_feature_dir_by_prefix() {
89 + local repo_root="$1"
90 + local branch_name="$2"
91 + local specs_dir="$repo_root/specs"
92 +
93 + # 从分支名提取数字前缀(例如从 "004-whatever" 提取 "004")
94 + if [[ ! "$branch_name" =~ ^([0-9]{3})- ]]; then
95 + # 分支名不含数字前缀:回退为按分支名拼路径
96 + echo "$specs_dir/$branch_name"
97 + return
98 + fi
99 +
100 + local prefix="${BASH_REMATCH[1]}"
101 +
102 + # 在 specs/ 下查找以该前缀开头的目录
103 + local matches=()
104 + if [[ -d "$specs_dir" ]]; then
105 + for dir in "$specs_dir"/"$prefix"-*; do
106 + if [[ -d "$dir" ]]; then
107 + matches+=("$(basename "$dir")")
108 + fi
109 + done
110 + fi
111 +
112 + # 处理查找结果
113 + if [[ ${#matches[@]} -eq 0 ]]; then
114 + # 未找到:返回按分支名拼的路径(后续会给出更明确的错误)
115 + echo "$specs_dir/$branch_name"
116 + elif [[ ${#matches[@]} -eq 1 ]]; then
117 + # 仅一个匹配:直接返回
118 + echo "$specs_dir/${matches[0]}"
119 + else
120 + # 多个匹配:命名规范正确时不应发生
121 + echo "错误:发现多个同前缀规格目录 '$prefix':${matches[*]}" >&2
122 + echo "请确保每个数字前缀只对应一个规格目录。" >&2
123 + echo "$specs_dir/$branch_name" # 返回一个路径以避免脚本中断
124 + fi
125 +}
126 +
127 +get_feature_paths() {
128 + local repo_root=$(get_repo_root)
129 + local current_branch=$(get_current_branch)
130 + local has_git_repo="false"
131 +
132 + if has_git; then
133 + has_git_repo="true"
134 + fi
135 +
136 + # 使用前缀匹配以支持“多分支对应同一份规格”的场景
137 + local feature_dir=$(find_feature_dir_by_prefix "$repo_root" "$current_branch")
138 +
139 + cat <<EOF
140 +REPO_ROOT='$repo_root'
141 +CURRENT_BRANCH='$current_branch'
142 +HAS_GIT='$has_git_repo'
143 +FEATURE_DIR='$feature_dir'
144 +FEATURE_SPEC='$feature_dir/spec.md'
145 +IMPL_PLAN='$feature_dir/plan.md'
146 +TASKS='$feature_dir/tasks.md'
147 +RESEARCH='$feature_dir/research.md'
148 +DATA_MODEL='$feature_dir/data-model.md'
149 +QUICKSTART='$feature_dir/quickstart.md'
150 +CONTRACTS_DIR='$feature_dir/contracts'
151 +EOF
152 +}
153 +
154 +check_file() { [[ -f "$1" ]] && echo " ✓ $2" || echo " ✗ $2"; }
155 +check_dir() { [[ -d "$1" && -n $(ls -A "$1" 2>/dev/null) ]] && echo " ✓ $2" || echo " ✗ $2"; }
1 +#!/usr/bin/env bash
2 +
3 +set -e
4 +
5 +JSON_MODE=false
6 +SHORT_NAME=""
7 +BRANCH_NUMBER=""
8 +ARGS=()
9 +i=1
10 +while [ $i -le $# ]; do
11 + arg="${!i}"
12 + case "$arg" in
13 + --json)
14 + JSON_MODE=true
15 + ;;
16 + --short-name)
17 + if [ $((i + 1)) -gt $# ]; then
18 + echo '错误:--short-name 需要提供值' >&2
19 + exit 1
20 + fi
21 + i=$((i + 1))
22 + next_arg="${!i}"
23 + # 检查下一个参数是否为另一个选项(以 -- 开头)
24 + if [[ "$next_arg" == --* ]]; then
25 + echo '错误:--short-name 需要提供值' >&2
26 + exit 1
27 + fi
28 + SHORT_NAME="$next_arg"
29 + ;;
30 + --number)
31 + if [ $((i + 1)) -gt $# ]; then
32 + echo '错误:--number 需要提供值' >&2
33 + exit 1
34 + fi
35 + i=$((i + 1))
36 + next_arg="${!i}"
37 + if [[ "$next_arg" == --* ]]; then
38 + echo '错误:--number 需要提供值' >&2
39 + exit 1
40 + fi
41 + BRANCH_NUMBER="$next_arg"
42 + ;;
43 + --help|-h)
44 + echo "用法:$0 [--json] [--short-name <短名>] [--number N] <功能描述>"
45 + echo ""
46 + echo "选项:"
47 + echo " --json 以 JSON 格式输出"
48 + echo " --short-name <短名> 为分支提供自定义短名(2-4 个单词)"
49 + echo " --number N 手动指定分支编号(覆盖自动检测)"
50 + echo " --help, -h 显示帮助信息"
51 + echo ""
52 + echo "示例:"
53 + echo " $0 '新增用户登录与鉴权能力' --short-name 'user-auth'"
54 + echo " $0 '为 API 接入 OAuth2 登录' --number 5"
55 + exit 0
56 + ;;
57 + *)
58 + ARGS+=("$arg")
59 + ;;
60 + esac
61 + i=$((i + 1))
62 +done
63 +
64 +FEATURE_DESCRIPTION="${ARGS[*]}"
65 +if [ -z "$FEATURE_DESCRIPTION" ]; then
66 + echo "用法:$0 [--json] [--short-name <短名>] [--number N] <功能描述>" >&2
67 + exit 1
68 +fi
69 +
70 +# 通过查找项目标记来定位仓库根目录
71 +find_repo_root() {
72 + local dir="$1"
73 + while [ "$dir" != "/" ]; do
74 + if [ -d "$dir/.git" ] || [ -d "$dir/.specify" ]; then
75 + echo "$dir"
76 + return 0
77 + fi
78 + dir="$(dirname "$dir")"
79 + done
80 + return 1
81 +}
82 +
83 +# 从 specs 目录中获取最大编号
84 +get_highest_from_specs() {
85 + local specs_dir="$1"
86 + local highest=0
87 +
88 + if [ -d "$specs_dir" ]; then
89 + for dir in "$specs_dir"/*; do
90 + [ -d "$dir" ] || continue
91 + dirname=$(basename "$dir")
92 + number=$(echo "$dirname" | grep -o '^[0-9]\+' || echo "0")
93 + number=$((10#$number))
94 + if [ "$number" -gt "$highest" ]; then
95 + highest=$number
96 + fi
97 + done
98 + fi
99 +
100 + echo "$highest"
101 +}
102 +
103 +# 从 git 分支中获取最大编号
104 +get_highest_from_branches() {
105 + local highest=0
106 +
107 + # 获取所有分支(本地 + 远端)
108 + branches=$(git branch -a 2>/dev/null || echo "")
109 +
110 + if [ -n "$branches" ]; then
111 + while IFS= read -r branch; do
112 + # 清理分支名:移除前缀标记与远端前缀
113 + clean_branch=$(echo "$branch" | sed 's/^[* ]*//; s|^remotes/[^/]*/||')
114 +
115 + # 若分支符合 ###-*,则提取功能编号
116 + if echo "$clean_branch" | grep -q '^[0-9]\{3\}-'; then
117 + number=$(echo "$clean_branch" | grep -o '^[0-9]\{3\}' || echo "0")
118 + number=$((10#$number))
119 + if [ "$number" -gt "$highest" ]; then
120 + highest=$number
121 + fi
122 + fi
123 + done <<< "$branches"
124 + fi
125 +
126 + echo "$highest"
127 +}
128 +
129 +# 检查现有分支(本地 + 远端)并返回下一个可用编号
130 +check_existing_branches() {
131 + local specs_dir="$1"
132 +
133 + # 拉取所有远端以获取最新分支信息(无远端时忽略错误)
134 + git fetch --all --prune 2>/dev/null || true
135 +
136 + # 获取所有分支中的最大编号(不局限于匹配 short name)
137 + local highest_branch=$(get_highest_from_branches)
138 +
139 + # 获取所有 specs 中的最大编号(不局限于匹配 short name)
140 + local highest_spec=$(get_highest_from_specs "$specs_dir")
141 +
142 + # 两者取最大值
143 + local max_num=$highest_branch
144 + if [ "$highest_spec" -gt "$max_num" ]; then
145 + max_num=$highest_spec
146 + fi
147 +
148 + # 返回下一个编号
149 + echo $((max_num + 1))
150 +}
151 +
152 +# 清理并格式化分支名
153 +clean_branch_name() {
154 + local name="$1"
155 + echo "$name" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//' | sed 's/-$//'
156 +}
157 +
158 +# 解析仓库根目录:优先使用 git 信息;如不可用则回退为查找仓库标记,
159 +# 以兼容使用 --no-git 初始化的仓库。
160 +SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
161 +
162 +if git rev-parse --show-toplevel >/dev/null 2>&1; then
163 + REPO_ROOT=$(git rev-parse --show-toplevel)
164 + HAS_GIT=true
165 +else
166 + REPO_ROOT="$(find_repo_root "$SCRIPT_DIR")"
167 + if [ -z "$REPO_ROOT" ]; then
168 + echo "错误:无法确定仓库根目录。请在仓库内运行本脚本。" >&2
169 + exit 1
170 + fi
171 + HAS_GIT=false
172 +fi
173 +
174 +cd "$REPO_ROOT"
175 +
176 +SPECS_DIR="$REPO_ROOT/specs"
177 +mkdir -p "$SPECS_DIR"
178 +
179 +# 生成分支名:包含停用词过滤与长度过滤
180 +generate_branch_name() {
181 + local description="$1"
182 +
183 + # 常见停用词(用于过滤)
184 + local stop_words="^(i|a|an|the|to|for|of|in|on|at|by|with|from|is|are|was|were|be|been|being|have|has|had|do|does|did|will|would|should|could|can|may|might|must|shall|this|that|these|those|my|your|our|their|want|need|add|get|set)$"
185 +
186 + # 转小写并按单词拆分
187 + local clean_name=$(echo "$description" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/ /g')
188 +
189 + # 过滤单词:移除停用词与长度 < 3 的词(除非在原描述中以大写出现,通常为缩写)
190 + local meaningful_words=()
191 + for word in $clean_name; do
192 + # 跳过空词
193 + [ -z "$word" ] && continue
194 +
195 + # 保留:不属于停用词,并且(长度 >= 3 或为可能的缩写)
196 + if ! echo "$word" | grep -qiE "$stop_words"; then
197 + if [ ${#word} -ge 3 ]; then
198 + meaningful_words+=("$word")
199 + elif echo "$description" | grep -q "\b${word^^}\b"; then
200 + # 原描述中若以大写出现则保留(很可能是缩写)
201 + meaningful_words+=("$word")
202 + fi
203 + fi
204 + done
205 +
206 + # 若有有效词,则取前 3-4 个
207 + if [ ${#meaningful_words[@]} -gt 0 ]; then
208 + local max_words=3
209 + if [ ${#meaningful_words[@]} -eq 4 ]; then max_words=4; fi
210 +
211 + local result=""
212 + local count=0
213 + for word in "${meaningful_words[@]}"; do
214 + if [ $count -ge $max_words ]; then break; fi
215 + if [ -n "$result" ]; then result="$result-"; fi
216 + result="$result$word"
217 + count=$((count + 1))
218 + done
219 + echo "$result"
220 + else
221 + # 若未找到有效词:回退为原始逻辑
222 + local cleaned=$(clean_branch_name "$description")
223 + echo "$cleaned" | tr '-' '\n' | grep -v '^$' | head -3 | tr '\n' '-' | sed 's/-$//'
224 + fi
225 +}
226 +
227 +# 生成分支名
228 +if [ -n "$SHORT_NAME" ]; then
229 + # 使用用户提供的 short name,并做清理
230 + BRANCH_SUFFIX=$(clean_branch_name "$SHORT_NAME")
231 +else
232 + # 根据描述智能过滤生成
233 + BRANCH_SUFFIX=$(generate_branch_name "$FEATURE_DESCRIPTION")
234 +fi
235 +
236 +# 确定分支编号
237 +if [ -z "$BRANCH_NUMBER" ]; then
238 + if [ "$HAS_GIT" = true ]; then
239 + # 检查远端已有分支
240 + BRANCH_NUMBER=$(check_existing_branches "$SPECS_DIR")
241 + else
242 + # 回退为本地目录检查
243 + HIGHEST=$(get_highest_from_specs "$SPECS_DIR")
244 + BRANCH_NUMBER=$((HIGHEST + 1))
245 + fi
246 +fi
247 +
248 +# 强制按十进制解释,避免八进制转换(例如 010 在八进制会变为 8,但这里应是十进制 10)
249 +FEATURE_NUM=$(printf "%03d" "$((10#$BRANCH_NUMBER))")
250 +BRANCH_NAME="${FEATURE_NUM}-${BRANCH_SUFFIX}"
251 +
252 +# GitHub 对分支名有 244 字节限制:必要时校验并截断
253 +MAX_BRANCH_LENGTH=244
254 +if [ ${#BRANCH_NAME} -gt $MAX_BRANCH_LENGTH ]; then
255 + # 计算需要从后缀中截断的长度
256 + # 分支名包含:功能编号(3)+ 连字符(1)= 4 个字符
257 + MAX_SUFFIX_LENGTH=$((MAX_BRANCH_LENGTH - 4))
258 +
259 + # 尽量按单词边界截断后缀
260 + TRUNCATED_SUFFIX=$(echo "$BRANCH_SUFFIX" | cut -c1-$MAX_SUFFIX_LENGTH)
261 + # 若截断产生了末尾连字符则移除
262 + TRUNCATED_SUFFIX=$(echo "$TRUNCATED_SUFFIX" | sed 's/-$//')
263 +
264 + ORIGINAL_BRANCH_NAME="$BRANCH_NAME"
265 + BRANCH_NAME="${FEATURE_NUM}-${TRUNCATED_SUFFIX}"
266 +
267 + >&2 echo "[specify] Warning: 分支名超过 GitHub 的 244 字节限制"
268 + >&2 echo "[specify] 原始:$ORIGINAL_BRANCH_NAME${#ORIGINAL_BRANCH_NAME} 字节)"
269 + >&2 echo "[specify] 已截断为:$BRANCH_NAME${#BRANCH_NAME} 字节)"
270 +fi
271 +
272 +if [ "$HAS_GIT" = true ]; then
273 + git checkout -b "$BRANCH_NAME"
274 +else
275 + >&2 echo "[specify] Warning: 未检测到 Git 仓库;已跳过创建分支 $BRANCH_NAME"
276 +fi
277 +
278 +FEATURE_DIR="$SPECS_DIR/$BRANCH_NAME"
279 +mkdir -p "$FEATURE_DIR"
280 +
281 +TEMPLATE="$REPO_ROOT/.specify/templates/spec-template.md"
282 +SPEC_FILE="$FEATURE_DIR/spec.md"
283 +if [ -f "$TEMPLATE" ]; then cp "$TEMPLATE" "$SPEC_FILE"; else touch "$SPEC_FILE"; fi
284 +
285 +# 为当前会话设置 SPECIFY_FEATURE 环境变量
286 +export SPECIFY_FEATURE="$BRANCH_NAME"
287 +
288 +if $JSON_MODE; then
289 + printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s"}\n' "$BRANCH_NAME" "$SPEC_FILE" "$FEATURE_NUM"
290 +else
291 + echo "BRANCH_NAME: $BRANCH_NAME"
292 + echo "SPEC_FILE: $SPEC_FILE"
293 + echo "FEATURE_NUM: $FEATURE_NUM"
294 + echo "已设置 SPECIFY_FEATURE 环境变量为:$BRANCH_NAME"
295 +fi
1 +#!/usr/bin/env bash
2 +
3 +set -e
4 +
5 +# 解析命令行参数
6 +JSON_MODE=false
7 +ARGS=()
8 +
9 +for arg in "$@"; do
10 + case "$arg" in
11 + --json)
12 + JSON_MODE=true
13 + ;;
14 + --help|-h)
15 + echo "用法:$0 [--json]"
16 + echo " --json 以 JSON 格式输出结果"
17 + echo " --help 显示帮助信息"
18 + exit 0
19 + ;;
20 + *)
21 + ARGS+=("$arg")
22 + ;;
23 + esac
24 +done
25 +
26 +# 获取脚本目录并加载通用函数
27 +SCRIPT_DIR="$(CDPATH="" cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
28 +source "$SCRIPT_DIR/common.sh"
29 +
30 +# 从通用函数获取所有路径与变量
31 +eval $(get_feature_paths)
32 +
33 +# 检查是否在合规的功能分支上(仅 git 仓库)
34 +check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1
35 +
36 +# 确保功能目录存在
37 +mkdir -p "$FEATURE_DIR"
38 +
39 +# 如果存在计划模板,则复制
40 +TEMPLATE="$REPO_ROOT/.specify/templates/plan-template.md"
41 +if [[ -f "$TEMPLATE" ]]; then
42 + cp "$TEMPLATE" "$IMPL_PLAN"
43 + echo "已复制 plan 模板到:$IMPL_PLAN"
44 +else
45 + echo "警告:未找到 plan 模板:$TEMPLATE"
46 + # 如果不存在模板,则创建空的 plan 文件
47 + touch "$IMPL_PLAN"
48 +fi
49 +
50 +# 输出结果
51 +if $JSON_MODE; then
52 + printf '{"FEATURE_SPEC":"%s","IMPL_PLAN":"%s","SPECS_DIR":"%s","BRANCH":"%s","HAS_GIT":"%s"}\n' \
53 + "$FEATURE_SPEC" "$IMPL_PLAN" "$FEATURE_DIR" "$CURRENT_BRANCH" "$HAS_GIT"
54 +else
55 + echo "FEATURE_SPEC: $FEATURE_SPEC"
56 + echo "IMPL_PLAN: $IMPL_PLAN"
57 + echo "SPECS_DIR: $FEATURE_DIR"
58 + echo "BRANCH: $CURRENT_BRANCH"
59 + echo "HAS_GIT: $HAS_GIT"
60 +fi
This diff is collapsed. Click to expand it.
1 +# [项目名称] 开发规范
2 +
3 +从所有功能计划自动生成。最近更新:[DATE]
4 +
5 +## 当前技术栈
6 +
7 +[从所有 plan.md 中提取]
8 +
9 +## 项目结构
10 +
11 +```text
12 +[从计划中提取的真实结构]
13 +```
14 +
15 +## 常用命令
16 +
17 +[仅保留与当前技术栈相关的命令]
18 +
19 +## 代码风格
20 +
21 +[语言相关规范(仅保留当前使用的语言)]
22 +
23 +## 最近变更
24 +
25 +[最近 3 个功能及其变更]
26 +
27 +<!-- 手工补充开始 -->
28 +<!-- 手工补充结束 -->
1 +# [清单类型] 检查清单:[功能名称]
2 +
3 +**用途**[本清单覆盖内容的简要说明]
4 +**创建时间**[DATE]
5 +**关联功能**[链接到 spec.md 或相关文档]
6 +
7 +**说明**:本清单由 `/speckit.checklist` 命令基于功能上下文与需求自动生成。
8 +
9 +<!--
10 + ============================================================================
11 + 重要:以下检查项仅为示例,用于说明格式。
12 +
13 + /speckit.checklist 命令必须基于以下信息,将这些示例替换为真实检查项:
14 + - 用户提出的具体检查清单诉求
15 + - spec.md 中的功能需求
16 + - plan.md 中的技术上下文
17 + - tasks.md 中的实现细节
18 +
19 + 生成的 checklist 文件中不要保留这些示例项。
20 + ============================================================================
21 +-->
22 +
23 +## [分类 1]
24 +
25 +- [ ] CHK001 第一条检查项(动作明确)
26 +- [ ] CHK002 第二条检查项
27 +- [ ] CHK003 第三条检查项
28 +
29 +## [分类 2]
30 +
31 +- [ ] CHK004 另一类检查项
32 +- [ ] CHK005 带具体判定标准的检查项
33 +- [ ] CHK006 本分类最后一条检查项
34 +
35 +## 备注
36 +
37 +- 完成后勾选:`[x]`
38 +- 发现问题可直接在行内补充说明
39 +- 可添加链接指向相关资源或文档
40 +- 条目按编号顺序排列,便于引用
1 +# 实现计划:[FEATURE]
2 +
3 +**分支**`[###-feature-name]` | **日期**[DATE] | **规格说明**[link]
4 +**输入**:来自 `/specs/[###-feature-name]/spec.md` 的功能规格说明
5 +
6 +**说明**:本模板由 `/speckit.plan` 命令填充。执行流程可参考 `.specify/templates/commands/plan.md`
7 +
8 +## 摘要
9 +
10 +[从功能规格中提取:核心需求 +(结合 research 的)技术方案摘要]
11 +
12 +## 技术上下文
13 +
14 +<!--
15 + 必填:将本章节内容替换为项目的技术细节。
16 + 这里的结构仅用于引导迭代过程,可按需调整。
17 +-->
18 +
19 +**语言/版本**: [例如 Python 3.11、Swift 5.9、Rust 1.75 或 NEEDS CLARIFICATION]
20 +**主要依赖**: [例如 FastAPI、UIKit、LLVM 或 NEEDS CLARIFICATION]
21 +**存储**: [如适用,例如 PostgreSQL、CoreData、文件 或 N/A]
22 +**测试**: [例如 pytest、XCTest、cargo test 或 NEEDS CLARIFICATION]
23 +**目标平台**: [例如 Linux 服务器、iOS 15+、WASM 或 NEEDS CLARIFICATION]
24 +**工程类型**: [single/web/mobile - 决定源码结构]
25 +**性能目标**: [领域相关,例如 1000 req/s、10k lines/sec、60 fps 或 NEEDS CLARIFICATION]
26 +**约束**: [领域相关,例如 <200ms p95、<100MB 内存、支持离线 或 NEEDS CLARIFICATION]
27 +**规模/范围**: [领域相关,例如 10k 用户、1M LOC、50 个页面 或 NEEDS CLARIFICATION]
28 +
29 +## 宪法检查
30 +
31 +*门禁:必须在阶段 0 调研前通过;在阶段 1 设计后需要复检。*
32 +
33 +[根据 constitution 文件确定门禁项]
34 +
35 +
36 +## 项目结构
37 +
38 +### 文档(本功能)
39 +
40 +```text
41 +specs/[###-feature]/
42 +├── plan.md # 本文件(/speckit.plan 输出)
43 +├── research.md # 阶段 0 输出(/speckit.plan)
44 +├── data-model.md # 阶段 1 输出(/speckit.plan)
45 +├── quickstart.md # 阶段 1 输出(/speckit.plan)
46 +├── contracts/ # 阶段 1 输出(/speckit.plan)
47 +└── tasks.md # 阶段 2 输出(/speckit.tasks - 不由 /speckit.plan 创建)
48 +```
49 +
50 +### 源码(仓库根目录)
51 +<!--
52 + 必填:将下方占位树替换为本功能对应的真实目录结构。
53 + 删除未使用的选项,并将所选结构扩展为真实路径(例如 apps/admin、packages/xxx)。
54 + 最终交付的 plan.md 不应包含 “选项” 字样。
55 +-->
56 +
57 +```text
58 +# [不使用则删除] 选项 1:单体工程(默认)
59 +src/
60 +├── models/
61 +├── services/
62 +├── cli/
63 +└── lib/
64 +
65 +tests/
66 +├── contract/
67 +├── integration/
68 +└── unit/
69 +
70 +# [不使用则删除] 选项 2:Web 应用(检测到 "frontend" + "backend" 时)
71 +backend/
72 +├── src/
73 +│ ├── models/
74 +│ ├── services/
75 +│ └── api/
76 +└── tests/
77 +
78 +frontend/
79 +├── src/
80 +│ ├── components/
81 +│ ├── pages/
82 +│ └── services/
83 +└── tests/
84 +
85 +# [不使用则删除] 选项 3:移动端 + API(检测到 "iOS/Android" 时)
86 +api/
87 +└── [同 backend 的结构]
88 +
89 +ios/ 或 android/
90 +└── [平台相关结构:功能模块、UI 流程、平台测试]
91 +```
92 +
93 +**结构选择**: [说明最终选择的结构,并引用上面列出的真实目录]
94 +
95 +## 复杂度记录
96 +
97 +> **仅在“宪法检查”存在需要解释的违规项时填写**
98 +
99 +| 违规项 | 必要性 | 为什么不能用更简单方案 |
100 +|--------|--------|--------------------------|
101 +| [例如:第 4 个子工程] | [当前需求] | [为何 3 个工程不够] |
102 +| [例如:Repository 模式] | [具体问题] | [为何不能直接访问数据库] |
1 +# 功能规格说明:[功能名称]
2 +
3 +**功能分支**`[###-feature-name]`
4 +**创建时间**[DATE]
5 +**状态**:草稿
6 +**输入**:用户描述:"$ARGUMENTS"
7 +
8 +## 用户场景与验收 *(必填)*
9 +
10 +<!--
11 + 重要:用户故事必须按重要性排序,体现为“用户旅程”优先级。
12 + 每个用户故事/旅程都必须可以独立验收——意味着即使只实现其中一个,
13 + 也应当形成可用的 MVP(最小可用产品)并能交付价值。
14 +
15 + 为每个故事分配优先级(P1、P2、P3...),其中 P1 最关键。
16 + 将每个故事视为一段可独立交付的功能切片,能够:
17 + - 独立开发
18 + - 独立验收
19 + - 独立部署
20 + - 独立向用户演示
21 +-->
22 +
23 +### 用户故事 1 - [简短标题](优先级:P1)
24 +
25 +[用通俗语言描述该用户旅程]
26 +
27 +**为什么是这个优先级**[解释价值以及为何排在该优先级]
28 +
29 +**独立验收**[描述如何独立验收——例如:“通过 [具体动作] 即可完整验收,并交付 [具体价值]”】【示例仅供参考】
30 +
31 +**验收场景**
32 +
33 +1. **假设** [初始状态]**当** [动作]**则** [期望结果]
34 +2. **假设** [初始状态]**当** [动作]**则** [期望结果]
35 +
36 +---
37 +
38 +### 用户故事 2 - [简短标题](优先级:P2)
39 +
40 +[用通俗语言描述该用户旅程]
41 +
42 +**为什么是这个优先级**[解释价值以及为何排在该优先级]
43 +
44 +**独立验收**[描述如何独立验收]
45 +
46 +**验收场景**
47 +
48 +1. **假设** [初始状态]**当** [动作]**则** [期望结果]
49 +
50 +---
51 +
52 +### 用户故事 3 - [简短标题](优先级:P3)
53 +
54 +[用通俗语言描述该用户旅程]
55 +
56 +**为什么是这个优先级**[解释价值以及为何排在该优先级]
57 +
58 +**独立验收**[描述如何独立验收]
59 +
60 +**验收场景**
61 +
62 +1. **假设** [初始状态]**当** [动作]**则** [期望结果]
63 +
64 +---
65 +
66 +[按需补充更多用户故事,并为每个故事分配优先级]
67 +
68 +### 边界情况
69 +
70 +<!--
71 + 需要补全:本章节内容是占位符。
72 + 请补充正确的边界情况。
73 +-->
74 +
75 +-[边界条件] 时会发生什么?
76 +- 系统如何处理 [错误场景]
77 +
78 +## 需求 *(必填)*
79 +
80 +<!--
81 + 需要补全:本章节内容是占位符。
82 + 请补充正确的功能需求。
83 +-->
84 +
85 +### 功能需求
86 +
87 +- **FR-001**:系统必须 [具体能力,例如“允许用户创建账号”]
88 +- **FR-002**:系统必须 [具体能力,例如“校验邮箱地址”]
89 +- **FR-003**:用户必须能够 [关键交互,例如“重置密码”]
90 +- **FR-004**:系统必须 [数据要求,例如“持久化用户偏好”]
91 +- **FR-005**:系统必须 [行为要求,例如“记录所有安全事件”]
92 +
93 +*标记不清晰需求的示例:*
94 +
95 +- **FR-006**:系统必须通过 [NEEDS CLARIFICATION:认证方式未指定——邮箱/密码、SSO、OAuth?] 对用户进行认证
96 +- **FR-007**:系统必须保留用户数据 [NEEDS CLARIFICATION:保留期限未指定]
97 +
98 +### 关键实体 *(当功能涉及数据时填写)*
99 +
100 +- **[实体 1]**[表示什么;关键属性(不写实现细节)]
101 +- **[实体 2]**[表示什么;与其他实体的关系]
102 +
103 +## 成功标准 *(必填)*
104 +
105 +<!--
106 + 需要补全:定义可度量的成功标准。
107 + 必须与技术实现无关,并且可度量。
108 +-->
109 +
110 +### 可度量结果
111 +
112 +- **SC-001**[可度量指标,例如“用户可在 2 分钟内完成账号创建”】【示例仅供参考】
113 +- **SC-002**[可度量指标,例如“系统在 1000 并发用户下无明显劣化”】【示例仅供参考】
114 +- **SC-003**[用户满意度指标,例如“90% 的用户首次尝试即可完成主任务”】【示例仅供参考】
115 +- **SC-004**[业务指标,例如“将与 [X] 相关的支持工单减少 50%”】【示例仅供参考】
1 +---
2 +
3 +description: "功能实现的任务清单模板"
4 +---
5 +
6 +# 任务清单:[功能名称]
7 +
8 +**输入**:来自 `/specs/[###-feature-name]/` 的设计与规格文档
9 +**前置条件**:plan.md(必需)、spec.md(用户故事必需)、research.md、data-model.md、contracts/
10 +
11 +**测试**:下方示例包含测试任务。测试是可选的——仅在功能规格中明确要求时才需要包含。
12 +
13 +**组织方式**:任务按用户故事分组,保证每个故事都能独立实现与独立验证。
14 +
15 +## 格式:`[ID] [P?] [Story] 描述`
16 +
17 +- **[P]**:可并行执行(不同文件、无依赖)
18 +- **[Story]**:任务所属用户故事(例如 US1、US2、US3)
19 +- 描述中包含准确的文件路径
20 +
21 +## 路径约定
22 +
23 +- **单体工程**:仓库根目录下 `src/``tests/`
24 +- **Web 应用**`backend/src/``frontend/src/`
25 +- **移动端**`api/src/``ios/src/``android/src/`
26 +- 下方展示默认按“单体工程”组织;请根据 plan.md 的结构调整
27 +
28 +<!--
29 + ============================================================================
30 + 重要:以下任务仅为示例,用于说明结构与写法。
31 +
32 + /speckit.tasks 命令必须基于以下信息,将这些示例替换为真实任务:
33 + - spec.md 的用户故事(含优先级 P1、P2、P3...)
34 + - plan.md 的功能与实现要求
35 + - data-model.md 的实体
36 + - contracts/ 的接口定义
37 +
38 + 任务必须按用户故事组织,使每个故事都能:
39 + - 独立实现
40 + - 独立验证
41 + - 作为 MVP 增量交付
42 +
43 + 生成的 tasks.md 文件中不要保留这些示例任务。
44 + ============================================================================
45 +-->
46 +
47 +## 阶段 1:准备(共享基础设施)
48 +
49 +**目标**:项目初始化与基础结构搭建
50 +
51 +- [ ] T001 按实现计划创建项目结构
52 +- [ ] T002 初始化 [language] 工程并安装 [framework] 依赖
53 +- [ ] T003 [P] 配置 lint 与格式化工具
54 +
55 +---
56 +
57 +## 阶段 2:基础(阻塞性前置条件)
58 +
59 +**目标**:核心基础设施(任何用户故事开始前必须完成)
60 +
61 +**⚠️ 关键**:在本阶段完成前,不允许开始任何用户故事的工作
62 +
63 +基础任务示例(请根据项目实际情况调整):
64 +
65 +- [ ] T004 建立数据库结构与迁移机制
66 +- [ ] T005 [P] 实现认证/鉴权框架
67 +- [ ] T006 [P] 建立 API 路由与中间件结构
68 +- [ ] T007 创建所有故事依赖的基础模型/实体
69 +- [ ] T008 配置错误处理与日志基础设施
70 +- [ ] T009 建立环境配置管理
71 +
72 +**检查点**:基础设施就绪——用户故事实现可以并行推进
73 +
74 +---
75 +
76 +## 阶段 3:用户故事 1 - [标题](优先级:P1)🎯 MVP
77 +
78 +**目标**[简述该故事交付内容]
79 +
80 +**独立验证**[如何单独验证该故事可用]
81 +
82 +### 用户故事 1 的测试(可选:仅在明确要求测试时)⚠️
83 +
84 +> **注意:先写测试,并确保在实现前测试会失败**
85 +
86 +- [ ] T010 [P] [US1][endpoint] 编写契约测试:tests/contract/test_[name].py
87 +- [ ] T011 [P] [US1][用户旅程] 编写集成测试:tests/integration/test_[name].py
88 +
89 +### 用户故事 1 的实现
90 +
91 +- [ ] T012 [P] [US1] 创建 [Entity1] 模型:src/models/[entity1].py
92 +- [ ] T013 [P] [US1] 创建 [Entity2] 模型:src/models/[entity2].py
93 +- [ ] T014 [US1] 实现 [Service]:src/services/[service].py(依赖 T012、T013)
94 +- [ ] T015 [US1] 实现 [endpoint/feature]:src/[location]/[file].py
95 +- [ ] T016 [US1] 增加校验与错误处理
96 +- [ ] T017 [US1] 为用户故事 1 的关键操作补充日志
97 +
98 +**检查点**:此时用户故事 1 应完整可用,且可独立验证
99 +
100 +---
101 +
102 +## 阶段 4:用户故事 2 - [标题](优先级:P2)
103 +
104 +**目标**[简述该故事交付内容]
105 +
106 +**独立验证**[如何单独验证该故事可用]
107 +
108 +### 用户故事 2 的测试(可选:仅在明确要求测试时)⚠️
109 +
110 +- [ ] T018 [P] [US2][endpoint] 编写契约测试:tests/contract/test_[name].py
111 +- [ ] T019 [P] [US2][用户旅程] 编写集成测试:tests/integration/test_[name].py
112 +
113 +### 用户故事 2 的实现
114 +
115 +- [ ] T020 [P] [US2] 创建 [Entity] 模型:src/models/[entity].py
116 +- [ ] T021 [US2] 实现 [Service]:src/services/[service].py
117 +- [ ] T022 [US2] 实现 [endpoint/feature]:src/[location]/[file].py
118 +- [ ] T023 [US2] 与用户故事 1 的组件集成(如需要)
119 +
120 +**检查点**:此时用户故事 1 和 2 应都能独立工作
121 +
122 +---
123 +
124 +## 阶段 5:用户故事 3 - [标题](优先级:P3)
125 +
126 +**目标**[简述该故事交付内容]
127 +
128 +**独立验证**[如何单独验证该故事可用]
129 +
130 +### 用户故事 3 的测试(可选:仅在明确要求测试时)⚠️
131 +
132 +- [ ] T024 [P] [US3][endpoint] 编写契约测试:tests/contract/test_[name].py
133 +- [ ] T025 [P] [US3][用户旅程] 编写集成测试:tests/integration/test_[name].py
134 +
135 +### 用户故事 3 的实现
136 +
137 +- [ ] T026 [P] [US3] 创建 [Entity] 模型:src/models/[entity].py
138 +- [ ] T027 [US3] 实现 [Service]:src/services/[service].py
139 +- [ ] T028 [US3] 实现 [endpoint/feature]:src/[location]/[file].py
140 +
141 +**检查点**:此时所有用户故事都应可独立运行
142 +
143 +---
144 +
145 +[如需要,可按同样格式继续添加更多用户故事阶段]
146 +
147 +---
148 +
149 +## 阶段 N:打磨与横切关注点
150 +
151 +**目标**:影响多个用户故事的改进项
152 +
153 +- [ ] TXXX [P] 更新 docs/ 内的文档
154 +- [ ] TXXX 代码清理与重构
155 +- [ ] TXXX 跨故事的性能优化
156 +- [ ] TXXX [P] 在 tests/unit/ 增加单测(如需)
157 +- [ ] TXXX 安全加固
158 +- [ ] TXXX 验证 quickstart.md
159 +
160 +---
161 +
162 +## 依赖与执行顺序
163 +
164 +### 阶段依赖
165 +
166 +- **准备(阶段 1)**:无依赖,可立即开始
167 +- **基础(阶段 2)**:依赖准备阶段完成——阻塞所有用户故事
168 +- **用户故事(阶段 3+)**:均依赖基础阶段完成
169 + - 之后可并行推进(若有人力)
170 + - 或按优先级串行推进(P1 → P2 → P3)
171 +- **打磨(最终阶段)**:依赖所有目标用户故事完成
172 +
173 +### 用户故事依赖
174 +
175 +- **用户故事 1(P1)**:基础阶段后可开始——不依赖其他故事
176 +- **用户故事 2(P2)**:基础阶段后可开始——可能与 US1 集成,但应保持可独立验证
177 +- **用户故事 3(P3)**:基础阶段后可开始——可能与 US1/US2 集成,但应保持可独立验证
178 +
179 +### 每个用户故事内部顺序
180 +
181 +- 测试(如包含)必须先写,且在实现前应失败
182 +- 先模型,再服务
183 +- 先服务,再接口/端点
184 +- 先核心实现,再集成
185 +- 完成当前故事后再进入下一个优先级
186 +
187 +### 并行机会
188 +
189 +- 阶段 1 中标记 [P] 的任务可并行
190 +- 阶段 2 中标记 [P] 的任务可并行(在阶段 2 内)
191 +- 基础阶段完成后,所有用户故事可并行开始(若团队容量允许)
192 +- 用户故事内标记 [P] 的测试可并行
193 +- 用户故事内标记 [P] 的模型可并行
194 +- 不同用户故事可由不同成员并行推进
195 +
196 +---
197 +
198 +## 并行示例:用户故事 1
199 +
200 +```bash
201 +# 一次性启动用户故事 1 的所有测试(如需要测试):
202 +任务: "为 [endpoint] 编写契约测试:tests/contract/test_[name].py"
203 +任务: "为 [用户旅程] 编写集成测试:tests/integration/test_[name].py"
204 +
205 +# 一次性启动用户故事 1 的所有模型任务:
206 +任务: "创建 [Entity1] 模型:src/models/[entity1].py"
207 +任务: "创建 [Entity2] 模型:src/models/[entity2].py"
208 +```
209 +
210 +---
211 +
212 +## 实施策略
213 +
214 +### MVP 优先(仅用户故事 1)
215 +
216 +1. 完成阶段 1:准备
217 +2. 完成阶段 2:基础(关键:阻塞所有故事)
218 +3. 完成阶段 3:用户故事 1
219 +4. **停止并验证**:独立验证用户故事 1
220 +5. 如已就绪则部署/演示
221 +
222 +### 增量交付
223 +
224 +1. 完成准备 + 基础 → 基础设施就绪
225 +2. 增加用户故事 1 → 独立验证 → 部署/演示(MVP)
226 +3. 增加用户故事 2 → 独立验证 → 部署/演示
227 +4. 增加用户故事 3 → 独立验证 → 部署/演示
228 +5. 每个故事都应在不破坏既有能力的前提下增量交付价值
229 +
230 +### 多人并行策略
231 +
232 +多人协作时:
233 +
234 +1. 团队协作完成准备 + 基础
235 +2. 基础完成后:
236 + - 开发 A:用户故事 1
237 + - 开发 B:用户故事 2
238 + - 开发 C:用户故事 3
239 +3. 各故事独立完成并独立集成
240 +
241 +---
242 +
243 +## 备注
244 +
245 +- [P] 任务:不同文件、无依赖,可并行
246 +- [Story] 标签:将任务映射到具体用户故事,便于追溯
247 +- 每个用户故事都应可独立完成与独立验证
248 +- 实现前先确认测试会失败(如有测试)
249 +- 每完成一个任务或合理的任务组再提交
250 +- 在任意检查点都可以停下来做独立验证
251 +- 避免:任务描述模糊、同文件冲突、跨故事强耦合导致无法独立交付