@chenguangyao/devflow-kit 0.1.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/CHANGELOG.md +232 -0
  2. package/LICENSE +21 -0
  3. package/README.md +539 -0
  4. package/bin/devflow.js +9 -0
  5. package/docs/RFC-001-devflow-kit.md +617 -0
  6. package/docs/RFC-002-workflow-kernel.md +134 -0
  7. package/docs/enterprise-integration-supplement.md +274 -0
  8. package/docs/internal-gitlab-setup.md +426 -0
  9. package/docs/marketplace-skills.md +231 -0
  10. package/docs/migration-from-arb.md +232 -0
  11. package/docs/tooling-overview.md +774 -0
  12. package/docs/workflow-orchestration.md +695 -0
  13. package/docs/workflow-ui-prototype.html +271 -0
  14. package/package.json +52 -0
  15. package/schemas/config.schema.json +51 -0
  16. package/schemas/delta.schema.json +22 -0
  17. package/schemas/state.schema.json +130 -0
  18. package/schemas/status-surface.schema.json +197 -0
  19. package/schemas/workflow-confirmation-surface.schema.json +70 -0
  20. package/schemas/workflow-picker.schema.json +94 -0
  21. package/scripts/postinstall.js +101 -0
  22. package/scripts/render-workflow-ui-prototype.js +271 -0
  23. package/skills/apply/SKILL.md +313 -0
  24. package/skills/apply/references/discipline-checklist.md +145 -0
  25. package/skills/apply/references/subagent-implementer-prompt.md +113 -0
  26. package/skills/apply/references/subagent-orchestration.md +150 -0
  27. package/skills/apply/references/subagent-reviewer-prompt.md +180 -0
  28. package/skills/apply/references/tdd-loop.md +287 -0
  29. package/skills/apply/references/when-plan-is-wrong.md +279 -0
  30. package/skills/apply/references/worktree-swarm.md +292 -0
  31. package/skills/archive/SKILL.md +229 -0
  32. package/skills/archive/references/conflict-resolution.md +336 -0
  33. package/skills/archive/references/knowledge-deposit.md +381 -0
  34. package/skills/archive/references/spec-merge.md +365 -0
  35. package/skills/brainstorm/SKILL.md +123 -0
  36. package/skills/brainstorm/references/proposal-template.md +244 -0
  37. package/skills/brainstorm/references/question-catalog.md +168 -0
  38. package/skills/brainstorm/references/session-template.md +184 -0
  39. package/skills/ci-fix/SKILL.md +63 -0
  40. package/skills/ci-fix/references/loop.md +25 -0
  41. package/skills/code-review/SKILL.md +279 -0
  42. package/skills/code-review/references/escalation-playbook.md +192 -0
  43. package/skills/code-review/references/language-cheatsheets/go.md +175 -0
  44. package/skills/code-review/references/language-cheatsheets/java-spring-mybatis.md +246 -0
  45. package/skills/code-review/references/language-cheatsheets/python.md +170 -0
  46. package/skills/code-review/references/language-cheatsheets/vue.md +199 -0
  47. package/skills/code-review/references/output-template.md +275 -0
  48. package/skills/code-review/references/review-checklist.md +251 -0
  49. package/skills/complexity-grading/SKILL.md +259 -0
  50. package/skills/deliver/SKILL.md +271 -0
  51. package/skills/deliver/references/delivery-modes.md +299 -0
  52. package/skills/deliver/references/notify.md +359 -0
  53. package/skills/deliver/references/pr-description.md +319 -0
  54. package/skills/dependency-upgrade/SKILL.md +57 -0
  55. package/skills/dependency-upgrade/references/risk-matrix.md +38 -0
  56. package/skills/df-orchestrator/SKILL.md +407 -0
  57. package/skills/df-orchestrator/references/complexity-grading.md +177 -0
  58. package/skills/df-orchestrator/references/escalation-matrix.md +191 -0
  59. package/skills/df-orchestrator/references/routing-rules.md +290 -0
  60. package/skills/df-orchestrator/references/workflow-state-machine.md +208 -0
  61. package/skills/frontend-quality/SKILL.md +61 -0
  62. package/skills/frontend-quality/references/checklist.md +35 -0
  63. package/skills/handoff-resume/SKILL.md +59 -0
  64. package/skills/handoff-resume/references/handoff-template.md +54 -0
  65. package/skills/plan/SKILL.md +166 -0
  66. package/skills/plan/references/task-breakdown.md +207 -0
  67. package/skills/plan/references/task-sequencing.md +143 -0
  68. package/skills/plan/references/task-template.md +248 -0
  69. package/skills/requirement-analysis/SKILL.md +499 -0
  70. package/skills/requirement-analysis/references/acceptance-criteria.md +183 -0
  71. package/skills/requirement-analysis/references/code-recon.md +151 -0
  72. package/skills/requirement-analysis/references/edge-case-catalog.md +164 -0
  73. package/skills/requirement-analysis/references/requirement-template.md +339 -0
  74. package/skills/requirement-analysis/references/scope-negotiation.md +162 -0
  75. package/skills/security-hardening/SKILL.md +60 -0
  76. package/skills/security-hardening/references/checklist.md +42 -0
  77. package/skills/tech-spec/SKILL.md +388 -0
  78. package/skills/tech-spec/references/api-contract-design.md +172 -0
  79. package/skills/tech-spec/references/decision-records.md +110 -0
  80. package/skills/tech-spec/references/design-template.md +301 -0
  81. package/skills/tech-spec/references/rollout-and-rollback.md +203 -0
  82. package/skills/tech-spec/references/spec-delta-conventions.md +250 -0
  83. package/skills/tech-spec/references/transaction-patterns.md +212 -0
  84. package/skills/test-spec/SKILL.md +219 -0
  85. package/skills/test-spec/references/coverage-strategy.md +218 -0
  86. package/skills/test-spec/references/edge-case-to-test.md +143 -0
  87. package/skills/test-spec/references/test-case-template.md +276 -0
  88. package/skills/verify/SKILL.md +232 -0
  89. package/skills/verify/references/nfr-verification.md +292 -0
  90. package/skills/verify/references/report-templates.md +510 -0
  91. package/skills/verify/references/self-test-guide.md +240 -0
  92. package/skills/verify/references/verify-rollback-map.md +247 -0
  93. package/src/cli/commands/_helpers.js +108 -0
  94. package/src/cli/commands/_submit.js +718 -0
  95. package/src/cli/commands/apply.js +198 -0
  96. package/src/cli/commands/archive.js +180 -0
  97. package/src/cli/commands/checkpoint.js +113 -0
  98. package/src/cli/commands/deliver.js +377 -0
  99. package/src/cli/commands/deploy.js +504 -0
  100. package/src/cli/commands/design.js +158 -0
  101. package/src/cli/commands/disable.js +21 -0
  102. package/src/cli/commands/doctor.js +178 -0
  103. package/src/cli/commands/enable.js +21 -0
  104. package/src/cli/commands/flow.js +645 -0
  105. package/src/cli/commands/help.js +93 -0
  106. package/src/cli/commands/ingest.js +602 -0
  107. package/src/cli/commands/init.js +341 -0
  108. package/src/cli/commands/knowledge.js +523 -0
  109. package/src/cli/commands/logs.js +43 -0
  110. package/src/cli/commands/new.js +202 -0
  111. package/src/cli/commands/plan.js +49 -0
  112. package/src/cli/commands/propose.js +27 -0
  113. package/src/cli/commands/provider.js +698 -0
  114. package/src/cli/commands/report.js +143 -0
  115. package/src/cli/commands/requirement.js +227 -0
  116. package/src/cli/commands/review.js +301 -0
  117. package/src/cli/commands/skills.js +457 -0
  118. package/src/cli/commands/status.js +925 -0
  119. package/src/cli/commands/switch.js +27 -0
  120. package/src/cli/commands/sync.js +47 -0
  121. package/src/cli/commands/test.js +366 -0
  122. package/src/cli/commands/uninstall.js +32 -0
  123. package/src/cli/commands/update.js +74 -0
  124. package/src/cli/commands/verify.js +354 -0
  125. package/src/cli/commands/worktree.js +78 -0
  126. package/src/cli/index.js +72 -0
  127. package/src/cli/parse-args.js +102 -0
  128. package/src/core/autodetect.js +271 -0
  129. package/src/core/change.js +208 -0
  130. package/src/core/checkpoint.js +217 -0
  131. package/src/core/config.js +60 -0
  132. package/src/core/delta.js +290 -0
  133. package/src/core/markers.js +59 -0
  134. package/src/core/paths.js +173 -0
  135. package/src/core/plan-tasks.js +36 -0
  136. package/src/core/project-routing.js +285 -0
  137. package/src/core/projects.js +200 -0
  138. package/src/core/state.js +200 -0
  139. package/src/core/workflow-check.js +177 -0
  140. package/src/core/workflow-init.js +34 -0
  141. package/src/core/workflow-picker.js +154 -0
  142. package/src/core/workflow-policy.js +119 -0
  143. package/src/core/workflow-suggest.js +181 -0
  144. package/src/core/workflow-verify.js +88 -0
  145. package/src/core/workflow.js +433 -0
  146. package/src/core/worktree.js +241 -0
  147. package/src/knowledge/categories.js +107 -0
  148. package/src/knowledge/classify.js +125 -0
  149. package/src/knowledge/deposit.js +414 -0
  150. package/src/knowledge/migrate.js +149 -0
  151. package/src/knowledge/mr.js +219 -0
  152. package/src/knowledge/query.js +131 -0
  153. package/src/knowledge/registry.js +151 -0
  154. package/src/knowledge/sync.js +179 -0
  155. package/src/providers/base.js +74 -0
  156. package/src/providers/drivers/api-yapi.js +78 -0
  157. package/src/providers/drivers/ci-jenkins.js +109 -0
  158. package/src/providers/drivers/intake-confluence.js +544 -0
  159. package/src/providers/drivers/kb-git.js +549 -0
  160. package/src/providers/drivers/kb-weknora.js +472 -0
  161. package/src/providers/drivers/notify-smtp.js +515 -0
  162. package/src/providers/drivers/observability-oss.js +43 -0
  163. package/src/providers/drivers/observability-sls.js +50 -0
  164. package/src/providers/lifecycle.js +135 -0
  165. package/src/providers/loader.js +132 -0
  166. package/src/providers/local.js +190 -0
  167. package/src/providers/userconfig.js +283 -0
  168. package/src/reports/aggregate.js +185 -0
  169. package/src/reports/coverage.js +163 -0
  170. package/src/reports/detect.js +143 -0
  171. package/src/reports/parse.js +236 -0
  172. package/src/templates/files/ci/github.yml +38 -0
  173. package/src/templates/files/ci/gitlab.yml +27 -0
  174. package/src/templates/files/design.md +63 -0
  175. package/src/templates/files/ide/devflow-workflow.md +58 -0
  176. package/src/templates/files/ide/project-overview-reference.md +1 -0
  177. package/src/templates/files/ide/project-overview.md +27 -0
  178. package/src/templates/files/knowledge-index.json +17 -0
  179. package/src/templates/files/knowledge.md +28 -0
  180. package/src/templates/files/meta.json +8 -0
  181. package/src/templates/files/plan.md +38 -0
  182. package/src/templates/files/proposal.md +33 -0
  183. package/src/templates/files/reports/contract-test.md +40 -0
  184. package/src/templates/files/reports/e2e-test.md +30 -0
  185. package/src/templates/files/reports/integration-test.md +36 -0
  186. package/src/templates/files/reports/joint-test.md +58 -0
  187. package/src/templates/files/reports/perf.md +24 -0
  188. package/src/templates/files/reports/regression.md +20 -0
  189. package/src/templates/files/reports/remote-test.md +55 -0
  190. package/src/templates/files/reports/self-test.md +43 -0
  191. package/src/templates/files/reports/smoke-test.md +22 -0
  192. package/src/templates/files/reports/unit-test.md +36 -0
  193. package/src/templates/files/requirement.md +51 -0
  194. package/src/templates/files/review.md +38 -0
  195. package/src/templates/files/tests.md +36 -0
  196. package/src/templates/files/verify.md +32 -0
  197. package/src/templates/index.js +21 -0
  198. package/src/utils/log.js +37 -0
@@ -0,0 +1,499 @@
1
+ ---
2
+ name: devflow-requirement-analysis
3
+ description: |
4
+ devflow-kit requirement 阶段把 `proposal.md`(brainstorm 产出)或 `refs/*.md`(ingest 产出)加工成结构化的 `requirement.md`
5
+ —— 所有后续 phase 都以它为契约。触发时机:`devflow ingest` 或 `devflow new + brainstorm` 完成后,或
6
+ 用户说"帮我分析需求"、"把这个 PRD 结构化一下"、"这个 issue 要我们做什么"。三步澄清:
7
+ **Step 0** KB 预检索(读缓存)→ **Round 1(业务侧)** ⛔卡点1,不碰代码先钉死业务契约 →
8
+ **项目路由确认**(多项目目录下先选定涉及项目) → **代码侦察**(Round 1 确认后,深度按 level 缩放) → **Round 2(实现侧)** ⛔卡点2(智能触发,
9
+ 无冲突跳过)。L1 只做 KB 查+快扫,跳 Round 1/2。
10
+ when_to_use: |
11
+ `devflow requirement` 或 `/df:requirement` 触发。必须在 `design` / `plan` 之前完成。
12
+ ---
13
+
14
+ # requirement-analysis
15
+
16
+ 目标:**把需求钉成 契约**。下游 tech-spec / test-spec / code-review / verify 全部以 `requirement.md` 为单一真相源。如果这份文档含糊,整条流水线都会飘。
17
+
18
+ ## 前置检查
19
+
20
+ | 输入 | 必需 | 缺失时 |
21
+ | --- | --- | --- |
22
+ | `devflow/changes/<slug>/proposal.md`(brainstorm 路径) 或 `refs/source.md`(ingest 路径) | **必一** | orchestrator 回退;不能两手空空做需求分析 |
23
+ | `state.level` | 是 | 缺则默认 L2 + 提示用户 |
24
+ | `state.problemCardConfirmedAt` | 是 | 回到 complexity-grading 补确认问题卡,不能继续 Round 1 / Round 2 |
25
+ | `state.projectConfirmationAt` | L2/L3 必须 | 回到 complexity-grading 补确认涉及项目;若用户明确 `项目=none`,需在 state 记录后再继续 |
26
+ | `devflow/config.json.detect.language / .project` | 否(有更佳) | 影响 Round 2 代码侦察命令 |
27
+
28
+ **旧状态兜底**:如果 `state.level` 已存在但缺少 `problemCardConfirmedAt` 或 `projectConfirmationAt`,这是旧版流程已经写入 level 但没有展示问题卡/项目确认。此时必须停止 requirement-analysis,回到 complexity-grading 补确认,输出一张"问题卡 + 涉及项目 + 当前 level"的简版确认卡;用户确认后再恢复 requirement。不要因为已有 `requirement.md` 或用户回复"继续"就直接做代码侦察。
29
+
30
+ **禁止补写确认字段(硬约束)**:
31
+
32
+ - requirement-analysis 不能代替 complexity-grading 完成问题卡确认。
33
+ - 发现缺少或可疑的 `problemCardConfirmedAt` / `projectConfirmationAt` 时,禁止修改 `requirement.md`,禁止进入 Round 1 / Round 2,禁止标记"level confirmed"或"project routing confirmed"。
34
+ - 禁止写入 `problemCardConfirmedAt`,也禁止写入 `projectConfirmationAt`;只能返回 NEEDS_INPUT,并指示 orchestrator 路由回 complexity-grading。
35
+ - 用户回复"继续"不等于问题卡确认,除非上一条回复正文已经由 complexity-grading 展示了问题卡和涉及项目确认。
36
+
37
+ ## 产物
38
+
39
+ 编辑 `devflow/changes/<slug>/requirement.md`,强制 9 个 section(L1 的 6、7 可跳):
40
+
41
+ | # | Section | L1 | L2 | L3 |
42
+ | --- | --- | --- | --- | --- |
43
+ | 1 | 业务背景(Business background) | 必 | 必 | 必 |
44
+ | 2 | 用户故事(User stories) | 必 | 必 | 必 |
45
+ | 3 | 功能需求(Functional requirements, 带 F-ID + AC) | 必 | 必 | 必 |
46
+ | 4 | 非功能需求(Non-functional:perf / security / observability / availability) | 简 | 必 | 必(含 SLO) |
47
+ | 5 | 数据 / 接口影响(DDL / 契约 / 事件) | 必 | 必 | 必 |
48
+ | 6 | Round 1 Q&A(业务侧) | 可选 | 必 | 必 |
49
+ | 7 | 项目路由确认(Project routing) | 可选 | 必 | 必 |
50
+ | 8 | Round 2 Q&A(实现侧) | 跳 | 必 | 必 |
51
+ | 9 | 边界与异常(Edge cases) | 必 | 必 | 必 |
52
+ | 10 | 风险与遗留(Risks & Open issues) | 必 | 必 | 必 |
53
+
54
+ 完整模板与正反例见 [`references/requirement-template.md`](references/requirement-template.md)。
55
+
56
+ ## Step 0:读取知识库背景(在 Round 1 之前)
57
+
58
+ > KB 预检索已在 ingest 阶段完成(`refs/kb-context.md`),这里直接读缓存,**不重复查询**。
59
+
60
+ ```bash
61
+ # 优先读 ingest 阶段写下的缓存
62
+ cat devflow/changes/<slug>/refs/kb-context.md # 有则读,无则跳到补查
63
+
64
+ # 若 kb-context.md 不存在(brainstorm 路径进来 / 手动发起),才补查一次
65
+ devflow knowledge query "<从 proposal.md 提取的核心关键词>" --slug=<slug>
66
+ ```
67
+
68
+ **读取结果处理:**
69
+ - **有命中**:提取与本次需求相关的边界条件 / 历史决策 / 已知坑点,在 Round 1 澄清时主动引用("过去类似功能做了 X 选择,本次是否沿用?")
70
+ - **无命中**:正常继续,Round 1 从零开始
71
+ - 命中摘要附在 `requirement.md` Section 9(Risks & Open issues)中列为"历史参考"
72
+
73
+ ## 三步澄清协议(核心方法论)
74
+
75
+ ```
76
+ Round 1 业务澄清 → ⛔ 卡点 1(用户确认后) → 项目路由确认 → Step 代码侦察 → Round 2 实现澄清 → ⛔ 卡点 2(智能触发)
77
+ ```
78
+
79
+ ### Round 1 — 业务澄清(**不碰代码**)⛔ 卡点 1
80
+
81
+ **目的**:钉死**业务契约**,确保"做什么、为谁做、怎样算做完"清楚。**必须等用户确认后才做代码侦察。**
82
+
83
+ **动作**:
84
+
85
+ 1. 读 `proposal.md` / `refs/*.md`,逐段过一遍(结合 Step 0 的 KB 命中内容)
86
+ 2. 列出**所有影响 scope 或 AC 的歧义**(不要列"实现细节"类歧义)
87
+ 3. **一次性输出本轮全部业务侧问题**,形成"业务澄清卡";不要只抛 Q1 等用户回答后再问 Q2
88
+ 4. 每个问题必须带`来源`和`影响`,可附推荐默认值 / 可选项,方便用户批量回答
89
+ 5. 最多 8 个问题;超过 8 个先合并同类项,仍超过则说明需求源材料太糟,要求补材料或重走 ingest
90
+
91
+ **输出格式**:
92
+
93
+ ```markdown
94
+ ## 业务层理解(Round 1)
95
+
96
+ ### 我的理解
97
+ [反向复述需求核心目标和功能点]
98
+
99
+ ### 涉及范围
100
+ - 业务领域:[xxx]
101
+ - 系统模块:[xxx]
102
+ - 外部依赖:[xxx]
103
+
104
+ ### 业务层待确认事项
105
+ | 序号 | 问题 | 来源 | 影响 |
106
+ |------|------|------|------|
107
+ | Q1 | ... | ... | ... |
108
+ | Q2 | ... | ... | ... |
109
+
110
+ 请一次性确认以上理解并批量回答问题后继续:
111
+ - "全部无疑问" / "OK" → 按表中默认理解进入代码侦察
112
+ - "Q1=A;Q2=xxx;Q3 按推荐" → 按指定处理
113
+ - "Q4 不确定,找产品确认" → 记为 Open issue;若是 P0,则停在 Round 1
114
+ ```
115
+
116
+ **P0 歧义必问**(这些不搞清楚,后面会翻车):
117
+
118
+ - 验收标准里的**数字**(响应 < 3s 是 P99 还是 P50?QPS 峰值多少?)
119
+ - **角色边界**(运营能做什么、用户能做什么、管理员能做什么)
120
+ - **跨系统接口**(外部系统提供谁?什么时候 ready?)
121
+ - **合规边界**(个人数据使用范围?留存多久?)
122
+ - **灰度 / 回滚**(L3 必问:怎么灰度?怎么回滚?)
123
+
124
+ **验收门禁**:Round 1 澄清卡已一次性发出,所有 P0 问题解答 + 用户明确确认后,进入代码侦察。L0 跳过代码侦察直接进 plan。
125
+
126
+ ---
127
+
128
+ ### 项目路由确认(Round 1 后,代码侦察前)⛔ 多项目硬闸
129
+
130
+ **目的**:在一个大目录包含多个项目时,先确认本次需求涉及哪些项目,避免 agent 在错误项目里读代码或改代码。
131
+
132
+ **CLI 入口**:
133
+
134
+ ```bash
135
+ # 用户已明确指定项目时:优先在入口命令前置选择项目;
136
+ # primary 项目的 git branch 会参与 change slug 生成,并写入 state.projects
137
+ devflow ingest <wiki-or-prd> --project-root=/path/to/project-a,/path/to/project-b
138
+ devflow new <slug> --project-root=/path/to/project-a,/path/to/project-b
139
+
140
+ # change 已创建后需要补选/覆盖项目时:
141
+ devflow requirement --project-root=/path/to/project-a,/path/to/project-b
142
+
143
+ # 用户只指定了大目录时:自动发现并推荐候选项目
144
+ devflow requirement --search-root=/path/to/big/code/root
145
+ ```
146
+
147
+ `devflow new/ingest --project-root` 会在创建 change 前确认项目,使用第一个项目(`primary`)的 git branch 生成 `<branch>-<slug>`,并写入 `state.projects`。`devflow requirement` 如果发现 state 已有项目且没有传新的路由参数,会复用现有选择;否则会自动发现候选项目(`pom.xml` / `build.gradle` / `go.mod` / `package.json` / `devflow/config.json` / `.git`),按 proposal/refs/requirement 关键词评分,并写入:
148
+
149
+ - `state.projectRouting`:候选项目、命中证据、搜索根
150
+ - `state.projects`:推荐选中的项目 root,后续阶段只围绕这些 root 展开
151
+ - `project-roots.json`:当前 change 的项目路径清单,后续阶段必须优先读取;多个项目不在同一个父目录时,不再依赖当前 shell 所在目录猜项目
152
+ - `requirement.md#项目路由确认`:给用户确认和手动修正
153
+
154
+ **规则**:
155
+
156
+ - 用户已明确给出项目路径时,必须使用 `--project-root`,禁止再从大目录自动猜。
157
+ - 新 change 优先在 `devflow new/ingest` 阶段传 `--project-root`,因为 change slug 需要依赖 primary 项目的 git branch。
158
+ - 不引入 workspace ID;真正执行依据是项目 `root` 绝对路径。
159
+ - 多项目散落在不同目录时,第一次确认后必须依赖 `project-roots.json` / `state.json#projects`;后续代码侦察只扫这些 root。
160
+ - L2/L3 进入代码侦察前必须确认 `state.projects`。
161
+ - 支持多选:`primary` 表示主改项目,`dependency` 表示可能涉及的公共库/依赖项目。
162
+ - 推荐不准确时,先手动修正 `requirement.md#项目路由确认` 和 `state.json#projects`,再做 Round 2。
163
+
164
+ ---
165
+
166
+ ### 代码侦察(Round 1 确认后执行,**深度按 level 缩放**)
167
+
168
+ **目的**:基于 Round 1 确认后的业务理解和已确认的 `state.projects`,精准扫描代码,找出现有实现、潜在冲突和复用机会。
169
+
170
+ **深度规则(按 state.level):**
171
+
172
+ | Level | 侦察深度 | 具体操作 |
173
+ | --- | --- | --- |
174
+ | **L0** | 跳过 | 不做侦察 |
175
+ | **L1** | 快扫(≤5 分钟) | 只找 1-2 个入口文件;确认改动落点即可;不追调用链 |
176
+ | **L2** | 主干链路(≤15 分钟) | 找入口 → 服务层 → 数据层;扫相关 Controller/Service/Repository;读主干函数 |
177
+ | **L3** | 全链路(≤30 分钟) | L2 + 跨服务调用、事件发布/消费、定时任务、迁移脚本;检查分布式事务 / 锁 |
178
+
179
+ ### 契约消费者影响侦察(L2/L3 硬闸)
180
+
181
+ > **HARD RULE**:只要本次需求改变任意对外/跨项目契约,就不能只侦察提供方。必须追踪消费者,否则会漏掉前端页、轮询页、回跳页、网关、任务中心等依赖。
182
+
183
+ 契约变化包括但不限于:
184
+
185
+ - URL / `returnUrl` / redirect / callback 参数增删改(例如旧回跳 URL 带订单号,新接入不带参数)
186
+ - Request / Response 字段、枚举、错误码、状态机语义变化
187
+ - 签约码、订单号、渠道字段、支付渠道、第三方流水号等跨系统传递字段变化
188
+ - 轮询页 / 结果页 / H5 / 小程序 / 管理后台依赖的 query、localStorage、缓存 key、接口返回字段变化
189
+
190
+ 侦察动作必须补充:
191
+
192
+ ```bash
193
+ rg "returnUrl|callback|redirect|orderNo|contractNo|signNo|pay_channel|bf|jd|poll|轮询|签约|支付结果" <confirmed-project-roots>
194
+ rg "URLSearchParams|location.search|route.query|query\\.|localStorage|sessionStorage" <frontend-project-roots>
195
+ rg "<接口路径>|<response字段>|<枚举值>" <all-related-project-roots>
196
+ ```
197
+
198
+ 如果发现消费者不在当前 `state.projects` 内,必须在 `requirement.md#项目路由确认` 标注"疑似新增受影响项目",并回到项目确认/complexity-grading 补确认;不能假装只改后端。
199
+
200
+ **侦察动作(L1 只做前两行,L2/L3 全做)**:
201
+
202
+ ```
203
+ Grep "Class名 / 接口名 / 路径" # 找现有实现 & 契约
204
+ Glob "**/*Controller.{java,go}" # 找相关入口
205
+ Read <入口文件> # 读主干逻辑
206
+ # L2/L3 额外:
207
+ Grep "事件名 / 消息 Topic" # 找异步链路
208
+ Grep "import.*<依赖服务>" # 找跨服务调用点
209
+ Read <数据层文件> # 确认 DDL 影响范围
210
+ ```
211
+
212
+ **侦察报告格式**(不写文件,作为 Round 2 的输入):
213
+
214
+ ```markdown
215
+ ## 代码侦察报告
216
+
217
+ ### 扫描范围
218
+ - 服务:{service-list}
219
+ - 关键词:{keywords}
220
+
221
+ ### 已有相关实现
222
+ | 类别 | 位置 | 说明 |
223
+ |------|------|------|
224
+ | 接口 | {file}:{line} {method} | {业务含义} |
225
+ | 数据模型 | {file} {entity} | {字段清单} |
226
+ | 业务流程 | {entry} → ... → {end} | {流程描述} |
227
+
228
+ ### 潜在冲突
229
+ | 序号 | 冲突类型 | 位置 | 说明 |
230
+ |------|---------|------|------|
231
+
232
+ ### 契约消费者影响
233
+ | 契约变化 | 消费者/页面/任务 | 位置 | 影响 | 是否纳入本次 |
234
+ |------|------|------|------|------|
235
+ | returnUrl 不再带订单号 | 前端签约轮询页 | `src/pages/...` | 不能从 query 取订单号,需要改为本地缓存或后端查询 | 是/否 |
236
+
237
+ ### 复用机会
238
+ | 序号 | 位置 | 说明 |
239
+ |------|------|------|
240
+ ```
241
+
242
+ 把侦察结论同步写进 `requirement.md` 的 `## 5. 数据/接口影响`(preliminary)。
243
+
244
+ ---
245
+
246
+ ### Round 2 — 实现澄清(**智能触发**)⛔ 卡点 2
247
+
248
+ **触发规则**:
249
+
250
+ ```
251
+ IF 代码侦察发现以下任一:
252
+ - 潜在冲突(接口/字段/流程/命名冲突)
253
+ - 需要人工决策的复用机会
254
+ - P0 踩坑点提示
255
+ THEN 触发 Round 2 卡点
256
+
257
+ ELSE 无冲突 → 跳过 Round 2,直接进入结构化提取
258
+ 输出一行:"代码侦察无冲突,直接进入结构化提取"
259
+ ```
260
+
261
+ **目的**:只问**代码侦察无法自己回答**的那一小部分决策,不打扰用户问他也不知道的细节。
262
+
263
+ **输出格式**:
264
+
265
+ ```markdown
266
+ ## 实现层待确认事项(Round 2)
267
+
268
+ | 序号 | 问题 | 代码位置 | 可选方案 | 推荐 |
269
+ |------|------|---------|---------|------|
270
+ | D1 | ... | ... | A.xxx / B.xxx | A |
271
+
272
+ 请回复:
273
+ - "全部按推荐" → 接受所有推荐方案
274
+ - "D1:B D2:A" → 逐条指定
275
+ ```
276
+
277
+ **可能的追问**(只问这些类型):
278
+
279
+ - "XxxService 已有两个实现(A/B),我们扩哪一个?"
280
+ - "字段 Y 的 NOT NULL 约束是否保留?"
281
+ - "已有一个 `coupon.grant` 事件,是否复用它做批量?"
282
+ - "关键流程里有个 retry 3 次的循环,这次要不要改成可配置?"
283
+
284
+ 侦察方法论与追问触发条件见 [`references/code-recon.md`](references/code-recon.md)。
285
+
286
+ ### L1 简化路径
287
+
288
+ - Round 1 可只问 1-3 个 P0 歧义
289
+ - L1 的 1-3 个问题也必须一次性列出,不要拆成逐题对话
290
+ - 代码侦察只做**快扫**(找改动落点,≤5 分钟),侦察结论写进 section 5
291
+ - Round 2 跳过
292
+
293
+ ## 功能需求表(F-ID + 可验收)
294
+
295
+ **硬约束**:每条功能需求必须有唯一 **F-ID**(F-01, F-02, ...)+ 至少 1 条**可验收**的 AC。
296
+
297
+ 完整的 AC 规范、INVEST / Given-When-Then 模板、边界场景挖掘方法见 [`references/acceptance-criteria.md`](references/acceptance-criteria.md)。
298
+
299
+ ### 好的 AC vs 差的 AC
300
+
301
+ | 差(打回) | 好(可过) |
302
+ | --- | --- |
303
+ | "批量发放要支持批量" | "批量发放单次支持 1-1000 个用户,超过返回 400 + 错误码 BATCH_TOO_LARGE" |
304
+ | "性能要好" | "P99 ≤ 3s,1000 人批量场景下" |
305
+ | "风控要一致" | "批量发放的每一条走同一路径的风控规则,对被拦截的用户返回 hitCode + userId,成功率 ≥ 99.9%" |
306
+
307
+ ## 边界场景挖掘(Edge cases)
308
+
309
+ 需求里最容易漏的地方。要主动挖掘:
310
+
311
+ | 维度 | 问自己 |
312
+ | --- | --- |
313
+ | **空 / 0 / null** | 传空列表怎样?用户为 null 怎样? |
314
+ | **极大 / 极小** | 1001 个人呢?0 个人呢?负数? |
315
+ | **重复 / 幂等** | 同一批发 2 次怎样? |
316
+ | **并发 / 竞态** | 同时两个运营同传批次? |
317
+ | **部分失败** | 1000 人里 10 人被风控拦截,返回成功还是失败? |
318
+ | **权限 / 越权** | 普通运营能发全国用户吗? |
319
+ | **数据一致性** | 部分成功时怎么记账?重试怎么去重? |
320
+ | **跨时区 / locale** | 过期时间是服务器时区还是用户时区? |
321
+
322
+ 边界场景完整 catalog(按功能域分类)见 [`references/edge-case-catalog.md`](references/edge-case-catalog.md)。
323
+
324
+ ## Scope 谈判(用户要加太多 / 想删减)
325
+
326
+ 用户说"再加一个能不能?" → 你要判断:
327
+
328
+ - 这个加进来还在 proposal 的 Problem 范围内吗?
329
+ - 是 → 加进 F-N,更新 Recommended level(可能升级)
330
+ - 否 → 拒绝加入本次 requirement,建议另开 slug
331
+ - 这个加进来,原 AC 还能满足吗?
332
+ - 否 → 提醒用户权衡
333
+
334
+ 用户说"这个能不能下次做?" → 移到 **Out of scope** 并在 `risks & open issues` 记理由。
335
+
336
+ 谈判话术与决策树见 [`references/scope-negotiation.md`](references/scope-negotiation.md)。
337
+
338
+ ## 硬闸(Done Criteria)
339
+
340
+ 进入 `devflow design` 前必须:
341
+
342
+ - [ ] 每条功能需求都有唯一 F-ID + 可验收 AC
343
+ - [ ] 所有 P0 歧义已解决(Round 1)
344
+ - [ ] `## 5. 数据/接口影响` 非空(Round 2 侦察结论已写)
345
+ - [ ] `## 8. 边界与异常` 至少 4 条具体场景
346
+ - [ ] 用户确认过整份文档("一次通读,有没有要改的")
347
+
348
+ 未达标 → 继续下一轮 Q 或回报 `NEEDS_INPUT`。
349
+
350
+ ## 反模式
351
+
352
+ - **不看 refs 直接编**:用户贴了 Wiki 你却写出 Wiki 里没有的内容 → 幻觉,必挂。
353
+ - **Round 1 就开始读代码**:浪费时间,Round 1 的重点是业务契约不是实现。
354
+ - **Round 2 问用户代码细节**(他答不出):读代码是你的事,不是用户的事。
355
+ - **Round 1 逐个问**:只问 Q1 等用户答完再问 Q2,会拖慢业务确认且容易丢上下文。Round 1 必须一次性列出本轮全部业务问题。
356
+ - **一轮问 20 个问题**:用户会挑着答,剩下的你当默认,后面炸。Round 1 最多 8 个,优先合并同类项;仍超过 8 个就要求补材料。
357
+ - **AC 全是"通过测试"**:这是自反的,没信息。AC 要写**业务可验证**的具体判定。
358
+ - **Edge cases 只写一两条当凑数**:漏掉的边界案例会在 code-review 或 verify 翻出来变 MUST。
359
+ - **忘记问灰度 / 回滚**(L3):非功能需求段一片空白,到 design 阶段临时补会混乱。
360
+ - **把 Out of scope 当最后一步填**:应该在 Round 1 Q5 附近就锚定,防止后续被一点点加。
361
+
362
+ ## 产物格式规范
363
+
364
+ ### refs/kb-context.md(代码侦察报告,持久化缓存)
365
+
366
+ ```markdown
367
+ # 知识背景
368
+
369
+ > WeKnora 命中 N 条 / 未配置,知识来源:本地代码仓库 + 需求文档
370
+
371
+ ## 相关代码位置
372
+
373
+ | 模块 | 路径 | 说明 |
374
+ |------|------|------|
375
+ | 接口入口 | `app/api/xxx.go:49` `Handler` | 按 xxxType dispatch,type=14 命中 map 判空报错 |
376
+ | 业务服务 | `services/xxx/info.go` `GetDetail` | type=11 的 detail 逻辑,会填充 Name、JumpUrl |
377
+ | 枚举定义 | `enum/member.go` | WeComFree=11,type=14 未定义 |
378
+
379
+ ## 关键常量
380
+
381
+ - `XxxDefaultReturnURL = "https://..."` — type=11 专属配置,type=14 需补充
382
+ - 敏感城市:北京、上海、深圳、珠海(+ 广东省)
383
+
384
+ ## 历史设计模式
385
+
386
+ - 领取流程均走 `ReceiveXxx → ReceiveWeComFreeXxx → CreateFreeReceiveOrder`
387
+ - 初始化器通过 Factory 注册,按 type dispatch,每个 type 独立实现 `OrderInitializer`
388
+ - detail 接口通过 `switch type` 分发到各 `Get*Detail` 方法
389
+ ```
390
+
391
+ ### requirement.md 格式
392
+
393
+ ```markdown
394
+ # 结构化需求:<标题>(<核心标识>)
395
+
396
+ > 来源:`refs/source.md` | JIRA/URL: <引用>
397
+
398
+ ---
399
+
400
+ ## 一、需求背景
401
+ <一段话:目标 + 价值>
402
+
403
+ ---
404
+
405
+ ## 二、角色与系统边界
406
+
407
+ | 角色 | 说明 |
408
+ |------|------|
409
+ | 用户 | ... |
410
+ | 后端服务 | ..., 提供 detail 查询和领取两个主要接口 |
411
+
412
+ ---
413
+
414
+ ## 三、功能点列表
415
+
416
+ | 序号 | 功能名 | 类型 | 优先级 | 说明 |
417
+ |------|--------|------|--------|------|
418
+ | F1 | <能力名> | 新增/修改/数据变更 | P0/P1 | <一句话说明 + 关联代码位置> |
419
+ | F2 | ... | ... | ... | ... |
420
+
421
+ ---
422
+
423
+ ## 四、功能详述(每个 F-ID 一节)
424
+
425
+ ### F1 — <能力名>
426
+
427
+ **AC(验收标准)**:
428
+ - AC-1: ...(Given-When-Then 或可自动化断言的描述)
429
+ - AC-2: ...
430
+
431
+ **边界条件**:
432
+ - 空/null:...
433
+ - 极大值:...
434
+ - 重复/幂等:...
435
+
436
+ ---
437
+
438
+ ## 五、数据/接口影响(代码侦察结论)
439
+
440
+ > 初步侦察结论,design 阶段细化。
441
+
442
+ | 类别 | 位置 | 影响描述 |
443
+ |------|------|---------|
444
+ | 接口 | `xxx.go:49` | 需新增 type=14 分支 |
445
+
446
+ ---
447
+
448
+ ## 六、非功能需求
449
+
450
+ - 性能:...
451
+ - 安全/合规:...
452
+
453
+ ---
454
+
455
+ ## 七、风险与遗留(含 KB 历史参考)
456
+
457
+ - 历史参考:<kb-context.md 命中的历史坑点>
458
+ - Open issue:...
459
+ ```
460
+
461
+ ## 完成状态协议
462
+
463
+ > **HARD RULE:下一步卡片必须出现。**
464
+ >
465
+ > requirement-analysis 的任何用户可见回复,特别是"已更新 requirement.md"、"已记录你的确认"、"已按你的回答调整 scope / AC / Out of scope"这类中间态回复,收尾都必须输出 `---STATUS---`,并紧跟一张明确的下一步卡片。不能只列"已更新文件"和变更摘要。
466
+ >
467
+ > - 如果 Done Criteria 已满足:`result: DONE`,`nextAction: devflow design --with-tests`(L2/L3)或 `devflow design`(L1)。
468
+ > - 如果刚根据用户反馈更新了 `requirement.md`,但还需要用户确认继续:`result: NEEDS_INPUT`,`nextAction: 等待用户回复「继续」后继续 devflow-requirement-analysis`。
469
+ > - 如果仍有业务问题:一次性列出剩余问题,并在下一步卡片里说明"请批量回答以上问题"。
470
+ > - 如果被前置确认缺失阻塞:`result: NEEDS_INPUT`,`nextAction: 回到 devflow-complexity-grading 补确认问题卡/涉及项目`。
471
+
472
+ ```
473
+ ---STATUS---
474
+ result: DONE | DONE_WITH_CONCERNS | BLOCKED | NEEDS_INPUT
475
+ outputs:
476
+ - devflow/changes/<slug>/refs/kb-context.md
477
+ - devflow/changes/<slug>/requirement.md
478
+ functionalRequirementCount: K # F-01..F-0K
479
+ openIssueCount: N # 未解决的 Open issue 数
480
+ level: L1 | L2 | L3 # 可能 brainstorm 的 level 在 requirement 阶段升级
481
+ nextAction: devflow design [--with-tests]
482
+ ---END_STATUS---
483
+ ```
484
+
485
+ **下一步卡片模板(必须紧跟 STATUS 展示):**
486
+
487
+ ```markdown
488
+ 下一步:<人类可读动作>
489
+ 命令:`<nextAction command 或 等待用户回复「继续」>`
490
+ 说明:<为什么是这一步,最多一行>
491
+ ```
492
+
493
+ ## 参考
494
+
495
+ - [`references/requirement-template.md`](references/requirement-template.md) — 9 段 requirement.md 模板、字段语义、正反例、完整示例
496
+ - [`references/code-recon.md`](references/code-recon.md) — Round 2 的代码侦察方法论:grep / glob 用法、哪些要读、何时停
497
+ - [`references/acceptance-criteria.md`](references/acceptance-criteria.md) — AC 规范(SMART / INVEST / Given-When-Then)、F-ID 编号、AC 例子库
498
+ - [`references/edge-case-catalog.md`](references/edge-case-catalog.md) — 8 个维度的边界 catalog,需求阶段挖 4 条以上
499
+ - [`references/scope-negotiation.md`](references/scope-negotiation.md) — 加功能 / 减功能 / 改优先级的决策树与话术
@@ -0,0 +1,183 @@
1
+ # requirement-analysis / acceptance-criteria
2
+
3
+ Acceptance Criteria(AC) 的规范、F-ID 编号、Given-When-Then 模板、AC 例子库。AC 是 requirement 的**最核心产物**,下游所有 phase(design 改动点、tests.md 用例、code-review 覆盖度、verify 自测) 都以它为锚。
4
+
5
+ ---
6
+
7
+ ## AC 的硬规范
8
+
9
+ | 规则 | 含义 |
10
+ | --- | --- |
11
+ | **S**pecific | 指明具体动作、输入、输出,避免"合理"/"适当"/"友好"这类模糊词 |
12
+ | **M**easurable | 要么可数、要么可二值判定;避免"更好"/"更快" |
13
+ | **A**chievable | 现有能力 + 本次改动能达成;不跨 phase 依赖 |
14
+ | **R**elevant | 对应 F-ID 的核心价值,不是"顺手也做" |
15
+ | **T**ime-bound | 若涉及时序,必须带具体时间(如"P99 ≤ 3s")或时序约束(如"30 秒内") |
16
+
17
+ ---
18
+
19
+ ## F-ID 编号规范
20
+
21
+ - 格式 `F-<NN>`,F-01 起
22
+ - 单 change 内全局唯一,**永不重用**
23
+ - 允许子项:`F-01.1`、`F-01.2`(表示 F-01 的分支场景)
24
+ - 删除时**只标注**("~~F-07 (删除)~~"),不真删不移号
25
+
26
+ ---
27
+
28
+ ## AC 两种写法(任选)
29
+
30
+ ### 写法 A:单句精确句
31
+
32
+ 适合简单场景。格式:`<条件> → <期望结果>`。
33
+
34
+ **例**:
35
+
36
+ - 批量超过 1000 人 → 返回 400 BATCH_TOO_LARGE
37
+ - 传空 userIds → 返回 400 EMPTY_BATCH
38
+ - 成功发放 → 返回 200 body 含 grantedCount 与 failedUsers 数组
39
+
40
+ ### 写法 B:Given-When-Then(推荐,L2/L3)
41
+
42
+ 行为驱动开发(BDD)的三段式,**与 test case 一一对应**,下游 test-spec 直接按 GWT 写用例。
43
+
44
+ ```
45
+ Given <前提条件>
46
+ When <触发动作>
47
+ Then <期望结果>
48
+ And <额外期望>(可选)
49
+ ```
50
+
51
+ **例**:
52
+
53
+ ```
54
+ F-01:
55
+ Given 有效 token 的运营角色 + 1000 个合法 userId + 存在的 couponTemplateId
56
+ When 调用 POST /api/v2/coupon/batch-grant
57
+ Then 返回 200
58
+ And body.grantedCount + body.failedCount === 1000
59
+ And 全量响应时间 ≤ 3s
60
+ And 指标 coupon.batch.latency 上报 1 条 histogram
61
+ ```
62
+
63
+ 一条 F-ID 可以有**多个 GWT** 覆盖不同场景(正向 / 边界 / 异常):
64
+
65
+ ```
66
+ F-01 正向:
67
+ Given 合法输入 When ... Then ...
68
+
69
+ F-01 边界(超限):
70
+ Given 1001 个 userId When ... Then 返回 400 BATCH_TOO_LARGE
71
+
72
+ F-01 边界(空):
73
+ Given 空 userIds ...
74
+ ```
75
+
76
+ ---
77
+
78
+ ## AC 写法对照表
79
+
80
+ | 差写法(打回) | 好写法(通过) |
81
+ | --- | --- |
82
+ | "接口要快" | "P99 ≤ 3s(1000 人场景)" |
83
+ | "风控要一致" | "每个 user 走与单发相同的 RiskService.check,拦截时 failedUsers 含 hitCode" |
84
+ | "要支持批量" | "单次 1-1000 人,>1000 返回 400 BATCH_TOO_LARGE" |
85
+ | "错误要友好" | "错误码表:EMPTY_BATCH / BATCH_TOO_LARGE / TEMPLATE_NOT_FOUND / INSUFFICIENT_STOCK,每个带 message + suggestion" |
86
+ | "权限要严" | "需要角色 coupon:batch_grant;无此权限返回 403 FORBIDDEN" |
87
+ | "数据不丢" | "部分成功时,成功的每条已落库 + 产生 grant_log;失败的不落 grant_log 但 log.error 带 userId + reason" |
88
+ | "灰度上线" | "feature flag coupon.batch.enabled;关闭时接口返回 503 SERVICE_DISABLED" |
89
+
90
+ ---
91
+
92
+ ## AC 例子库(按需直接抄)
93
+
94
+ ### 业务功能
95
+
96
+ - 写入成功:`Given 有效请求 When 调用 X Then 返回 200 + resourceId`
97
+ - 超限:`Given 请求超过 N When ... Then 400 + errorCode=OVER_LIMIT`
98
+ - 不存在资源:`Given 不存在的 id When ... Then 404 + errorCode=NOT_FOUND`
99
+ - 冲突 / 重复:`Given 重复 key When ... Then 409 + errorCode=DUPLICATE`
100
+
101
+ ### 权限 / 安全
102
+
103
+ - 无 token:`Given 缺失 Authorization Then 401 UNAUTHORIZED`
104
+ - 无权限:`Given token 角色不足 Then 403 FORBIDDEN + errorCode=INSUFFICIENT_ROLE`
105
+ - 越权:`Given 用户 A 的 token 访问用户 B 的资源 Then 403 FORBIDDEN + 不泄漏 B 的存在信息`
106
+ - 敏感数据日志:`Given 任意请求含手机号 Then log 中手机号脱敏到后 4 位(如 138****1234)`
107
+
108
+ ### 并发 / 幂等
109
+
110
+ - 重复支付:`Given 同一 payNo 提交 2 次 Then 第 2 次返回第 1 次的结果 + 不产生新订单`
111
+ - 同时扣减:`Given qty=10 库存 + 两请求同时减 1 Then 最终 qty=8(原子 UPDATE)`
112
+ - 乐观锁:`Given 两请求更新同记录 Then 晚提交的返回 409 VERSION_CONFLICT`
113
+
114
+ ### 性能 / 扩展性
115
+
116
+ - 单次吞吐:`Given 1000 人批量 Then P99 ≤ 3s`
117
+ - 持续负载:`Given QPS=20 持续 10 分钟 Then error_rate < 0.1% + P99 不超过基线 1.5x`
118
+ - 冷热缓存:`Given 冷启动 Then 前 3 次请求允许超过基线(带 cache-miss 标记)`
119
+
120
+ ### 可观测性
121
+
122
+ - 指标:`Given 任一次调用 Then 指标 xxx.latency 上报;失败时 xxx.errors.count 累加`
123
+ - 告警:`Given P99 > 阈值 5 分钟 Then 触发 warning 告警 + 10 分钟内通知 on-call`
124
+ - 日志:`Given 异常路径 Then log.error 含 traceId + 业务 key + exception.toString`
125
+
126
+ ### 灰度 / 回滚
127
+
128
+ - 灰度:`Given flag coupon.batch.enabled=0.1 Then 请求按 userId hash 随机 10% 进入新逻辑,其余 90% 走旧路径`
129
+ - 回滚:`Given flag 从 1.0 → 0 Then 正在进行的请求沿用新路径完成,新请求走旧路径,数据可继续读`
130
+ - 前向兼容:`Given 新客户端请求 + 旧服务端 Then 服务端忽略未知字段,返回旧版响应`
131
+
132
+ ### 边界 / 异常
133
+
134
+ - 空集合:`Given 空输入 Then 400 + EMPTY_INPUT(不要返回 200 空结果)`
135
+ - null:`Given 必填字段为 null Then 400 + FIELD_REQUIRED:<name>`
136
+ - 超大:`Given payload > 1MB Then 413 PAYLOAD_TOO_LARGE`
137
+ - 编码:`Given 请求含 emoji Then 正确解析 UTF-8 并原样存储(不乱码)`
138
+
139
+ ---
140
+
141
+ ## AC 密度规则
142
+
143
+ | Level | 每个 F-ID 最少 AC 数 | 必覆盖的场景 |
144
+ | --- | --- | --- |
145
+ | L1 | 1 | 正向 |
146
+ | L2 | 2-3 | 正向 + 1 边界 / 1 异常 |
147
+ | L3 | 3-5 | 正向 + 2 边界 + 1 异常 + 1 性能 / 可观测性 |
148
+
149
+ **反例**(L2 F-ID 只有一条正向 AC):
150
+
151
+ > F-01 批量发放:Given 1000 人 When 调用 Then 200 ✓
152
+
153
+ 这个在 verify / code-review 阶段会被打回 —— L2 要求至少覆盖一条边界和一条异常。
154
+
155
+ ---
156
+
157
+ ## AC 与下游产物的映射(关键)
158
+
159
+ | 产物 | 如何使用 AC |
160
+ | --- | --- |
161
+ | `tests.md`(test-spec) | **每个 AC 至少映射 1 个 TC**;Given-When-Then 直接对应 test 的 setup/action/assert |
162
+ | `design.md`(tech-spec) | 每个 F-ID 的实现路径在"改动点汇总"里体现;AC 约束选型(比如 P99 ≤ 3s 决定要不要缓存) |
163
+ | `plan.md`(plan) | 每个 task 引用对应的 F-ID + 对应的 TC 编号 |
164
+ | `code-review` | Completeness 维度逐条核对 F-ID / AC 是否已实现 |
165
+ | `verify` | self-test 表按 F-ID 组织,逐条打勾 |
166
+
167
+ 换句话说 —— **AC 写得好,下游全自动;AC 写得差,下游全返工**。
168
+
169
+ ---
170
+
171
+ ## 写 AC 的常见误区
172
+
173
+ 1. **"通过测试"不是 AC**:AC 是业务契约,"通过测试"是自反的。
174
+ 2. **"根据设计文档实现"不是 AC**:设计文档是下游产物,不能被需求引用。
175
+ 3. **把 AC 写成"一步步怎么做"**:AC 是 WHAT,不是 HOW。HOW 在 design.md。
176
+ 4. **把多个独立判定混在一句 AC 里**:每个判定独立一行,方便一一映射 test case。
177
+ 5. **AC 里引用了 design 里的具体实现**(比如"走 Redis")**:不允许**;AC 应该只约束行为契约,实现细节留 design。
178
+
179
+ ---
180
+
181
+ ## 本文与 SKILL.md 的关系
182
+
183
+ SKILL.md 只说了"每条 F-ID 至少 1 条可验收的 AC"。本文给:AC 规范(SMART)、F-ID 编号规则、两种写法(单句 / GWT)、AC 例子库、AC 密度规则、下游映射、常见误区。agent 写 `§3 功能需求` 时应以本文例子库为参考。