@tea-agent/loop-agent 0.12.0 → 0.13.0-beta.0

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 (284) hide show
  1. package/AGENTS.md +155 -153
  2. package/CHANGELOG.md +338 -265
  3. package/README.md +345 -298
  4. package/bin/agent-worker.js +22 -22
  5. package/bin/loop-agent.js +21 -21
  6. package/dist/application/dag/generate-task-dag.js +28 -28
  7. package/dist/application/evaluation/candidate-hash.js +75 -0
  8. package/dist/application/evaluation/candidate.js +52 -0
  9. package/dist/application/evaluation/replay.js +289 -0
  10. package/dist/application/evaluation/types.js +130 -0
  11. package/dist/cli/command-definitions.js +27 -7
  12. package/dist/cli/program.js +8 -4
  13. package/dist/commands/cursor-prompt.js +6 -6
  14. package/dist/commands/eval.js +235 -0
  15. package/dist/commands/init.js +544 -506
  16. package/dist/commands/knowledge.js +129 -31
  17. package/dist/commands/loop-benchmark.js +11 -11
  18. package/dist/commands/pi-reuse-benchmark.js +16 -16
  19. package/dist/executors/pi-sdk-executor.js +38 -24
  20. package/dist/executors/shell-executor.js +34 -2
  21. package/dist/executors/shell-presets.js +20 -0
  22. package/dist/executors/shell-verification.js +7 -0
  23. package/dist/governance/manifest-types.js +4 -0
  24. package/dist/infrastructure/evaluation/candidate-store.js +435 -0
  25. package/dist/infrastructure/evaluation/store.js +40 -0
  26. package/dist/sidecars/cursor-prompt/executor.js +1 -1
  27. package/dist/task/config-types.js +28 -1
  28. package/dist/task/runtime.js +27 -27
  29. package/dist/worker/cli.js +96 -1
  30. package/dist/worker/delivery/package.js +3 -3
  31. package/dist/worker/feature/decision-loader.js +37 -6
  32. package/dist/worker/feature/next-action.js +10 -2
  33. package/dist/worker/feature/ready-plan-projection.js +81 -0
  34. package/dist/worker/feature/reducer.js +2 -1
  35. package/dist/worker/feature/review.js +19 -2
  36. package/dist/worker/feature/run.js +27 -2
  37. package/dist/worker/follow-up/approve.js +5 -2
  38. package/dist/worker/follow-up/factory.js +1 -1
  39. package/dist/worker/observability/read-model.js +246 -41
  40. package/dist/worker/observe/routes.js +173 -15
  41. package/dist/worker/observe/spec-evidence.js +281 -0
  42. package/dist/worker/observe/static/api.js +46 -27
  43. package/dist/worker/observe/static/app.js +150 -150
  44. package/dist/worker/observe/static/constants.js +148 -148
  45. package/dist/worker/observe/static/copy.js +67 -67
  46. package/dist/worker/observe/static/dag-helpers.js +172 -172
  47. package/dist/worker/observe/static/dag-layout.d.ts +31 -31
  48. package/dist/worker/observe/static/dag-layout.js +83 -83
  49. package/dist/worker/observe/static/dag-model.js +72 -72
  50. package/dist/worker/observe/static/dom.js +61 -61
  51. package/dist/worker/observe/static/format-pool.js +67 -67
  52. package/dist/worker/observe/static/format.js +292 -292
  53. package/dist/worker/observe/static/index.html +308 -308
  54. package/dist/worker/observe/static/kpi.js +94 -94
  55. package/dist/worker/observe/static/relations.js +133 -128
  56. package/dist/worker/observe/static/router.js +93 -85
  57. package/dist/worker/observe/static/run-processing.js +148 -148
  58. package/dist/worker/observe/static/shell-chrome.js +68 -68
  59. package/dist/worker/observe/static/state.js +253 -253
  60. package/dist/worker/observe/static/styles.css +1902 -1890
  61. package/dist/worker/observe/static/views/batch.js +227 -226
  62. package/dist/worker/observe/static/views/dag-graph.js +172 -172
  63. package/dist/worker/observe/static/views/dag-inspector.js +607 -477
  64. package/dist/worker/observe/static/views/dag.js +362 -362
  65. package/dist/worker/observe/static/views/dashboard.js +445 -442
  66. package/dist/worker/observe/static/views/failures.js +143 -143
  67. package/dist/worker/observe/static/views/feature.js +492 -453
  68. package/dist/worker/observe/static/views/pool.js +350 -347
  69. package/dist/worker/observe/static/views/run.js +453 -453
  70. package/dist/worker/observe/static/views/session-timeline.js +205 -205
  71. package/dist/worker/observe/static/views/shell.js +7 -7
  72. package/dist/worker/observe/static/views/task.js +314 -260
  73. package/dist/worker/observe/static/views/timeline.js +163 -163
  74. package/dist/worker/pool/doctor.js +165 -0
  75. package/dist/worker/pool/migrate-state.js +303 -0
  76. package/dist/worker/pool/run-store.js +205 -17
  77. package/dist/worker/pool/types.js +17 -1
  78. package/dist/worker/pool/validation.js +100 -15
  79. package/dist/worker/report/morning-report.js +12 -2
  80. package/dist/worker/runner/run-ready.js +41 -26
  81. package/dist/worker/task-graph/ready-planner.js +136 -0
  82. package/dist/workflows/dag/backend-test-analysis-contract.js +120 -0
  83. package/dist/workflows/dag/canvas-observer.js +275 -275
  84. package/dist/workflows/dag/convergence/controller.js +16 -8
  85. package/dist/workflows/dag/dynamic-runtime/map.js +90 -2
  86. package/dist/workflows/dag/failure-routing.js +12 -1
  87. package/dist/workflows/dag/init-hybrid.js +2404 -360
  88. package/dist/workflows/dag/node-execution.js +9 -0
  89. package/dist/workflows/dag/prompt.js +9 -0
  90. package/dist/workflows/dag/report.js +35 -1
  91. package/dist/workflows/dag/runner.js +28 -2
  92. package/dist/workflows/dag/task-demand-routing.js +383 -0
  93. package/dist/workflows/dag/types.js +51 -13
  94. package/dist/workflows/dag/upstream-artifacts.js +1 -0
  95. package/dist/workflows/dag/validate.js +59 -1
  96. package/docs/README.md +106 -104
  97. package/docs/agent-dag-recovery-playbook.md +195 -184
  98. package/docs/agent-dag-runner.md +67 -67
  99. package/docs/architecture/README.md +26 -26
  100. package/docs/architecture/dag-execution.md +140 -140
  101. package/docs/architecture/evolution.md +54 -53
  102. package/docs/architecture/facts-and-state.md +71 -58
  103. package/docs/architecture/runtime-boundaries.md +191 -191
  104. package/docs/architecture/system-overview.md +93 -93
  105. package/docs/architecture/worker-and-feature.md +85 -81
  106. package/docs/cursor-prompt-sidecar.md +36 -36
  107. package/docs/decisions/README.md +18 -15
  108. package/docs/design/README.md +167 -77
  109. package/docs/development-principles.md +73 -73
  110. package/docs/exec-plans/README.md +6 -6
  111. package/docs/exec-plans/active/README.md +15 -9
  112. package/docs/exec-plans/completed/README.md +85 -73
  113. package/docs/feature-workflow.md +389 -261
  114. package/docs/harness-methodology-debugging.md +153 -153
  115. package/docs/harness-methodology-tdd.md +130 -130
  116. package/docs/harness-methodology-verification.md +27 -27
  117. package/docs/init-surface.manifest.json +289 -280
  118. package/docs/loop-agent-harness.md +142 -130
  119. package/docs/production-readiness.md +96 -96
  120. package/docs/progress/README.md +64 -54
  121. package/docs/reports/README.md +117 -94
  122. package/docs/skills/README.md +7 -7
  123. package/docs/skills/vetted-skill-registry.md +29 -27
  124. package/docs/templates/adr.md +60 -60
  125. package/docs/templates/agent-dag-authority-surface-audit.prompt.md +94 -94
  126. package/docs/templates/agent-dag-decision-envelope.schema.json +213 -213
  127. package/docs/templates/agent-dag-decision-gate-dogfood-report.md +117 -117
  128. package/docs/templates/agent-dag-decision-gate.prompt.md +246 -246
  129. package/docs/templates/agent-dag-process-supervisor.prompt.md +98 -98
  130. package/docs/templates/agent-dag-report.schema.json +473 -473
  131. package/docs/templates/agent-dag-review-verdict.prompt.md +68 -68
  132. package/docs/templates/agent-dag.base.json +190 -190
  133. package/docs/templates/agent-dag.final-verification.json +185 -185
  134. package/docs/templates/agent-dag.schema.json +411 -383
  135. package/docs/templates/agent-dag.supervised-implementation.json +501 -501
  136. package/docs/templates/backend-test-analysis.schema.json +44 -0
  137. package/docs/templates/backend-test-dag.generate-pytest.prompt.md +202 -139
  138. package/docs/templates/backend-test-dag.json +311 -276
  139. package/docs/templates/backend-test-dag.retrospect.prompt.md +125 -125
  140. package/docs/templates/backend-test-dag.review-cases.prompt.md +81 -81
  141. package/docs/templates/exec-plan.md +64 -64
  142. package/docs/templates/feature-spec.md +53 -53
  143. package/docs/templates/frontend-design-contract.md +42 -33
  144. package/docs/templates/frontend-task-constraints.md +35 -25
  145. package/docs/templates/frontend-task-requirement.md +70 -61
  146. package/docs/templates/frontend-test-dag.generate-cases.prompt.md +5 -0
  147. package/docs/templates/frontend-test-dag.json +23 -0
  148. package/docs/templates/frontend-test-dag.retrieve-context.prompt.md +3 -0
  149. package/docs/templates/frontend-test-dag.retrospect.prompt.md +3 -0
  150. package/docs/templates/frontend-test-dag.review-cases.prompt.md +3 -0
  151. package/docs/templates/frontend-test-dag.review-execution.prompt.md +3 -0
  152. package/docs/templates/harness.schema.json +221 -221
  153. package/docs/templates/hybrid-dag.json +188 -188
  154. package/docs/templates/init-evolution-review.md +35 -35
  155. package/docs/templates/interactive-ui-round2-experiment.md +66 -66
  156. package/docs/templates/knowledge-graph-bootstrap-dag.json +118 -0
  157. package/docs/templates/knowledge-sync-dag.json +178 -0
  158. package/docs/templates/knowledge-sync-draft.schema.json +71 -0
  159. package/docs/templates/product-line/AGENTS.md +8 -8
  160. package/docs/templates/product-line/README.md +9 -9
  161. package/docs/templates/product-line/acceptance.yaml +14 -14
  162. package/docs/templates/product-line/closeout.yaml +9 -9
  163. package/docs/templates/product-line/design.md +13 -13
  164. package/docs/templates/product-line/links.md +10 -10
  165. package/docs/templates/product-line/requirement.md +17 -17
  166. package/docs/templates/product-line/task-graph.yaml +15 -15
  167. package/docs/templates/product-line/task.yaml +64 -64
  168. package/docs/templates/product-line/test-plan.md +7 -7
  169. package/docs/templates/production-readiness-checklist.md +57 -57
  170. package/docs/templates/progress-log.md +17 -17
  171. package/docs/templates/project-start-checklist.md +9 -9
  172. package/docs/templates/qa-report.md +48 -48
  173. package/docs/templates/sprint-contract.md +29 -29
  174. package/docs/templates/worker-dogfood-evidence.md +80 -80
  175. package/docs/templates/worker-dogfood-setup.md +68 -68
  176. package/docs/verification-matrix.md +70 -66
  177. package/examples/decision-gate-agent-dag.json +177 -177
  178. package/examples/example-dag.json +46 -46
  179. package/examples/hybrid-loop-agent-dag.json +189 -189
  180. package/harness.json +66 -66
  181. package/package.json +88 -46
  182. package/scripts/check-product-line-docs.sh +29 -29
  183. package/scripts/check-task-pool-root.sh +32 -32
  184. package/scripts/kb-bootstrap-init-skeleton.sh +240 -0
  185. package/scripts/kb-graph-incremental-prepare.mjs +386 -0
  186. package/scripts/kb-graph-incremental-prepare.sh +5 -0
  187. package/scripts/kb-graph-materialize.mjs +105 -0
  188. package/scripts/kb-graph-materialize.sh +4 -0
  189. package/scripts/kb-graph-promote.mjs +164 -0
  190. package/scripts/kb-graph-promote.sh +4 -0
  191. package/scripts/kb-query.mjs +554 -0
  192. package/scripts/kb-query.sh +5 -0
  193. package/skills/agent-worker/SKILL.md +39 -37
  194. package/skills/agent-worker/references/agent-worker-operator.md +60 -43
  195. package/skills/ai-engineering-context/SKILL.md +48 -48
  196. package/skills/analyze-product-dependencies/SKILL.md +67 -0
  197. package/skills/analyze-product-dependencies/agents/openai.yaml +4 -0
  198. package/skills/analyze-product-dependencies/references/api-documentation-schema.md +30 -0
  199. package/skills/analyze-product-dependencies/references/dependency-analysis-schema.md +28 -0
  200. package/skills/analyze-product-dependencies/references/example.md +76 -0
  201. package/skills/analyze-product-dependencies/references/forward-test-cases.md +35 -0
  202. package/skills/analyze-product-dependencies/references/input-contract.md +11 -0
  203. package/skills/analyze-product-dependencies/references/scouting-rules.md +61 -0
  204. package/skills/analyze-product-dependencies/scripts/test-validators.mjs +267 -0
  205. package/skills/analyze-product-dependencies/scripts/validate-api-documentation.mjs +101 -0
  206. package/skills/analyze-product-dependencies/scripts/validate-dependency-analysis.mjs +142 -0
  207. package/skills/analyze-product-dependencies/scripts/validate-product-requirement-input.mjs +76 -0
  208. package/skills/analyze-product-dependencies/scripts/validation-helpers.mjs +146 -0
  209. package/skills/analyze-product-requirements/SKILL.md +90 -0
  210. package/skills/analyze-product-requirements/agents/openai.yaml +4 -0
  211. package/skills/analyze-product-requirements/references/acceptance-criteria.md +91 -0
  212. package/skills/analyze-product-requirements/references/clarification-and-knowledge.md +56 -0
  213. package/skills/analyze-product-requirements/references/example.md +86 -0
  214. package/skills/analyze-product-requirements/references/forward-test-cases.md +66 -0
  215. package/skills/analyze-product-requirements/references/product-analysis-schema.md +32 -0
  216. package/skills/analyze-product-requirements/references/product-requirement-schema.md +33 -0
  217. package/skills/analyze-product-requirements/references/requirement-clarification-schema.md +35 -0
  218. package/skills/analyze-product-requirements/scripts/test-validators.mjs +193 -0
  219. package/skills/analyze-product-requirements/scripts/validate-product-analysis.mjs +69 -0
  220. package/skills/analyze-product-requirements/scripts/validate-product-requirement.mjs +97 -0
  221. package/skills/analyze-product-requirements/scripts/validate-requirement-clarification.mjs +98 -0
  222. package/skills/analyze-product-requirements/scripts/validation-helpers.mjs +156 -0
  223. package/skills/code-review-core/SKILL.md +20 -20
  224. package/skills/codebase-scout/SKILL.md +19 -19
  225. package/skills/frontend-design-review/SKILL.md +66 -59
  226. package/skills/frontend-design-review/references/review-checklist.md +58 -37
  227. package/skills/frontend-implementation/SKILL.md +47 -51
  228. package/skills/frontend-implementation/references/code-standards.md +32 -34
  229. package/skills/frontend-implementation/references/design-spec.md +46 -46
  230. package/skills/frontend-implementation/references/node-contracts.md +76 -32
  231. package/skills/frontend-review/SKILL.md +59 -53
  232. package/skills/frontend-review/references/review-findings.md +47 -42
  233. package/skills/frontend-verification/SKILL.md +53 -40
  234. package/skills/frontend-verification/references/verification-checklist.md +68 -56
  235. package/skills/grill-me/SKILL.md +10 -10
  236. package/skills/grill-with-docs/SKILL.md +88 -88
  237. package/skills/grill-with-docs/adr-format.md +47 -47
  238. package/skills/grill-with-docs/context-format.md +60 -60
  239. package/skills/init-capability-evolution/SKILL.md +70 -70
  240. package/skills/loop-agent/SKILL.md +151 -151
  241. package/skills/loop-agent/references/README.md +67 -67
  242. package/skills/loop-agent/references/command-reference.md +505 -452
  243. package/skills/loop-agent/references/docs-converge.md +126 -126
  244. package/skills/loop-agent/references/harness-policy.md +263 -263
  245. package/skills/loop-agent/references/hybrid-dag.md +238 -233
  246. package/skills/loop-agent/references/learned/README.md +21 -21
  247. package/skills/loop-agent/references/long-running-loop.md +57 -57
  248. package/skills/loop-agent/references/model-routing.md +36 -36
  249. package/skills/loop-agent/references/multi-worktree.md +54 -54
  250. package/skills/loop-agent/references/one-shot-runs.md +85 -85
  251. package/skills/loop-agent/references/orchestrator-and-interventions.md +169 -169
  252. package/skills/loop-agent/references/pi-prompt.md +23 -23
  253. package/skills/loop-agent/references/pi-subagent-assisted-mode.md +84 -84
  254. package/skills/loop-agent/references/post-implementation-and-patterns.md +44 -44
  255. package/skills/loop-agent/references/task-workflow.md +89 -89
  256. package/skills/loop-agent/references/verification-and-failure-handling.md +139 -139
  257. package/skills/playwright-cli/SKILL.md +420 -0
  258. package/skills/playwright-cli/references/element-attributes.md +23 -0
  259. package/skills/playwright-cli/references/playwright-tests.md +39 -0
  260. package/skills/playwright-cli/references/request-mocking.md +87 -0
  261. package/skills/playwright-cli/references/running-code.md +241 -0
  262. package/skills/playwright-cli/references/session-management.md +225 -0
  263. package/skills/playwright-cli/references/storage-state.md +275 -0
  264. package/skills/playwright-cli/references/test-generation.md +433 -0
  265. package/skills/playwright-cli/references/tracing.md +139 -0
  266. package/skills/playwright-cli/references/video-recording.md +143 -0
  267. package/skills/playwright-cli-case-generator/SKILL.md +74 -0
  268. package/skills/requesting-code-review/SKILL.md +101 -101
  269. package/skills/requesting-code-review/code-reviewer.md +168 -168
  270. package/skills/systematic-debugging/CREATION-LOG.md +119 -119
  271. package/skills/systematic-debugging/SKILL.md +296 -296
  272. package/skills/systematic-debugging/condition-based-waiting-example.ts +158 -158
  273. package/skills/systematic-debugging/condition-based-waiting.md +115 -115
  274. package/skills/systematic-debugging/defense-in-depth.md +122 -122
  275. package/skills/systematic-debugging/find-polluter.sh +63 -63
  276. package/skills/systematic-debugging/root-cause-tracing.md +169 -169
  277. package/skills/systematic-debugging/test-academic.md +14 -14
  278. package/skills/systematic-debugging/test-pressure-1.md +58 -58
  279. package/skills/systematic-debugging/test-pressure-2.md +68 -68
  280. package/skills/systematic-debugging/test-pressure-3.md +69 -69
  281. package/skills/test-driven-development/SKILL.md +20 -20
  282. package/skills/using-git-worktrees/SKILL.md +215 -215
  283. package/skills/verification-before-completion/SKILL.md +154 -154
  284. package/skills/webapp-testing/SKILL.md +19 -19
@@ -0,0 +1,146 @@
1
+ import { existsSync, readFileSync, statSync } from "node:fs";
2
+ import { basename, dirname, join, resolve } from "node:path";
3
+
4
+ export function load(fileArg, label) {
5
+ const path = resolve(fileArg);
6
+ try { return { path, text: readFileSync(path, "utf8") }; }
7
+ catch (error) { throw new Error(`Cannot read ${label} ${path}: ${error.message}`); }
8
+ }
9
+
10
+ export function metadata(text, name) {
11
+ const fm = text.match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1] ?? "";
12
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
13
+ return fm.match(new RegExp(`^${escaped}:[ \\t]*["']?([^"'\\r\\n]+)["']?[ \\t]*$`, "m"))?.[1].trim();
14
+ }
15
+
16
+ export function canonical(title) {
17
+ return title.replace(/^\d+(?:\.\d+)*[.、]?[ \t]*/, "").trim();
18
+ }
19
+
20
+ export function headings(text, level) {
21
+ const prefix = "#".repeat(level);
22
+ const matches = [...text.matchAll(new RegExp(`^${prefix}\\s+(.+)$`, "gm"))];
23
+ return matches.map((match, index) => ({ title: match[1].trim(), text: text.slice(match.index, matches[index + 1]?.index ?? text.length) }));
24
+ }
25
+
26
+ export function section(text, level, title) {
27
+ return headings(text, level).find((item) => canonical(item.title) === title)?.text;
28
+ }
29
+
30
+ export function assertHeadings(text, level, required, errors, owner) {
31
+ for (const title of required) {
32
+ const found = headings(text, level).filter((item) => canonical(item.title) === title);
33
+ if (found.length !== 1) errors.push(`${owner} must contain exactly one ${title} heading.`);
34
+ else if (!found[0].text.split(/\r?\n/).slice(1).some((line) => line.trim() && !/^\|?[-:| ]+\|?$/.test(line.trim()))) {
35
+ errors.push(`${owner} section ${title} must not be empty.`);
36
+ }
37
+ }
38
+ }
39
+
40
+ export function storyBlocks(text, prefix) {
41
+ if (!text) return [];
42
+ const matches = [...text.matchAll(new RegExp(`^###\\s+(${prefix}-\\d{3,})\\s+(.+)$`, "gm"))];
43
+ return matches.map((match, index) => ({ id: match[1], text: text.slice(match.index, matches[index + 1]?.index ?? text.length) }));
44
+ }
45
+
46
+ export function outputSpecBlocks(text, prefix) {
47
+ return storyBlocks(text, prefix);
48
+ }
49
+
50
+ export function acceptanceBlocks(story, prefix) {
51
+ const matches = [...story.text.matchAll(new RegExp(`^####\\s+(${prefix}-\\d{3,})\\s+(.+)$`, "gm"))];
52
+ return matches.map((match, index) => ({
53
+ id: match[1],
54
+ text: story.text.slice(match.index, matches[index + 1]?.index ?? story.text.length),
55
+ }));
56
+ }
57
+
58
+ export function validateAcceptance(block, owner, errors) {
59
+ const labels = ["Given", "When", "Then", "异常场景"];
60
+ const positions = labels.map((label) => ({ label, index: block.search(new RegExp(`^${label}[::]`, "m")) }));
61
+ for (const item of positions) if (item.index < 0) errors.push(`${owner} is missing ${item.label}.`);
62
+ if (positions.some((item) => item.index < 0)) return;
63
+ const counts = positions.map((item, index) => {
64
+ const end = positions[index + 1]?.index ?? block.length;
65
+ return (block.slice(item.index, end).match(/^-\s+\S.+$/gm) ?? []).length;
66
+ });
67
+ if (counts[0] < 1 || counts[1] < 1 || counts[2] < 2 || counts[3] < 1) {
68
+ errors.push(`${owner} must contain at least 1 Given, 1 When, 2 Then, and 1 exception bullet.`);
69
+ }
70
+ if (counts.reduce((sum, count) => sum + count, 0) < 6) errors.push(`${owner} must contain at least six concrete bullets.`);
71
+ if (!/(?:不得|不应|禁止|保留|恢复|重试|兜底|回滚|disabled)/.test(block)) {
72
+ errors.push(`${owner} must include an observable protection or recovery result.`);
73
+ }
74
+ }
75
+
76
+ export function containsUnresolvedBlockingPriority(block) {
77
+ if (!block) return false;
78
+ return block.split(/\r?\n/).slice(1).some((line) => {
79
+ const plain = line.trim().replace(/^[-*+]\s*/, "").replace(/^\[[ xX]\]\s*/, "");
80
+ if (!/\bP[01]\b/.test(plain)) return false;
81
+ if (/^(?:不存在|没有|无)(?:任何)?(?:尚未|未)?(?:解决|确认|关闭|完成)?(?:的)?\s*P[01]\b/.test(plain)) return false;
82
+ if (/^P[01]\b/.test(plain)) return true;
83
+ return /(?:pending(?:-blocking)?|unresolved|未解决|未确认|待确认|未决|阻塞)/i.test(plain);
84
+ });
85
+ }
86
+
87
+ export function scopeIncludes(upstream, selected) {
88
+ if (upstream === "both") return ["frontend", "backend", "both"].includes(selected);
89
+ return upstream === selected;
90
+ }
91
+
92
+ export function field(text, name) {
93
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
94
+ return text.match(new RegExp(`^-[ \\t]*${escaped}[::][ \\t]*(.+)$`, "m"))?.[1].trim().replace(/[。.]$/, "");
95
+ }
96
+
97
+ export function fieldBlock(text, name) {
98
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
99
+ const match = new RegExp(`^-[ \\t]*${escaped}[::][ \\t]*(.*)$`, "m").exec(text);
100
+ if (!match) return "";
101
+ const lineEnd = text.indexOf("\n", match.index);
102
+ const rest = lineEnd < 0 ? "" : text.slice(lineEnd + 1);
103
+ const next = rest.search(/^-\s*[^\r\n::]+[::]/m);
104
+ return `${match[1]}\n${rest.slice(0, next < 0 ? rest.length : next)}`.trim();
105
+ }
106
+
107
+ export function tableValue(text, name) {
108
+ const escaped = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
109
+ return text.match(new RegExp(`^\\|[ \\t]*${escaped}[ \\t]*\\|[ \\t]*([^|]+)\\|`, "m"))?.[1].trim();
110
+ }
111
+
112
+ export function apiBlocks(text) {
113
+ const details = section(text, 2, "API 详情") ?? "";
114
+ const matches = [...details.matchAll(/^###\s+(API-\d{3,})\s+(.+)$/gm)];
115
+ return matches.map((match, index) => ({ id: match[1], title: match[2].trim(), text: details.slice(match.index, matches[index + 1]?.index ?? details.length) }));
116
+ }
117
+
118
+ export function print(label, path, errors) {
119
+ if (errors.length) {
120
+ console.error(`${label} validation failed (${errors.length}):`);
121
+ for (const error of errors) console.error(`- ${error}`);
122
+ process.exit(1);
123
+ }
124
+ console.log(`${label} validation passed: ${path}`);
125
+ }
126
+
127
+ export function validateArtifactLocation(artifact, errors, expectedName) {
128
+ const requirementId = metadata(artifact.text, "requirement_id");
129
+ const projectRootValue = metadata(artifact.text, "project_root");
130
+ if (!requirementId || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(requirementId)) {
131
+ errors.push("requirement_id must use lowercase letters, digits, and single hyphens.");
132
+ return;
133
+ }
134
+ if (!projectRootValue) {
135
+ errors.push("project_root is required.");
136
+ return;
137
+ }
138
+ const projectRoot = resolve(dirname(artifact.path), projectRootValue);
139
+ if (!existsSync(projectRoot) || !statSync(projectRoot).isDirectory()) {
140
+ errors.push(`project_root does not resolve to an existing directory: ${projectRoot}`);
141
+ return;
142
+ }
143
+ const expected = resolve(join(projectRoot, "docs", "product-analysis", requirementId));
144
+ if (dirname(artifact.path) !== expected) errors.push(`Artifact must be located under ${expected}.`);
145
+ if (expectedName && basename(artifact.path) !== expectedName) errors.push(`Artifact filename must be ${expectedName}.`);
146
+ }
@@ -0,0 +1,90 @@
1
+ ---
2
+ name: analyze-product-requirements
3
+ description: 将自然语言需求或现有需求文档整理为冻结的澄清前分析、按需澄清记录和完整 Product Requirement,按 frontend、backend 或 both 范围生成精简用户故事、逐故事输出规范与 Given/When/Then 验收标准。用于需求分析、需求澄清、PRD 或用户故事拆分。
4
+ ---
5
+
6
+ # Analyze Product Requirements
7
+
8
+ IRON LAW:`product-analysis.md` 只能生成一次。首次写入成功后,其正文、frontmatter 和文件路径在当前 requirement 的整个生命周期内都不可变;后续轮次禁止编辑、覆盖、追加、格式化、移动或删除该文件。澄清决策只能写入 `requirement-clarification.md`,并通过重新生成合并到 `product-requirement.md`。原始需求同样只读。
9
+
10
+ 本 skill 只定义需求,不分析完整代码依赖或生成实现代码。可对用户提供的仓库做定向事实搜索,但不得输出文件级影响分析。
11
+
12
+ ## 输入与产物
13
+
14
+ - 必填:自然语言需求或原始需求文档路径。
15
+ - 可选:`target=frontend|backend|both` 或 `--target frontend|backend|both`;两种写法等价,默认 `both`。
16
+ - 可选:代码仓库、知识库、历史需求、API 文档、设计规范、业务规则、`project_root`、`requirement_id` 和 `output_dir`。
17
+ - 默认目录:`<project-root>/docs/product-analysis/<requirement-id>/`。
18
+ - 固定产物:该目录内的 `product-analysis.md`、`requirement-clarification.md`、`product-requirement.md`。
19
+
20
+ ## Workflow
21
+
22
+ - [ ] Step 0:确认输入与写入边界 ⛔ BLOCKING
23
+ - [ ] 原始需求必须足以识别业务目标;输入文件只读。
24
+ - [ ] 将 `target=<value>` 和 `--target <value>` 归一化为唯一 target;缺省时为 `both`,非法值或冲突的多个值必须停止。
25
+ - [ ] 在生成前明确回显“分析范围:frontend | backend | both”;三个产物的 `analysis_scope` 必须等于该归一化 target,后续不得自动扩大范围。
26
+ - [ ] 确定项目根:显式 `project_root` > 仓库根 > 当前项目根。
27
+ - [ ] 确定 requirement ID:显式值 > 需求标题 slug > `YYYYMMDD-<summary-slug>`;仅小写字母、数字和单连字符。
28
+ - [ ] 确定目录:显式 `output_dir` 必须等于项目根下 `docs/product-analysis/<requirement-id>`;否则使用该默认目录。
29
+ - [ ] 创建目录,三个产物写入同一目录;元数据使用同一 `requirement_id` 和相对 `project_root: ../../..`。
30
+ - [ ] 输出路径不得与原始需求路径相同;已有目录来源不同则停止,不得混写。
31
+ - [ ] 目标目录已有 `product-analysis.md` 时,验证同源后只读加载并跳过 Step 1;无论 pending 或 complete,都不得对该文件执行任何写操作。
32
+ - [ ] 已有同源 pending 任务只能继续更新 Clarification 和 Product Requirement;如 Product Analysis 需要更正,停止当前 requirement,使用新的 `requirement_id` 和目录重新开始。其他产物覆盖先确认。
33
+ - [ ] Step 1:一次性生成并冻结 Product Analysis ⚠️ REQUIRED
34
+ - [ ] 读取 `references/product-analysis-schema.md`。
35
+ - [ ] 区分明确需求、推断需求和待确认问题。
36
+ - [ ] 如提供仓库,只定向搜索可验证事实并记录 `CODE-FACT-*` 证据。
37
+ - [ ] 仅按 target 生成精简故事骨架和逐故事初步输出规范:`frontend` 只生成 `FE-US-*`,`backend` 只生成 `BE-US-*`,`both` 才生成两端。
38
+ - [ ] Product Analysis 只记录验收关注点,不创建正式 `AC-*` 或完整 Given/When/Then。
39
+ - [ ] 有问题时使用 `ready-for-clarification`;无问题时使用 `no-clarification-required`。
40
+ - [ ] 写入前完成全部分析内容,只允许一次创建;写入成功即冻结,当前及后续澄清轮次不得再调用写工具处理该路径。
41
+ - [ ] Step 2:建立澄清决策树 ⚠️ REQUIRED
42
+ - [ ] 读取 `references/clarification-and-knowledge.md` 和 `references/requirement-clarification-schema.md`。
43
+ - [ ] 有问题时列出 3–6 个顶层 `BR-*` 分支,按依赖排序,从最基础分支开始。
44
+ - [ ] 每轮先给推荐答案和理由,只问一个主要问题;可合并同一决策分支内紧密耦合的子项,但不得混合无关分支。
45
+ - [ ] 用户回答后先复核当前回答是否足以形成明确、唯一、可执行且可验收的最终决策;不得仅因用户已经回答就标记为 confirmed。
46
+ - [ ] 回答不完整、存在多种合理解释、依赖未定义概念、与原始需求或已有决策冲突,或无法自然合并到范围、规则、输出规范和 AC 时,当前问题仍未解决;下一轮必须优先针对该回答的具体模糊点继续澄清,不得跳到其他分支。
47
+ - [ ] 后续追问必须指出上一轮回答中仍不明确的内容,并收窄为可直接确认的决策点;不得原样重复上一轮问题。
48
+ - [ ] 当前回答明确后,再重新识别其他剩余模糊点和回答新引入的模糊点;仅在它们会影响范围、规则、输出或验收时进入下一轮,总轮数不得超过 3 轮。
49
+ - [ ] 第 3 轮后不得继续提问;仍有 P0/P1 时保持 `pending` 并说明阻断项,仍有 P2 时仅可按已记录的默认行为与影响处理。
50
+ - [ ] 能由代码或资料确认的事实自行回答并附证据,不把现状当作产品决策。
51
+ - [ ] 完成一个分支后再进入下一个;不得遗留模糊的“视情况而定”。
52
+ - [ ] 无需澄清时使用三章精简记录,不伪造 `BR-*`、`Q-*` 或 `DEC-Q-*`。
53
+ - [ ] Step 3:记录 Requirement Clarification ⚠️ REQUIRED
54
+ - [ ] 记录总澄清轮数,并为每个问题记录所属轮次、推荐答案、用户回答、最终决策、来源和目标位置;依赖、备选、代码证据和未确认影响仅在适用时记录。
55
+ - [ ] P0/P1 未解决时保持 `pending`;P2 延后必须给出默认行为和影响。
56
+ - [ ] Step 4:重新生成 Product Requirement ⛔ BLOCKING
57
+ - [ ] 读取 `references/product-requirement-schema.md` 和 `references/acceptance-criteria.md`。
58
+ - [ ] 基于原始需求、冻结的 Product Analysis 和 Clarification 重新生成,不做字符串回写。
59
+ - [ ] 优先级:用户确认决策 > 原始明确需求 > 已确认默认值 > 模型推断;代码库事实只用于理解现状、发现冲突和辅助澄清,不构成独立需求来源。
60
+ - [ ] 不得把 `CODE-FACT-*`、仓库路径、代码符号、模块结构、数据表或当前实现过程原样写入 Product Requirement;代码事实只有经用户确认或被原始需求明确要求时,才能转换为不含实现细节的产品规则,证据仍只保留在 Product Analysis 和 Clarification。
61
+ - [ ] 把决策自然合并到范围、规则、故事、逐故事输出规范和 AC,并在决策追溯中登记。
62
+ - [ ] 用户故事只描述角色/使用方、目标/能力、价值、入口/触发方式和 AC 引用;详细产品行为只写在同 ID 输出规范中,正式 AC 嵌入该输出规范。
63
+ - [ ] target 为 `backend` 或 `both` 时,后端故事只定义 API 的业务能力、输入输出语义、权限和规则;具体方法、路径及 DTO 留给依赖 skill。
64
+ - [ ] Step 5:验证并交付 ⛔ BLOCKING
65
+ - [ ] 向 Product Analysis 和 Product Requirement 校验器传入归一化 target,再运行三个产物校验器和 validator matrix。
66
+ - [ ] 确认 `product-analysis.md` 与进入澄清前的冻结版本完全一致。
67
+ - [ ] 只有所有命令返回 0 才能声明完成。
68
+
69
+ 完整格式示例按需读取 `references/example.md`;维护或 forward-test 时读取 `references/forward-test-cases.md`。不要为了执行校验而阅读脚本,直接运行。
70
+
71
+ ## 完成规则
72
+
73
+ - `no-clarification-required` 仍生成三个产物;Clarification 使用“澄清结论、来源、合并结果”三章精简结构。
74
+ - `complete` Clarification 的全部分支必须 resolved,P0/P1 必须由用户确认,每个决策标记必须进入 Product Requirement 决策追溯。
75
+ - Product Requirement 必须自包含;读者不得依赖聊天、Product Analysis 或 Clarification 才能理解需求。
76
+ - Product Requirement 只描述目标产品行为,不记录代码库事实、证据位置或当前实现;不得出现 `CODE-FACT-*`、仓库文件路径、代码级类/函数/组件符号、模块调用关系、数据表名或实现算法。
77
+ - 不得生成独立用户角色、验收标准汇总、前后端契约、Open Questions、测试建议或独立边界 case 章节。
78
+
79
+ ## Validation
80
+
81
+ 把 `<skill-root>` 解析为本 `SKILL.md` 所在目录,全部参数使用绝对路径:
82
+
83
+ ```bash
84
+ node <skill-root>/scripts/validate-product-analysis.mjs <product-analysis.md> --target <frontend|backend|both>
85
+ node <skill-root>/scripts/validate-product-requirement.mjs <product-requirement.md> --target <frontend|backend|both>
86
+ node <skill-root>/scripts/validate-requirement-clarification.mjs <product-analysis.md> <requirement-clarification.md> <product-requirement.md>
87
+ node <skill-root>/scripts/test-validators.mjs
88
+ ```
89
+
90
+ 澄清中的中间产物可加 `--allow-pending`;通过 pending 校验不代表完成。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "产品需求分析"
3
+ short_description: "分析并按需澄清需求,生成故事、输出规范和验收标准"
4
+ default_prompt: "使用 $analyze-product-requirements 分析并按需澄清需求,生成完整 Product Requirement。"
@@ -0,0 +1,91 @@
1
+ # 详细验收标准规则
2
+
3
+ ## 目录
4
+
5
+ - 基本要求
6
+ - 分段最低要求
7
+ - 前端示例
8
+ - 后端示例
9
+ - 不合格写法
10
+
11
+ ## 基本要求
12
+
13
+ 每条验收标准必须独立可执行、结果可观察,并使用 Given/When/Then。一个用户故事存在多个关键流程时,拆成多个 AC,不要把互不相关的行为塞入一条 AC。
14
+
15
+ 每条 AC 必须说明:
16
+
17
+ 1. Given:用户身份、权限、业务数据、系统状态和必要依赖。
18
+ 2. When:具体操作、请求、事件或任务触发。
19
+ 3. Then:明确的 UI、状态、字段值、状态码、数据变化或日志结果。
20
+ 4. 异常场景:空数据、错误输入、无权限、超时、依赖失败及恢复方式。
21
+ 5. 禁止行为:不得泄露、重复提交、产生脏数据、白屏或静默失败等。
22
+
23
+ ## 分段最低要求
24
+
25
+ - Given:至少 1 个具体条目。
26
+ - When:至少 1 个具体条目。
27
+ - Then:至少 2 个可观察条目。
28
+ - 异常场景:至少 1 个条目;每个条目必须同时写明具体触发条件和可观察处理结果。
29
+ - 四段总计:至少 6 个条目。
30
+ - Then 或异常场景:至少包含一个禁止行为、失败保护、保留、恢复、重试或兜底结果。
31
+
32
+ 不得在 AC 中使用“功能正常、应正常展示、展示正确、接口可用、数据正确、符合预期、妥善处理、合理处理”等模糊结果。
33
+ 不得用“无异常情况”“没有需要处理的异常场景”“无需处理失败”等表述代替异常处理结果。
34
+
35
+ ## 前端示例
36
+
37
+ ```md
38
+ #### AC-FE-001 展示退款处理中状态
39
+
40
+ Given:
41
+ - 用户已登录且订单属于当前用户。
42
+ - 订单存在退款记录,refundStatus 为 processing。
43
+
44
+ When:
45
+ - 用户从订单列表进入该订单详情页。
46
+
47
+ Then:
48
+ - 退款进度模块展示“退款处理中”。
49
+ - 展示 currentStep 和格式化后的 updatedAt。
50
+ - 请求完成后 loading 状态消失。
51
+ - 页面不得展示其他订单的退款数据。
52
+
53
+ 异常场景:
54
+ - 请求超时时展示失败提示和重试入口。
55
+ - currentStep 缺失时展示“状态未知”,页面不得白屏。
56
+ ```
57
+
58
+ ## 后端示例
59
+
60
+ ```md
61
+ #### AC-BE-001 返回退款处理中状态
62
+
63
+ Given:
64
+ - 请求用户已认证且拥有目标订单。
65
+ - 退款记录状态为 processing。
66
+
67
+ When:
68
+ - 调用 GET /orders/{orderId}/refund-status。
69
+
70
+ Then:
71
+ - HTTP 状态码为 200。
72
+ - refundStatus 为 processing,failedReason 为 null。
73
+ - currentStep 与退款记录一致,updatedAt 使用约定时间格式。
74
+ - 响应不得包含内部错误堆栈或其他用户数据。
75
+
76
+ 异常场景:
77
+ - 订单不存在时返回 404 和标准错误结构。
78
+ - 无权访问时返回 403,且不得泄露订单详情。
79
+ ```
80
+
81
+ ## 不合格写法
82
+
83
+ 以下内容不能单独作为验收标准:
84
+
85
+ - 功能正常。
86
+ - 页面展示正确。
87
+ - 接口可用。
88
+ - 数据符合预期。
89
+ - 异常情况正确处理。
90
+
91
+ 必须将“正常、正确、可用、符合预期”替换为可核对的具体结果。
@@ -0,0 +1,56 @@
1
+ # 澄清、代码事实与合成规则
2
+
3
+ ## 1. 知识库与代码事实
4
+
5
+ 未执行知识检索时明确记录 `not-integrated`/`not-executed`,不得声称“未命中”或模拟记录。
6
+
7
+ 提供代码仓库时只做定向事实搜索:认证、权限、状态枚举、相似能力、字段类型、统一错误结构。事实使用 `CODE-FACT-*`,包含事实、证据位置和需求影响。代码只能回答现状,不能替代用户决定目标需求。
8
+
9
+ 知识或代码与需求冲突时:保留来源证据、生成澄清问题、用户裁决前不选边。
10
+
11
+ ## 2. 决策树式访谈
12
+
13
+ 1. 从 Product Analysis 的推断、问题、输出规范和高风险默认值提取 3–6 个顶层 `BR-*` 分支。
14
+ 2. 标注分支依赖,从范围、权限、核心流程、数据语义等基础决策开始。
15
+ 3. 每轮只处理一个主要问题:先给推荐答案和理由,再提问并等待回答。同分支、同依赖链的子项可合并,不相关问题不得换装为一题。
16
+ 4. 收到回答后重新识别剩余模糊点;仅在它们会影响范围、输出或验收时开启下一轮。
17
+ 5. 一次助手提问与用户回答记为一轮,总轮数不得超过 3。第 3 轮后仍有 P0/P1 时保持 pending 并阻断 Product Requirement complete;P2 按已记录的默认行为和影响处理。
18
+ 6. 所有分支解决后,用一段话总结关键决策。
19
+
20
+ ### 回答复核
21
+
22
+ 收到用户回答后,先判断它是否直接覆盖当前问题的关键决策点、是否只有一种合理的产品解释、是否足以写成明确的范围/规则/输出行为/验收结果、是否与原始明确需求或已有决策冲突,以及是否引入新的未定义概念、例外条件或依赖关系。全部满足时才形成最终决策并标记为 confirmed。
23
+
24
+ 任一条件不满足时:
25
+
26
+ - 保留用户原始回答,`最终决策` 写“未形成”并说明具体模糊点。
27
+ - P0/P1 使用 `pending-blocking`;P2 使用 `pending-non-blocking`,同时记录默认行为和未确认影响。
28
+ - 下一轮优先继续当前分支,明确指出上一轮回答仍不清晰的部分,并将问题收窄为可直接确认的决策点;不得原样重复问题或跳到其他分支。
29
+ - 不得把模型推断、推荐答案或代码现状当作用户确认。
30
+
31
+ 当前问题明确后,再扫描其他未解决问题和本次回答新引入的模糊点。只有会改变范围、权限、核心流程、数据语义、输出行为或验收结果的问题才继续澄清;不影响产品行为的措辞和下游技术细节不消耗澄清轮次。
32
+
33
+ 问题等级:
34
+
35
+ - P0:改变范围、权限、关键流程、数据语义或验收结果;必须由用户明确确认。
36
+ - P1:可以推荐默认值,但必须经用户确认。
37
+ - P2:可延后,但必须给出当前默认行为、影响和后续确认入口。
38
+
39
+ 没有问题时跳过交互访谈,不伪造分支、问题或决策标记,但仍生成完整 Clarification 检查记录。
40
+
41
+ ## 3. 合成规则
42
+
43
+ Product Analysis 冻结不回写。`最终决策` 是合成最终需求的规范化事实;`目标位置` 指向需求范围、业务规则、故事、输出规范或 AC。
44
+
45
+ 三个产物必须写入同一 `<project-root>/docs/product-analysis/<requirement-id>/`。同目录来源使用相对路径,避免把个人机器绝对路径写入可交接产物。
46
+
47
+ 生成 Product Requirement 时:
48
+
49
+ - 用户确认的推断转为正式需求。
50
+ - 用户否定的推断删除或进入非目标。
51
+ - 确认的默认值进入规则和故事。
52
+ - 代码库事实只用于解释现状、识别冲突和支持澄清,不作为独立需求来源;未经用户确认且未被原始需求明确要求的代码现状不得进入 Product Requirement。
53
+ - 需要合并的代码事实必须转换为目标产品语言,只保留用户可感知的行为、业务规则和验收结果;`CODE-FACT-*`、证据路径、代码符号、模块结构、数据表和实现过程继续留在 Product Analysis 或 Clarification。
54
+ - 决策影响故事时重新生成故事与 AC,不只在决策列表堆积答案。
55
+ - `DEC-Q-*` 在决策追溯中登记,并能定位到正式章节。
56
+ - 无需澄清时不生成任何 `DEC-Q-*`,说明需求直接来源于原始需求。
@@ -0,0 +1,86 @@
1
+ # V3 完整流程示例
2
+
3
+ 需求:登录用户在个人资料页修改昵称;昵称 2–20 个字符;保存失败时保留输入并允许重试;不修改头像。
4
+
5
+ ## Product Analysis 关键结构
6
+
7
+ ```md
8
+ ---
9
+ artifact_version: "3.0"
10
+ artifact_type: product-analysis
11
+ requirement_id: profile-nickname
12
+ project_root: ../../..
13
+ analysis_scope: frontend
14
+ analysis_status: no-clarification-required
15
+ source_requirement: inline
16
+ repository_root: none
17
+ ---
18
+
19
+ ## 6. 初步前端用户故事
20
+ ### FE-US-001 修改昵称
21
+ - 角色:已登录用户
22
+ - 目标:修改自己的展示昵称
23
+ - 价值:保持个人资料准确
24
+ - 入口:个人资料页
25
+ - 验收关注点:合法值可保存;非法值不可提交;失败时保留输入
26
+
27
+ ## 7. 初步前端输出规范
28
+ ### FE-US-001 修改昵称
29
+ - 页面/组件:个人资料页、昵称编辑表单
30
+ - 展示内容:当前昵称、字符计数、校验提示
31
+ - 交互动作:编辑、保存、取消、重试
32
+ - UI 状态:normal、dirty、loading、success、error、disabled
33
+ - 表单校验:昵称长度为 2–20 个字符
34
+ - 权限可见性:仅当前登录用户
35
+ - 边界处理:保存失败时保留输入,不得静默失败
36
+ ```
37
+
38
+ Product Analysis 不创建正式 AC。
39
+
40
+ ## 无需澄清记录
41
+
42
+ ```md
43
+ ## 1. 澄清结论
44
+ - 状态:no-clarification-required
45
+ - 原因:范围、权限、数据语义和验收结果已经明确。
46
+ ## 2. 来源
47
+ - Product Analysis:./product-analysis.md
48
+ ## 3. 合并结果
49
+ - Product Requirement 根据明确需求生成,无额外决策标记。
50
+ ```
51
+
52
+ ## Product Requirement 故事、规范与 AC
53
+
54
+ ```md
55
+ ## 5. 前端用户故事
56
+ ### FE-US-001 修改昵称
57
+ - 角色:已登录用户
58
+ - 目标:修改自己的展示昵称
59
+ - 价值:保持个人资料准确
60
+ - 入口:个人资料页
61
+ - 验收标准:AC-FE-001
62
+
63
+ ## 6. 前端输出规范
64
+ ### FE-US-001 修改昵称
65
+ - 页面/组件:个人资料页、昵称编辑表单
66
+ - 展示内容:当前昵称、字符计数、校验提示
67
+ - 交互动作:编辑、保存、取消、重试
68
+ - UI 状态:normal、dirty、loading、success、error、disabled
69
+ - 表单校验:昵称长度为 2–20 个字符
70
+ - 权限可见性:仅当前登录用户
71
+ - 边界处理:失败时保留输入,不得静默失败
72
+
73
+ #### AC-FE-001 保存合法昵称
74
+ Given:
75
+ - 用户已登录并打开个人资料页。
76
+ When:
77
+ - 用户输入合法昵称并点击保存。
78
+ Then:
79
+ - 页面提交昵称修改请求。
80
+ - 保存成功后展示新昵称。
81
+ - 保存期间按钮保持 disabled。
82
+ 异常场景:
83
+ - 保存失败时保留输入并提供重试入口。
84
+ ```
85
+
86
+ 故事与输出规范使用同一 ID;故事只引用 AC,AC 正文只在对应输出规范中出现一次。
@@ -0,0 +1,66 @@
1
+ # Forward-Test Cases
2
+
3
+ 在独立 agent 中逐个执行,不提供预期正文,只核对不变量。
4
+
5
+ ## Case 1:无需澄清
6
+
7
+ ```text
8
+ Use $analyze-product-requirements --target frontend.
9
+ 需求:登录用户在个人资料页修改自己的昵称;昵称 2–20 个字符;保存失败时保留输入并允许重试;不修改头像。
10
+ ```
11
+
12
+ 核对:三个产物都在 `<project-root>/docs/product-analysis/<requirement-id>/`;三者 `analysis_scope` 均为 `frontend`;Product Analysis 为 `no-clarification-required` 且不含正式 AC;Clarification 使用三章精简结构且没有 BR/Q/DEC;Product Requirement 为 complete;故事与同 ID 输出规范一一对应。
13
+
14
+ ## Case 2:需要逐题澄清
15
+
16
+ ```text
17
+ Use $analyze-product-requirements target=both.
18
+ 需求:管理员可以导出用户数据。
19
+ ```
20
+
21
+ 核对:先列 3–6 个分支;从管理员角色和敏感字段范围开始;每轮先推荐再只问一个主要问题;收到回答后重新识别模糊点;`clarification_rounds` 和问题轮次一致且最多为 3。第 3 轮后仍有 P0/P1 时保持 pending,不再提问、不自行补全;不得回写 Product Analysis。
22
+
23
+ ## Case 3:后端 API 业务需求
24
+
25
+ ```text
26
+ Use $analyze-product-requirements target=backend.
27
+ 需求:登录用户查询自己订单的退款状态,失败时看到可理解原因,内部错误不得泄露。
28
+ ```
29
+
30
+ 核对:BE 故事只保留能力、使用方、价值、触发方式和 AC 引用;同 ID 输出规范明确输入输出语义、权限和规则;不虚构最终 URL、HTTP 方法、DTO 或代码落点。
31
+
32
+ ## Case 4:非 API 后端任务
33
+
34
+ ```text
35
+ Use $analyze-product-requirements target=backend.
36
+ 需求:每天归档 90 天前已完成通知,重复执行不得重复归档。
37
+ ```
38
+
39
+ 核对:触发方式明确为定时任务;包含批次、幂等、并发和失败恢复;不会把它误标为 API。
40
+
41
+ ## Case 5:回答仍然模糊
42
+
43
+ ```text
44
+ Use $analyze-product-requirements target=both.
45
+ 需求:管理员可以导出用户数据。
46
+ 第一轮询问导出字段范围时,用户回答:敏感字段按实际情况处理。
47
+ ```
48
+
49
+ 核对:不得把该回答标记为 confirmed;保留原始回答,最终决策写“未形成”并说明无法确定的字段;当前分支保持 unresolved;下一轮继续当前分支并明确指出手机号、邮箱等字段仍未确定,给出可直接确认的推荐方案;不得跳到文件格式或导出入口。
50
+
51
+ ## Case 6:下一轮消除模糊
52
+
53
+ ```text
54
+ 沿用 Case 5。下一轮用户回答:导出邮箱,不导出手机号和身份证号。
55
+ ```
56
+
57
+ 核对:形成唯一字段规则并标记 confirmed;最终决策明确列出包含和排除字段;当前分支 resolved;重新扫描其他剩余问题和该回答新引入的模糊点;仅在仍会影响范围、规则、输出或验收时进入下一轮。
58
+
59
+ ## Case 7:代码事实不得泄漏到最终需求
60
+
61
+ ```text
62
+ Use $analyze-product-requirements target=backend,并提供一个仓库。
63
+ 需求:仅管理员可以导出用户数据。仓库中现有权限判断位于 src/auth/permission.ts,使用 role=admin。
64
+ ```
65
+
66
+ 核对:Product Analysis 可记录 `CODE-FACT-*`、证据路径和现状;Clarification 可引用该证据辅助判断,但不得把现状自动视为目标决策;Product Requirement 只写“仅管理员可以导出用户数据”等产品规则,不包含 `CODE-FACT-*`、`src/auth/permission.ts`、`role=admin`、代码符号、模块结构或当前实现过程。
@@ -0,0 +1,32 @@
1
+ # Product Analysis V3 输出契约
2
+
3
+ Product Analysis 是澄清前快照,只允许一次创建。首次写入后,正文、frontmatter 和路径全部冻结;需要更正时使用新的 `requirement_id`。
4
+
5
+ ```yaml
6
+ ---
7
+ artifact_version: "3.0"
8
+ artifact_type: product-analysis
9
+ requirement_id: <lowercase-slug>
10
+ project_root: ../../..
11
+ analysis_scope: frontend | backend | both
12
+ analysis_status: ready-for-clarification | no-clarification-required
13
+ source_requirement: <路径或 inline>
14
+ repository_root: <路径或 none>
15
+ ---
16
+ ```
17
+
18
+ 文件固定为 `<project-root>/docs/product-analysis/<requirement-id>/product-analysis.md`。
19
+
20
+ 固定章节:原始需求、需求概述、业务目标、需求分析、外部事实。需求分析包含明确需求、推断需求、待确认问题、初步非目标;外部事实包含知识库事实、代码库事实。
21
+
22
+ 按 scope 追加“初步前端用户故事/初步前端输出规范”或“初步后端用户故事/初步后端输出规范”。不得生成独立用户角色或验收标准汇总。
23
+
24
+ 前端故事字段:角色、目标、价值、入口、验收关注点。
25
+
26
+ 后端故事字段:系统能力、使用方、业务价值、触发方式、验收关注点。触发方式使用 API、定时任务、事件、消息、内部调用或数据迁移。
27
+
28
+ 每个故事必须恰好存在一个同 ID 输出规范。前端输出规范字段:页面/组件、展示内容、交互动作、UI 状态、表单校验、权限可见性、边界处理。后端输出规范字段:输入语义、输出语义、数据读写、权限规则、业务规则、安全要求、幂等与并发、错误与边界。
29
+
30
+ Product Analysis 只记录验收关注点,不得出现正式 `AC-FE-*`、`AC-BE-*` 或 Given/When/Then 块。
31
+
32
+ `no-clarification-required` 的待确认问题明确写“无”和理由,不得出现问题标记、优先级或问句;`ready-for-clarification` 至少包含一个带优先级或问号的问题。
@@ -0,0 +1,33 @@
1
+ # Product Requirement V3 输出契约
2
+
3
+ Product Requirement 是澄清后的完整需求文档和下游唯一需求事实源。
4
+
5
+ ```yaml
6
+ ---
7
+ artifact_version: "3.0"
8
+ artifact_type: product-requirement
9
+ requirement_id: <lowercase-slug>
10
+ project_root: ../../..
11
+ requirement_status: pending | complete
12
+ analysis_scope: frontend | backend | both
13
+ source_requirement: <路径或 inline>
14
+ source_product_analysis: ./product-analysis.md
15
+ source_clarification: ./requirement-clarification.md
16
+ ---
17
+ ```
18
+
19
+ 固定章节:需求概述、业务目标、需求范围、业务规则、决策追溯。需求范围包含已确认需求、非目标、默认假设、未决事项。不得生成独立用户角色或验收标准汇总。
20
+
21
+ Product Requirement 只描述目标产品行为,不承载代码侦察记录。不得包含 `CODE-FACT-*`、仓库文件路径、代码级类/函数/组件符号、模块调用关系、数据表名、证据位置、当前实现过程或实现算法。产品层的页面或组件名称仍可用于描述用户可见输出。代码库事实只可在经用户确认或被原始需求明确要求后,转换为不含实现细节的产品规则;原始证据保留在 Product Analysis 或 Clarification。
22
+
23
+ 按 scope 追加前端/后端用户故事和同域输出规范。
24
+
25
+ 前端故事字段:角色、目标、价值、入口、验收标准。后端故事字段:系统能力、使用方、业务价值、触发方式、验收标准。
26
+
27
+ 每个故事必须恰好存在一个同 ID 输出规范。前端规范字段:页面/组件、展示内容、交互动作、UI 状态、表单校验、权限可见性、边界处理。后端规范字段:输入语义、输出语义、数据读写、权限规则、业务规则、安全要求、幂等与并发、错误与边界。
28
+
29
+ 正式 `AC-FE-*` 或 `AC-BE-*` 作为四级标题嵌入对应输出规范。故事的验收标准引用必须与该规范中的 AC 完全一致;AC 遵循 `acceptance-criteria.md`。
30
+
31
+ 后端触发方式明确写 API、定时任务、事件、消息、内部调用或数据迁移,供下游判断 API 适用性。
32
+
33
+ `complete` 不得包含未解决 P0/P1。真实未决项以 `P0:`、`P1:` 或 `P2:` 开头。澄清决策使用 `DEC-Q-*` 在决策追溯中登记并定位到正式章节。
@@ -0,0 +1,35 @@
1
+ # Requirement Clarification V3 输出契约
2
+
3
+ ```yaml
4
+ ---
5
+ artifact_version: "3.0"
6
+ artifact_type: requirement-clarification
7
+ requirement_id: <lowercase-slug>
8
+ project_root: ../../..
9
+ analysis_scope: frontend | backend | both
10
+ clarification_status: pending | complete
11
+ clarification_rounds: 0 | 1 | 2 | 3
12
+ source_product_analysis: ./product-analysis.md
13
+ target_product_requirement: ./product-requirement.md
14
+ ---
15
+ ```
16
+
17
+ 文件与 Product Analysis、Product Requirement 位于同一需求目录。
18
+
19
+ ## 无需澄清
20
+
21
+ 只生成三个章节:澄清结论、来源、合并结果。`clarification_rounds` 必须为 `0`。澄清结论写明 `no-clarification-required` 和理由;不得生成 `BR-*`、`Q-*`、`DEC-Q-*`。
22
+
23
+ ## 需要澄清
24
+
25
+ 固定章节:澄清来源、决策分支、问题记录、决策索引。定义 3–6 个 `BR-*` 分支,表格包含分支 ID、名称、优先级、依赖和状态。
26
+
27
+ 问题核心字段:澄清轮次、分支、优先级、影响范围、推荐答案、推荐理由、用户回答、最终决策、决策来源、状态、决策标记、目标位置。`clarification_rounds` 必须为 `1`–`3`,每个问题的澄清轮次不得超过该值。
28
+
29
+ 条件字段:有前置依赖时写依赖问题;存在真实备选时写备选方案;决策来源为 `code-evidence` 时写代码证据;状态为 `pending-non-blocking` 时写未确认影响。
30
+
31
+ 状态使用 confirmed、default-confirmed、pending-blocking、pending-non-blocking;决策来源使用 user、source-requirement、code-evidence、confirmed-default。决策标记必须为 `DEC-Q-*`。
32
+
33
+ `complete` 要求全部分支 resolved;P0/P1 必须由用户明确回答并使用 confirmed/user;P2 可确认、使用已确认默认值,或在写明影响后延后。complete 时每个决策标记必须出现在 Product Requirement 的决策追溯中。
34
+
35
+ 每轮在用户回答后重新识别模糊点,有必要才再澄清。最多 3 轮;第 3 轮后仍有 P0/P1 时产物必须保持 `pending`,不得继续追问或自行填补决策。