cc-devflow 1.0.1

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 (277) hide show
  1. package/.claude/CLAUDE.md +83 -0
  2. package/.claude/agents/architecture-designer.md +443 -0
  3. package/.claude/agents/bug-analyzer.md +382 -0
  4. package/.claude/agents/checklist-agent.md +175 -0
  5. package/.claude/agents/clarify-analyst.md +50 -0
  6. package/.claude/agents/code-reviewer.md +71 -0
  7. package/.claude/agents/codex-analyzer.md +39 -0
  8. package/.claude/agents/compatibility-checker.md +580 -0
  9. package/.claude/agents/consistency-checker.md +532 -0
  10. package/.claude/agents/impact-analyzer.md +441 -0
  11. package/.claude/agents/planner.md +230 -0
  12. package/.claude/agents/prd-writer.md +320 -0
  13. package/.claude/agents/project-guidelines-generator.md +1329 -0
  14. package/.claude/agents/qa-tester.md +313 -0
  15. package/.claude/agents/release-manager.md +295 -0
  16. package/.claude/agents/security-reviewer.md +314 -0
  17. package/.claude/agents/style-guide-generator.md +458 -0
  18. package/.claude/agents/tech-architect.md +516 -0
  19. package/.claude/agents/ui-designer.md +485 -0
  20. package/.claude/commands/code-review-high.md +58 -0
  21. package/.claude/commands/core-architecture.md +429 -0
  22. package/.claude/commands/core-guidelines.md +486 -0
  23. package/.claude/commands/core-roadmap.md +439 -0
  24. package/.claude/commands/core-style.md +293 -0
  25. package/.claude/commands/flow-archive.md +245 -0
  26. package/.claude/commands/flow-checklist.md +260 -0
  27. package/.claude/commands/flow-clarify.md +136 -0
  28. package/.claude/commands/flow-constitution.md +82 -0
  29. package/.claude/commands/flow-dev.md +134 -0
  30. package/.claude/commands/flow-epic.md +150 -0
  31. package/.claude/commands/flow-fix.md +104 -0
  32. package/.claude/commands/flow-ideate.md +214 -0
  33. package/.claude/commands/flow-init.md +313 -0
  34. package/.claude/commands/flow-new.md +394 -0
  35. package/.claude/commands/flow-prd.md +131 -0
  36. package/.claude/commands/flow-qa.md +93 -0
  37. package/.claude/commands/flow-release.md +92 -0
  38. package/.claude/commands/flow-restart.md +98 -0
  39. package/.claude/commands/flow-status.md +64 -0
  40. package/.claude/commands/flow-tech.md +142 -0
  41. package/.claude/commands/flow-ui.md +189 -0
  42. package/.claude/commands/flow-update.md +111 -0
  43. package/.claude/commands/flow-upgrade.md +115 -0
  44. package/.claude/commands/flow-verify.md +96 -0
  45. package/.claude/commands/problem-analyzer.md +60 -0
  46. package/.claude/config/quality-rules.yml +161 -0
  47. package/.claude/docs/SPEC_KIT_CONSTITUTION_ANALYSIS.md +426 -0
  48. package/.claude/docs/design/consistency-conflict-detection-algorithms.md +658 -0
  49. package/.claude/docs/design/intent-driven-input-design.md +380 -0
  50. package/.claude/docs/design/prd-version-management-design.md +437 -0
  51. package/.claude/docs/guides/INIT_TROUBLESHOOTING.md +117 -0
  52. package/.claude/docs/guides/NEW_TROUBLESHOOTING.md +151 -0
  53. package/.claude/docs/guides/ROADMAP_TROUBLESHOOTING.md +188 -0
  54. package/.claude/docs/guides/TASK_COMPLETION_MARKING.md +338 -0
  55. package/.claude/docs/templates/ARCHITECTURE_TEMPLATE.md +633 -0
  56. package/.claude/docs/templates/BACKLOG_TEMPLATE.md +261 -0
  57. package/.claude/docs/templates/CHECKLIST_TEMPLATE.md +52 -0
  58. package/.claude/docs/templates/CLARIFICATION_REPORT_TEMPLATE.md +206 -0
  59. package/.claude/docs/templates/CODE_REVIEW_TEMPLATE.md +71 -0
  60. package/.claude/docs/templates/EPIC_TEMPLATE.md +805 -0
  61. package/.claude/docs/templates/INIT_FLOW_TEMPLATE.md +213 -0
  62. package/.claude/docs/templates/INTENT_CLARIFICATION_TEMPLATE.md +57 -0
  63. package/.claude/docs/templates/NEW_ORCHESTRATION_TEMPLATE.md +148 -0
  64. package/.claude/docs/templates/PRD_TEMPLATE.md +562 -0
  65. package/.claude/docs/templates/RESEARCH_TEMPLATE.md +276 -0
  66. package/.claude/docs/templates/REVIEW-HIGH.md +57 -0
  67. package/.claude/docs/templates/ROADMAP_DIALOGUE_TEMPLATE.md +198 -0
  68. package/.claude/docs/templates/ROADMAP_TEMPLATE.md +310 -0
  69. package/.claude/docs/templates/STYLE_TEMPLATE.md +1266 -0
  70. package/.claude/docs/templates/TASKS_TEMPLATE.md +523 -0
  71. package/.claude/docs/templates/TECH_DESIGN_TEMPLATE.md +1019 -0
  72. package/.claude/docs/templates/UI_PROTOTYPE_TEMPLATE.md +1436 -0
  73. package/.claude/guides/agent-guides/agent-coordination-guide.md +459 -0
  74. package/.claude/guides/project-guidelines-system.md +463 -0
  75. package/.claude/guides/technical-guides/datetime-handling-guide.md +563 -0
  76. package/.claude/guides/technical-guides/git-github-guide.md +642 -0
  77. package/.claude/guides/technical-guides/test-execution-guide.md +618 -0
  78. package/.claude/guides/workflow-guides/bug-fix-orchestrator.md +217 -0
  79. package/.claude/guides/workflow-guides/flow-orchestrator.md +282 -0
  80. package/.claude/hooks/checklist-gate.js +397 -0
  81. package/.claude/hooks/error-handling-reminder.sh +12 -0
  82. package/.claude/hooks/error-handling-reminder.ts +459 -0
  83. package/.claude/hooks/post-tool-use-tracker.sh +280 -0
  84. package/.claude/hooks/pre-tool-use-guardrail.sh +36 -0
  85. package/.claude/hooks/pre-tool-use-guardrail.ts +342 -0
  86. package/.claude/hooks/skill-activation-prompt.sh +36 -0
  87. package/.claude/hooks/skill-activation-prompt.ts +214 -0
  88. package/.claude/hooks/state/skills-used-test-guard.json +3 -0
  89. package/.claude/rules/devflow-conventions.md +305 -0
  90. package/.claude/rules/project-constitution.md +748 -0
  91. package/.claude/schemas/constitution.schema.json +43 -0
  92. package/.claude/scripts/analyze-upgrade-impact.sh +200 -0
  93. package/.claude/scripts/archive-requirement.sh +351 -0
  94. package/.claude/scripts/calculate-checklist-completion.sh +243 -0
  95. package/.claude/scripts/calculate-quarter.sh +206 -0
  96. package/.claude/scripts/check-dependencies.sh +409 -0
  97. package/.claude/scripts/check-prerequisites.sh +232 -0
  98. package/.claude/scripts/check-task-status.sh +264 -0
  99. package/.claude/scripts/checklist-errors.sh +131 -0
  100. package/.claude/scripts/common.sh +570 -0
  101. package/.claude/scripts/consolidate-research.sh +182 -0
  102. package/.claude/scripts/create-requirement.sh +426 -0
  103. package/.claude/scripts/export-contracts.sh +117 -0
  104. package/.claude/scripts/extract-data-model.sh +78 -0
  105. package/.claude/scripts/generate-clarification-questions.sh +377 -0
  106. package/.claude/scripts/generate-clarification-report.sh +463 -0
  107. package/.claude/scripts/generate-quickstart.sh +146 -0
  108. package/.claude/scripts/generate-research-tasks.sh +157 -0
  109. package/.claude/scripts/generate-status-report.sh +523 -0
  110. package/.claude/scripts/generate-tech-analysis.sh +46 -0
  111. package/.claude/scripts/locate-requirement-in-roadmap.sh +233 -0
  112. package/.claude/scripts/manage-constitution.sh +602 -0
  113. package/.claude/scripts/mark-task-complete.sh +198 -0
  114. package/.claude/scripts/populate-research-tasks.sh +259 -0
  115. package/.claude/scripts/recover-workflow.sh +460 -0
  116. package/.claude/scripts/run-clarify-scan.sh +601 -0
  117. package/.claude/scripts/run-high-review.sh +62 -0
  118. package/.claude/scripts/run-problem-analysis.sh +68 -0
  119. package/.claude/scripts/setup-epic.sh +173 -0
  120. package/.claude/scripts/sync-roadmap-progress.sh +300 -0
  121. package/.claude/scripts/sync-task-marks.sh +199 -0
  122. package/.claude/scripts/test-clarify-scan.sh +515 -0
  123. package/.claude/scripts/update-agent-context.sh +806 -0
  124. package/.claude/scripts/validate-constitution.sh +567 -0
  125. package/.claude/scripts/validate-hooks.sh +487 -0
  126. package/.claude/scripts/validate-research.sh +332 -0
  127. package/.claude/scripts/validate-scope-boundary.sh +493 -0
  128. package/.claude/scripts/verify-setup.sh +37 -0
  129. package/.claude/settings.json +76 -0
  130. package/.claude/skills/_reference-implementations/README.md +96 -0
  131. package/.claude/skills/_reference-implementations/backend-express-prisma/SKILL.md +302 -0
  132. package/.claude/skills/_reference-implementations/backend-express-prisma/resources/architecture-overview.md +451 -0
  133. package/.claude/skills/_reference-implementations/backend-express-prisma/resources/async-and-errors.md +307 -0
  134. package/.claude/skills/_reference-implementations/backend-express-prisma/resources/complete-examples.md +638 -0
  135. package/.claude/skills/_reference-implementations/backend-express-prisma/resources/configuration.md +275 -0
  136. package/.claude/skills/_reference-implementations/backend-express-prisma/resources/database-patterns.md +224 -0
  137. package/.claude/skills/_reference-implementations/backend-express-prisma/resources/middleware-guide.md +213 -0
  138. package/.claude/skills/_reference-implementations/backend-express-prisma/resources/routing-and-controllers.md +756 -0
  139. package/.claude/skills/_reference-implementations/backend-express-prisma/resources/sentry-and-monitoring.md +336 -0
  140. package/.claude/skills/_reference-implementations/backend-express-prisma/resources/services-and-repositories.md +789 -0
  141. package/.claude/skills/_reference-implementations/backend-express-prisma/resources/testing-guide.md +235 -0
  142. package/.claude/skills/_reference-implementations/backend-express-prisma/resources/validation-patterns.md +754 -0
  143. package/.claude/skills/_reference-implementations/frontend-react-mui/SKILL.md +399 -0
  144. package/.claude/skills/_reference-implementations/frontend-react-mui/resources/common-patterns.md +331 -0
  145. package/.claude/skills/_reference-implementations/frontend-react-mui/resources/complete-examples.md +872 -0
  146. package/.claude/skills/_reference-implementations/frontend-react-mui/resources/component-patterns.md +502 -0
  147. package/.claude/skills/_reference-implementations/frontend-react-mui/resources/data-fetching.md +767 -0
  148. package/.claude/skills/_reference-implementations/frontend-react-mui/resources/file-organization.md +502 -0
  149. package/.claude/skills/_reference-implementations/frontend-react-mui/resources/loading-and-error-states.md +501 -0
  150. package/.claude/skills/_reference-implementations/frontend-react-mui/resources/performance.md +406 -0
  151. package/.claude/skills/_reference-implementations/frontend-react-mui/resources/routing-guide.md +364 -0
  152. package/.claude/skills/_reference-implementations/frontend-react-mui/resources/styling-guide.md +428 -0
  153. package/.claude/skills/_reference-implementations/frontend-react-mui/resources/typescript-standards.md +418 -0
  154. package/.claude/skills/cc-devflow-orchestrator/SKILL.md +229 -0
  155. package/.claude/skills/constitution-guardian/SKILL.md +306 -0
  156. package/.claude/skills/devflow-constitution-quick-ref/SKILL.md +374 -0
  157. package/.claude/skills/devflow-file-standards/SKILL.md +353 -0
  158. package/.claude/skills/devflow-tdd-enforcer/SKILL.md +192 -0
  159. package/.claude/skills/skill-developer/ADVANCED.md +197 -0
  160. package/.claude/skills/skill-developer/HOOK_MECHANISMS.md +306 -0
  161. package/.claude/skills/skill-developer/PATTERNS_LIBRARY.md +152 -0
  162. package/.claude/skills/skill-developer/SKILL.md +426 -0
  163. package/.claude/skills/skill-developer/SKILL_RULES_REFERENCE.md +315 -0
  164. package/.claude/skills/skill-developer/TRIGGER_TYPES.md +305 -0
  165. package/.claude/skills/skill-developer/TROUBLESHOOTING.md +514 -0
  166. package/.claude/skills/skill-rules.json +213 -0
  167. package/.claude/tests/README.md +300 -0
  168. package/.claude/tests/TODO.md +69 -0
  169. package/.claude/tests/__pycache__/test_analyze_upgrade_impact.cpython-311-pytest-7.2.2.pyc +0 -0
  170. package/.claude/tests/__pycache__/test_consolidate_research.cpython-311-pytest-7.2.2.pyc +0 -0
  171. package/.claude/tests/__pycache__/test_export_contracts.cpython-311-pytest-7.2.2.pyc +0 -0
  172. package/.claude/tests/__pycache__/test_extract_data_model.cpython-311-pytest-7.2.2.pyc +0 -0
  173. package/.claude/tests/__pycache__/test_generate_quickstart.cpython-311-pytest-7.2.2.pyc +0 -0
  174. package/.claude/tests/__pycache__/test_generate_research_tasks.cpython-311-pytest-7.2.2.pyc +0 -0
  175. package/.claude/tests/constitution/run_all_constitution_tests.sh +111 -0
  176. package/.claude/tests/constitution/test_agent_assignment.sh +207 -0
  177. package/.claude/tests/constitution/test_article_coverage.sh +201 -0
  178. package/.claude/tests/constitution/test_template_completeness.sh +150 -0
  179. package/.claude/tests/constitution/test_version_consistency.sh +120 -0
  180. package/.claude/tests/fixtures/spec_delta_full.md +16 -0
  181. package/.claude/tests/fixtures/tasks_progress_sample.md +5 -0
  182. package/.claude/tests/run-all-tests.sh +229 -0
  183. package/.claude/tests/scripts/run.sh +30 -0
  184. package/.claude/tests/scripts/test-framework.sh +128 -0
  185. package/.claude/tests/scripts/test_check_prerequisites.sh +511 -0
  186. package/.claude/tests/scripts/test_check_prerequisites.sh.bak +504 -0
  187. package/.claude/tests/scripts/test_check_prerequisites.sh.bak2 +505 -0
  188. package/.claude/tests/scripts/test_check_prerequisites.sh.bak3 +506 -0
  189. package/.claude/tests/scripts/test_check_prerequisites.sh.bak4 +507 -0
  190. package/.claude/tests/scripts/test_check_prerequisites.sh.bak5 +508 -0
  191. package/.claude/tests/scripts/test_check_task_status.sh +499 -0
  192. package/.claude/tests/scripts/test_common.sh +244 -0
  193. package/.claude/tests/scripts/test_generate_status_report.sh +71 -0
  194. package/.claude/tests/scripts/test_mark_task_complete.sh +441 -0
  195. package/.claude/tests/scripts/test_mark_task_complete.sh.backup +410 -0
  196. package/.claude/tests/scripts/test_recover_workflow.sh +304 -0
  197. package/.claude/tests/scripts/test_setup_epic.sh +437 -0
  198. package/.claude/tests/scripts/test_sync_task_marks.sh +196 -0
  199. package/.claude/tests/scripts/test_validate_constitution.sh +74 -0
  200. package/.claude/tests/scripts/test_validate_research.sh +462 -0
  201. package/.claude/tests/slugify.bats +82 -0
  202. package/.claude/tests/test-framework.sh +732 -0
  203. package/.claude/tests/test_analyze_upgrade_impact.py +34 -0
  204. package/.claude/tests/test_consolidate_research.py +48 -0
  205. package/.claude/tests/test_export_contracts.py +43 -0
  206. package/.claude/tests/test_extract_data_model.py +33 -0
  207. package/.claude/tests/test_generate_quickstart.py +50 -0
  208. package/.claude/tests/test_generate_research_tasks.py +52 -0
  209. package/.claude/tsc-cache/6e64f818-6398-49ca-8623-581a9af85c44/edited-files.log +1 -0
  210. package/.claude/tsc-cache/795ba6e3-b98a-423b-bab2-51aa62812569/affected-repos.txt +1 -0
  211. package/.claude/tsc-cache/795ba6e3-b98a-423b-bab2-51aa62812569/edited-files.log +1 -0
  212. package/.claude/tsc-cache/ae335694-be5a-4ba4-a1a0-b676c09a7906/affected-repos.txt +1 -0
  213. package/.claude/tsc-cache/ae335694-be5a-4ba4-a1a0-b676c09a7906/edited-files.log +1 -0
  214. package/CHANGELOG.md +507 -0
  215. package/LICENSE +21 -0
  216. package/README.md +534 -0
  217. package/README.zh-CN.md +530 -0
  218. package/bin/adapt.js +240 -0
  219. package/bin/cc-devflow-cli.js +185 -0
  220. package/bin/cc-devflow.js +78 -0
  221. package/config/adapters.yml +5 -0
  222. package/config/schema/adapters.schema.json +44 -0
  223. package/docs/CLAUDE.md +26 -0
  224. package/docs/commands/README.md +61 -0
  225. package/docs/commands/README.zh-CN.md +55 -0
  226. package/docs/commands/core-roadmap.md +106 -0
  227. package/docs/commands/core-roadmap.zh-CN.md +102 -0
  228. package/docs/commands/core-style.md +405 -0
  229. package/docs/commands/core-style.zh-CN.md +405 -0
  230. package/docs/commands/flow-init.md +134 -0
  231. package/docs/commands/flow-init.zh-CN.md +163 -0
  232. package/docs/commands/flow-new.md +274 -0
  233. package/docs/commands/flow-new.zh-CN.md +270 -0
  234. package/docs/guides/getting-started.md +204 -0
  235. package/docs/guides/getting-started.zh-CN.md +152 -0
  236. package/lib/adapters/adapter-interface.js +57 -0
  237. package/lib/adapters/claude-adapter.js +74 -0
  238. package/lib/adapters/codex-adapter.js +40 -0
  239. package/lib/adapters/config-validator.js +68 -0
  240. package/lib/adapters/logger.js +42 -0
  241. package/lib/adapters/registry.js +153 -0
  242. package/lib/compiler/CLAUDE.md +92 -0
  243. package/lib/compiler/__tests__/drift.test.js +215 -0
  244. package/lib/compiler/__tests__/errors.test.js +184 -0
  245. package/lib/compiler/__tests__/incremental.test.js +174 -0
  246. package/lib/compiler/__tests__/integration.test.js +174 -0
  247. package/lib/compiler/__tests__/manifest.test.js +233 -0
  248. package/lib/compiler/__tests__/parser.test.js +456 -0
  249. package/lib/compiler/__tests__/schemas.test.js +301 -0
  250. package/lib/compiler/__tests__/skills-registry.test.js +125 -0
  251. package/lib/compiler/__tests__/transformer.test.js +286 -0
  252. package/lib/compiler/emitters/antigravity-emitter.js +171 -0
  253. package/lib/compiler/emitters/base-emitter.js +73 -0
  254. package/lib/compiler/emitters/codex-emitter.js +52 -0
  255. package/lib/compiler/emitters/cursor-emitter.js +31 -0
  256. package/lib/compiler/emitters/index.js +50 -0
  257. package/lib/compiler/emitters/qwen-emitter.js +39 -0
  258. package/lib/compiler/errors.js +119 -0
  259. package/lib/compiler/index.js +256 -0
  260. package/lib/compiler/manifest.js +242 -0
  261. package/lib/compiler/parser.js +258 -0
  262. package/lib/compiler/platforms.js +113 -0
  263. package/lib/compiler/resource-copier.js +320 -0
  264. package/lib/compiler/rules-emitters/__tests__/antigravity-rules-emitter.test.js +191 -0
  265. package/lib/compiler/rules-emitters/__tests__/codex-rules-emitter.test.js +109 -0
  266. package/lib/compiler/rules-emitters/__tests__/cursor-rules-emitter.test.js +123 -0
  267. package/lib/compiler/rules-emitters/__tests__/qwen-rules-emitter.test.js +123 -0
  268. package/lib/compiler/rules-emitters/antigravity-rules-emitter.js +253 -0
  269. package/lib/compiler/rules-emitters/base-rules-emitter.js +83 -0
  270. package/lib/compiler/rules-emitters/codex-rules-emitter.js +116 -0
  271. package/lib/compiler/rules-emitters/cursor-rules-emitter.js +98 -0
  272. package/lib/compiler/rules-emitters/index.js +71 -0
  273. package/lib/compiler/rules-emitters/qwen-rules-emitter.js +70 -0
  274. package/lib/compiler/schemas.js +144 -0
  275. package/lib/compiler/skills-registry.js +225 -0
  276. package/lib/compiler/transformer.js +236 -0
  277. package/package.json +50 -0
@@ -0,0 +1,504 @@
1
+ #!/usr/bin/env bash
2
+ # test_check_prerequisites.sh - 测试 check-prerequisites.sh
3
+ # 注意: check-prerequisites.sh 通过环境变量 DEVFLOW_REQ_ID 或 Git 分支获取 REQ_ID
4
+
5
+ # 加载测试框架
6
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
+ source "$SCRIPT_DIR/../test-framework.sh"
8
+
9
+ # 脚本路径
10
+ REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
11
+ CHECK_PREREQ_SCRIPT="$REPO_ROOT/scripts/check-prerequisites.sh"
12
+
13
+ # ============================================================================
14
+ # 辅助函数
15
+ # ============================================================================
16
+
17
+ # 创建完整的模拟需求目录结构
18
+ setup_full_requirement() {
19
+ local req_id="$1"
20
+ local req_dir="$TEST_TMP_DIR/.claude/docs/requirements/$req_id"
21
+
22
+ mkdir -p "$req_dir"/{research,tasks}
23
+
24
+ # 创建状态文件
25
+ cat > "$req_dir/orchestration_status.json" << EOF
26
+ {
27
+ "reqId": "$req_id",
28
+ "title": "Test Requirement",
29
+ "status": "prd_complete",
30
+ "phase": "epic_planning",
31
+ "createdAt": "2025-10-01T00:00:00Z",
32
+ "updatedAt": "2025-10-01T00:00:00Z"
33
+ }
34
+ EOF
35
+
36
+ # 创建必需文档
37
+ echo "# PRD" > "$req_dir/PRD.md"
38
+ echo "# Execution Log" > "$req_dir/EXECUTION_LOG.md"
39
+
40
+ echo "$req_dir"
41
+ }
42
+
43
+ # 创建测试专用的 common.sh(覆盖 get_repo_root 函数)
44
+ create_test_common() {
45
+ local test_common="$TEST_TMP_DIR/scripts/common.sh"
46
+ mkdir -p "$(dirname "$test_common")"
47
+
48
+ # 复制原始 common.sh 到临时文件
49
+ cp "$REPO_ROOT/scripts/common.sh" "$test_common"
50
+
51
+ # 使用 awk 替换 get_repo_root 函数
52
+ awk -v tmpdir="$TEST_TMP_DIR" '
53
+ /^get_repo_root\(\)/ {
54
+ print "get_repo_root() {"
55
+ print " echo \"" tmpdir "\""
56
+ print "}"
57
+ in_function = 1
58
+ next
59
+ }
60
+ in_function && /^}/ {
61
+ in_function = 0
62
+ next
63
+ }
64
+ !in_function {
65
+ print
66
+ }
67
+ ' "$REPO_ROOT/scripts/common.sh" > "$test_common.tmp"
68
+
69
+ mv "$test_common.tmp" "$test_common"
70
+ }
71
+
72
+ # 在测试环境中运行脚本并捕获退出码
73
+ run_check_prereq_with_exit() {
74
+ local req_id="$1"
75
+ shift
76
+ local args=("$@")
77
+
78
+ # 设置环境
79
+ export DEVFLOW_REQ_ID="$req_id"
80
+
81
+ # 创建测试专用的脚本副本
82
+ local test_scripts_dir="$TEST_TMP_DIR/scripts"
83
+ mkdir -p "$test_scripts_dir"
84
+
85
+ # 创建测试专用的 common.sh
86
+ create_test_common
87
+
88
+ # 复制 check-prerequisites.sh 到测试目录
89
+ cp "$CHECK_PREREQ_SCRIPT" "$test_scripts_dir/"
90
+
91
+ # 运行脚本并保存输出和退出码
92
+ local output_file="$TEST_TMP_DIR/output.txt"
93
+ local exit_code_file="$TEST_TMP_DIR/exitcode.txt"
94
+
95
+ (
96
+ cd "$TEST_TMP_DIR"
97
+ bash "$test_scripts_dir/check-prerequisites.sh" "${args[@]}" > "$output_file" 2>&1
98
+ echo $? > "$exit_code_file"
99
+ )
100
+
101
+ # 返回输出(退出码需要从文件读取)
102
+ cat "$output_file"
103
+ }
104
+
105
+ # 获取最后一次运行的退出码
106
+ get_last_exit_code() {
107
+ cat "$TEST_TMP_DIR/exitcode.txt" 2>/dev/null || echo "0"
108
+ }
109
+
110
+ # 在测试环境中运行脚本(旧版本,向后兼容)
111
+ run_check_prereq() {
112
+ local req_id="$1"
113
+ shift
114
+ local args=("$@")
115
+
116
+ # 设置环境
117
+ export DEVFLOW_REQ_ID="$req_id"
118
+
119
+ # 创建测试专用的脚本副本
120
+ local test_scripts_dir="$TEST_TMP_DIR/scripts"
121
+ mkdir -p "$test_scripts_dir"
122
+
123
+ # 创建测试专用的 common.sh
124
+ create_test_common
125
+
126
+ # 复制 check-prerequisites.sh 到测试目录
127
+ cp "$CHECK_PREREQ_SCRIPT" "$test_scripts_dir/"
128
+
129
+ # 在测试目录中运行脚本
130
+ (
131
+ cd "$TEST_TMP_DIR"
132
+ bash "$test_scripts_dir/check-prerequisites.sh" "${args[@]}" 2>&1
133
+ )
134
+ }
135
+
136
+ # ============================================================================
137
+ # 测试帮助信息
138
+ # ============================================================================
139
+
140
+ test_help_flag() {
141
+ describe "Should show help with --help"
142
+
143
+ # Act
144
+ local output=$(bash "$CHECK_PREREQ_SCRIPT" --help 2>&1)
145
+
146
+ # Assert
147
+ assert_contains "$output" "Usage:" "Should show usage"
148
+ assert_contains "$output" "check-prerequisites.sh" "Should mention script name"
149
+ assert_contains "$output" "--json" "Should document --json flag"
150
+ assert_contains "$output" "--paths-only" "Should document --paths-only flag"
151
+ }
152
+
153
+ test_help_short_flag() {
154
+ describe "Should show help with -h"
155
+
156
+ # Act
157
+ local output=$(bash "$CHECK_PREREQ_SCRIPT" -h 2>&1)
158
+
159
+ # Assert
160
+ assert_contains "$output" "Usage:" "Should show usage with -h"
161
+ }
162
+
163
+ # ============================================================================
164
+ # 测试无 REQ_ID 的情况
165
+ # ============================================================================
166
+
167
+ test_no_req_id_error() {
168
+ describe "Should fail when no REQ_ID is available"
169
+
170
+ # Arrange - 创建测试脚本副本但不设置 REQ_ID
171
+ local test_scripts_dir="$TEST_TMP_DIR/scripts"
172
+ mkdir -p "$test_scripts_dir"
173
+ create_test_common
174
+ cp "$CHECK_PREREQ_SCRIPT" "$test_scripts_dir/"
175
+
176
+ # Act - 不设置 DEVFLOW_REQ_ID 环境变量
177
+ local output_file="$TEST_TMP_DIR/output.txt"
178
+ local exit_code_file="$TEST_TMP_DIR/exitcode.txt"
179
+
180
+ (
181
+ cd "$TEST_TMP_DIR"
182
+ unset DEVFLOW_REQ_ID
183
+ bash "$test_scripts_dir/check-prerequisites.sh" > "$output_file" 2>&1
184
+ echo $? > "$exit_code_file"
185
+ )
186
+
187
+ local output=$(cat "$output_file")
188
+ local exit_code=$(cat "$exit_code_file")
189
+
190
+ # Assert
191
+ assert_not_equals "$exit_code" "0" "Should fail without REQ_ID"
192
+ assert_contains "$output" "ERROR" "Should show error message"
193
+ }
194
+
195
+ # ============================================================================
196
+ # 测试 --paths-only 模式
197
+ # ============================================================================
198
+
199
+ test_paths_only_mode() {
200
+ describe "Should output paths in --paths-only mode"
201
+
202
+ # Arrange
203
+ local req_id="REQ-001"
204
+ setup_full_requirement "$req_id"
205
+
206
+ # Act
207
+ local output=$(run_check_prereq "$req_id" --paths-only)
208
+
209
+ # Assert
210
+ assert_contains "$output" "REPO_ROOT:" "Should output REPO_ROOT"
211
+ assert_contains "$output" "REQ_ID:" "Should output REQ_ID"
212
+ assert_contains "$output" "REQ_DIR:" "Should output REQ_DIR"
213
+ assert_contains "$output" "PRD_FILE:" "Should output PRD_FILE"
214
+ }
215
+
216
+ test_paths_only_json_mode() {
217
+ describe "Should output JSON in --paths-only --json mode"
218
+
219
+ # Arrange
220
+ local req_id="REQ-002"
221
+ setup_full_requirement "$req_id"
222
+
223
+ # Act
224
+ local output=$(run_check_prereq "$req_id" --paths-only --json)
225
+
226
+ # Assert
227
+ assert_json_valid "$output" "Should output valid JSON"
228
+ assert_contains "$output" "\"REPO_ROOT\"" "Should have REPO_ROOT in JSON"
229
+ assert_contains "$output" "\"REQ_ID\"" "Should have REQ_ID in JSON"
230
+ assert_contains "$output" "\"REQ_DIR\"" "Should have REQ_DIR in JSON"
231
+ }
232
+
233
+ # ============================================================================
234
+ # 测试必需文件验证
235
+ # ============================================================================
236
+
237
+ test_missing_req_dir() {
238
+ describe "Should fail when requirement directory doesn't exist"
239
+
240
+ # Arrange
241
+ local req_id="REQ-NOTEXIST"
242
+ # 不创建目录
243
+
244
+ # Act
245
+ local exit_code=0
246
+ local output=$(run_check_prereq "$req_id" 2>&1) || exit_code=$?
247
+
248
+ # Assert
249
+ assert_not_equals "$exit_code" "0" "Should fail when REQ_DIR missing"
250
+ assert_contains "$output" "ERROR" "Should show error"
251
+ assert_contains "$output" "directory not found" "Should mention missing directory"
252
+ }
253
+
254
+ test_missing_prd_file() {
255
+ describe "Should fail when PRD.md doesn't exist"
256
+
257
+ # Arrange
258
+ local req_id="REQ-003"
259
+ local req_dir="$TEST_TMP_DIR/.claude/docs/requirements/$req_id"
260
+ mkdir -p "$req_dir"
261
+ # 不创建 PRD.md
262
+
263
+ # Act
264
+ local exit_code=0
265
+ local output=$(run_check_prereq "$req_id" 2>&1) || exit_code=$?
266
+
267
+ # Assert
268
+ assert_not_equals "$exit_code" "0" "Should fail when PRD.md missing"
269
+ assert_contains "$output" "PRD.md not found" "Should mention missing PRD"
270
+ }
271
+
272
+ test_valid_minimal_requirement() {
273
+ describe "Should succeed with minimal valid requirement"
274
+
275
+ # Arrange
276
+ local req_id="REQ-004"
277
+ setup_full_requirement "$req_id"
278
+
279
+ # Act
280
+ local exit_code=0
281
+ local output=$(run_check_prereq "$req_id" 2>&1) || exit_code=$?
282
+
283
+ # Assert
284
+ assert_equals "$exit_code" "0" "Should succeed with PRD.md present"
285
+ }
286
+
287
+ # ============================================================================
288
+ # 测试 --require-epic 选项
289
+ # ============================================================================
290
+
291
+ test_require_epic_missing() {
292
+ describe "Should fail with --require-epic when EPIC.md missing"
293
+
294
+ # Arrange
295
+ local req_id="REQ-005"
296
+ setup_full_requirement "$req_id"
297
+ # 不创建 EPIC.md
298
+
299
+ # Act
300
+ local exit_code=0
301
+ local output=$(run_check_prereq "$req_id" --require-epic 2>&1) || exit_code=$?
302
+
303
+ # Assert
304
+ assert_not_equals "$exit_code" "0" "Should fail when EPIC.md required but missing"
305
+ assert_contains "$output" "EPIC.md not found" "Should mention missing EPIC"
306
+ }
307
+
308
+ test_require_epic_present() {
309
+ describe "Should succeed with --require-epic when EPIC.md exists"
310
+
311
+ # Arrange
312
+ local req_id="REQ-006"
313
+ local req_dir=$(setup_full_requirement "$req_id")
314
+ echo "# EPIC" > "$req_dir/EPIC.md"
315
+
316
+ # Act
317
+ local exit_code=0
318
+ local output=$(run_check_prereq "$req_id" --require-epic 2>&1) || exit_code=$?
319
+
320
+ # Assert
321
+ assert_equals "$exit_code" "0" "Should succeed when EPIC.md present"
322
+ }
323
+
324
+ # ============================================================================
325
+ # 测试 --require-tasks 选项
326
+ # ============================================================================
327
+
328
+ test_require_tasks_empty_dir() {
329
+ describe "Should fail with --require-tasks when tasks/ is empty"
330
+
331
+ # Arrange
332
+ local req_id="REQ-007"
333
+ local req_dir=$(setup_full_requirement "$req_id")
334
+ echo "# EPIC" > "$req_dir/EPIC.md"
335
+ # tasks/ 目录存在但为空
336
+
337
+ # Act
338
+ local exit_code=0
339
+ local output=$(run_check_prereq "$req_id" --require-tasks 2>&1) || exit_code=$?
340
+
341
+ # Assert
342
+ assert_not_equals "$exit_code" "0" "Should fail when tasks/ empty"
343
+ assert_contains "$output" "tasks/ directory" "Should mention tasks directory issue"
344
+ }
345
+
346
+ test_require_tasks_with_files() {
347
+ describe "Should succeed with --require-tasks when tasks/ has files"
348
+
349
+ # Arrange
350
+ local req_id="REQ-008"
351
+ local req_dir=$(setup_full_requirement "$req_id")
352
+ echo "# EPIC" > "$req_dir/EPIC.md"
353
+ echo "task" > "$req_dir/tasks/TASK_001.md"
354
+
355
+ # Act
356
+ local exit_code=0
357
+ local output=$(run_check_prereq "$req_id" --require-epic --require-tasks 2>&1) || exit_code=$?
358
+
359
+ # Assert
360
+ assert_equals "$exit_code" "0" "Should succeed when tasks/ has files"
361
+ }
362
+
363
+ # ============================================================================
364
+ # 测试 JSON 输出
365
+ # ============================================================================
366
+
367
+ test_json_output_valid() {
368
+ describe "Should output valid JSON with --json"
369
+
370
+ # Arrange
371
+ local req_id="REQ-009"
372
+ setup_full_requirement "$req_id"
373
+
374
+ # Act
375
+ local output=$(run_check_prereq "$req_id" --json)
376
+
377
+ # Assert
378
+ assert_json_valid "$output" "Should be valid JSON"
379
+ }
380
+
381
+ test_json_output_has_req_id() {
382
+ describe "JSON should include REQ_ID field"
383
+
384
+ # Arrange
385
+ local req_id="REQ-010"
386
+ setup_full_requirement "$req_id"
387
+
388
+ # Act
389
+ local output=$(run_check_prereq "$req_id" --json)
390
+
391
+ # Assert
392
+ assert_contains "$output" "\"REQ_ID\"" "Should have REQ_ID field"
393
+ assert_contains "$output" "\"$req_id\"" "Should have correct REQ_ID value"
394
+ }
395
+
396
+ test_json_output_available_docs() {
397
+ describe "JSON should include AVAILABLE_DOCS array"
398
+
399
+ # Arrange
400
+ local req_id="REQ-011"
401
+ local req_dir=$(setup_full_requirement "$req_id")
402
+
403
+ # 添加一些文档
404
+ echo "test" > "$req_dir/research/test.md"
405
+ echo "# Test Plan" > "$req_dir/TEST_PLAN.md"
406
+
407
+ # Act
408
+ local output=$(run_check_prereq "$req_id" --json)
409
+
410
+ # Assert
411
+ assert_contains "$output" "\"AVAILABLE_DOCS\"" "Should have AVAILABLE_DOCS field"
412
+ assert_contains "$output" "research/" "Should list research/"
413
+ assert_contains "$output" "TEST_PLAN.md" "Should list TEST_PLAN.md"
414
+ }
415
+
416
+ # ============================================================================
417
+ # 测试 BUG 类型需求
418
+ # ============================================================================
419
+
420
+ test_bug_type_requirement() {
421
+ describe "Should handle BUG-XXX format"
422
+
423
+ # Arrange
424
+ local req_id="BUG-999"
425
+ local req_dir=$(setup_full_requirement "$req_id")
426
+
427
+ # Act
428
+ local exit_code=0
429
+ local output=$(run_check_prereq "$req_id" --json 2>&1) || exit_code=$?
430
+
431
+ # Assert
432
+ assert_equals "$exit_code" "0" "Should handle BUG format"
433
+ assert_contains "$output" "BUG-999" "Should preserve BUG ID"
434
+ }
435
+
436
+ # ============================================================================
437
+ # 测试 --include-tasks 选项
438
+ # ============================================================================
439
+
440
+ test_include_tasks_in_output() {
441
+ describe "Should include tasks/ in output with --include-tasks"
442
+
443
+ # Arrange
444
+ local req_id="REQ-012"
445
+ local req_dir=$(setup_full_requirement "$req_id")
446
+ echo "task" > "$req_dir/tasks/TASK_001.md"
447
+
448
+ # Act
449
+ local output=$(run_check_prereq "$req_id" --include-tasks --json)
450
+
451
+ # Assert
452
+ assert_contains "$output" "tasks/" "Should include tasks/ in AVAILABLE_DOCS"
453
+ }
454
+
455
+ # ============================================================================
456
+ # 测试错误处理
457
+ # ============================================================================
458
+
459
+ test_invalid_option() {
460
+ describe "Should reject invalid options"
461
+
462
+ # Arrange - 创建测试脚本副本
463
+ local test_scripts_dir="$TEST_TMP_DIR/scripts"
464
+ mkdir -p "$test_scripts_dir"
465
+ create_test_common
466
+ cp "$CHECK_PREREQ_SCRIPT" "$test_scripts_dir/"
467
+
468
+ # Act
469
+ local exit_code=0
470
+ local output=$(
471
+ cd "$TEST_TMP_DIR"
472
+ bash "$test_scripts_dir/check-prerequisites.sh" --invalid-option 2>&1
473
+ ) || exit_code=$?
474
+
475
+ # Assert
476
+ assert_not_equals "$exit_code" "0" "Should fail on invalid option"
477
+ if [[ $exit_code -ne 0 ]]; then
478
+ assert_contains "$output" "Unknown option" "Should mention unknown option"
479
+ fi
480
+ }
481
+
482
+ # ============================================================================
483
+ # 运行所有测试
484
+ # ============================================================================
485
+
486
+ run_tests \
487
+ test_help_flag \
488
+ test_help_short_flag \
489
+ test_no_req_id_error \
490
+ test_paths_only_mode \
491
+ test_paths_only_json_mode \
492
+ test_missing_req_dir \
493
+ test_missing_prd_file \
494
+ test_valid_minimal_requirement \
495
+ test_require_epic_missing \
496
+ test_require_epic_present \
497
+ test_require_tasks_empty_dir \
498
+ test_require_tasks_with_files \
499
+ test_json_output_valid \
500
+ test_json_output_has_req_id \
501
+ test_json_output_available_docs \
502
+ test_bug_type_requirement \
503
+ test_include_tasks_in_output \
504
+ test_invalid_option