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,43 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://cc-devflow.claude/.claude/schemas/constitution.schema.json",
4
+ "title": "Devflow Constitution Tracking",
5
+ "type": "object",
6
+ "required": [
7
+ "articles"
8
+ ],
9
+ "properties": {
10
+ "articles": {
11
+ "type": "array",
12
+ "minItems": 1,
13
+ "items": {
14
+ "type": "object",
15
+ "required": [
16
+ "article",
17
+ "status"
18
+ ],
19
+ "properties": {
20
+ "article": {
21
+ "type": "string",
22
+ "minLength": 1
23
+ },
24
+ "status": {
25
+ "type": "string",
26
+ "enum": [
27
+ "pending",
28
+ "in_progress",
29
+ "approved",
30
+ "waived",
31
+ "rejected"
32
+ ]
33
+ },
34
+ "notes": {
35
+ "type": "string"
36
+ }
37
+ },
38
+ "additionalProperties": false
39
+ }
40
+ }
41
+ },
42
+ "additionalProperties": true
43
+ }
@@ -0,0 +1,200 @@
1
+ #!/usr/bin/env bash
2
+ # shellcheck disable=SC2312
3
+
4
+ set -euo pipefail
5
+
6
+ usage() {
7
+ cat <<'USAGE'
8
+ Usage: scripts/bash/analyze-upgrade-impact.sh --req <requirement-dir|REQ-ID> [--compare version] [--format {text,json}]
9
+
10
+ Produces PRD change detection and impact assessment reports under
11
+ devflow/requirements/<REQ>/analysis/.
12
+ USAGE
13
+ }
14
+
15
+ REQ=""
16
+ COMPARE=""
17
+ FORMAT="text"
18
+
19
+ while [[ $# -gt 0 ]]; do
20
+ case "$1" in
21
+ --req)
22
+ shift
23
+ REQ="${1:-}"
24
+ ;;
25
+ --compare)
26
+ shift
27
+ COMPARE="${1:-}"
28
+ ;;
29
+ --format)
30
+ shift
31
+ FORMAT="${1:-text}"
32
+ ;;
33
+ -h|--help)
34
+ usage
35
+ exit 0
36
+ ;;
37
+ *)
38
+ echo "Unknown argument: $1" >&2
39
+ usage
40
+ exit 1
41
+ ;;
42
+ esac
43
+ shift
44
+ done
45
+
46
+ if [[ -z "$REQ" ]]; then
47
+ echo "Error: --req is required." >&2
48
+ usage
49
+ exit 1
50
+ fi
51
+
52
+ if [[ -d "$REQ" ]]; then
53
+ REQ_DIR="$(cd "$REQ" && pwd)"
54
+ else
55
+ REQ_DIR="devflow/requirements/$REQ"
56
+ fi
57
+
58
+ if [[ ! -d "$REQ_DIR" ]]; then
59
+ echo "Error: requirement directory '$REQ_DIR' not found." >&2
60
+ exit 1
61
+ fi
62
+
63
+ python3 - "$REQ_DIR" "$COMPARE" "$FORMAT" <<'PY'
64
+ from __future__ import annotations
65
+
66
+ import json
67
+ import re
68
+ import sys
69
+ from datetime import datetime, timezone
70
+ from pathlib import Path
71
+ from typing import Dict, Any
72
+
73
+ req_dir = Path(sys.argv[1]).resolve()
74
+ compare_version = sys.argv[2] or ""
75
+ fmt = sys.argv[3]
76
+
77
+ prd_current = req_dir / "PRD.md"
78
+ if not prd_current.exists():
79
+ print(f"Error: {prd_current} not found.", file=sys.stderr)
80
+ sys.exit(1)
81
+
82
+ versions_dir = req_dir / "versions"
83
+ compare_path = None
84
+ if compare_version:
85
+ compare_path = versions_dir / compare_version / "PRD.md"
86
+ if not compare_path.exists():
87
+ print(f"Warning: compare version {compare_version} not found; skipping diff.", file=sys.stderr)
88
+ compare_path = None
89
+
90
+ current_lines = prd_current.read_text(encoding="utf-8").splitlines()
91
+ previous_lines = compare_path.read_text(encoding="utf-8").splitlines() if compare_path else []
92
+
93
+ analysis_dir = req_dir / "analysis"
94
+ analysis_dir.mkdir(exist_ok=True, parents=True)
95
+ timestamp = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S")
96
+
97
+ def diff_stats() -> Dict[str, Any]:
98
+ additions = sum(1 for line in current_lines if line.startswith("+") and "User Story" in line)
99
+ removals = sum(1 for line in previous_lines if line.startswith("+") and "User Story" in line)
100
+ breaking = 0
101
+ additive = 0
102
+ for line in current_lines:
103
+ if "[BREAKING]" in line or re.search(r"\bRemoved\b", line, re.IGNORECASE):
104
+ breaking += 1
105
+ if "User Story" in line or "API" in line:
106
+ additive += 1
107
+ return {
108
+ "userStoriesAdded": additions,
109
+ "userStoriesRemoved": removals,
110
+ "breakingMarkers": breaking,
111
+ "featureChanges": additive,
112
+ }
113
+
114
+ stats = diff_stats()
115
+
116
+ if stats["breakingMarkers"] > 0 or stats["userStoriesRemoved"] > 0:
117
+ recommendation = "MAJOR"
118
+ elif stats["featureChanges"] > 1:
119
+ recommendation = "MINOR"
120
+ else:
121
+ recommendation = "PATCH"
122
+
123
+ change_report = analysis_dir / f"change_detection_{timestamp}.md"
124
+ impact_report = analysis_dir / f"impact_assessment_{timestamp}.md"
125
+ recommendation_report = analysis_dir / f"upgrade_recommendation_{timestamp}.md"
126
+
127
+ change_report.write_text(
128
+ "\n".join(
129
+ [
130
+ f"# Change Detection — {req_dir.name}",
131
+ f"Generated: {datetime.now(timezone.utc).isoformat()}",
132
+ "",
133
+ f"- User stories added: {stats['userStoriesAdded']}",
134
+ f"- User stories removed: {stats['userStoriesRemoved']}",
135
+ f"- Breaking markers: {stats['breakingMarkers']}",
136
+ f"- Feature change mentions: {stats['featureChanges']}",
137
+ ]
138
+ )
139
+ + "\n",
140
+ encoding="utf-8",
141
+ )
142
+
143
+ impact_report.write_text(
144
+ "\n".join(
145
+ [
146
+ f"# Impact Assessment — {req_dir.name}",
147
+ "",
148
+ "## Code Areas Impacted",
149
+ "- TODO: map affected services/controllers.",
150
+ "",
151
+ "## Test Plan Impact",
152
+ "- TODO: identify regression suites requiring updates.",
153
+ "",
154
+ "## Deployment Considerations",
155
+ "- TODO: document rollout/rollback implications.",
156
+ ]
157
+ )
158
+ + "\n",
159
+ encoding="utf-8",
160
+ )
161
+
162
+ recommendation_report.write_text(
163
+ "\n".join(
164
+ [
165
+ f"# Upgrade Recommendation — {req_dir.name}",
166
+ "",
167
+ f"- Suggested version bump: **{recommendation}**",
168
+ "- Rationale:",
169
+ f" * Breaking markers detected: {stats['breakingMarkers']}",
170
+ f" * User stories added: {stats['userStoriesAdded']}",
171
+ f" * User stories removed: {stats['userStoriesRemoved']}",
172
+ ]
173
+ )
174
+ + "\n",
175
+ encoding="utf-8",
176
+ )
177
+
178
+ summary = {
179
+ "requirement": req_dir.name,
180
+ "compareVersion": compare_version or None,
181
+ "recommendedBump": recommendation,
182
+ "statistics": stats,
183
+ "reports": {
184
+ "changeDetection": str(change_report.relative_to(req_dir)),
185
+ "impactAssessment": str(impact_report.relative_to(req_dir)),
186
+ "recommendation": str(recommendation_report.relative_to(req_dir)),
187
+ },
188
+ }
189
+
190
+ if fmt.lower() == "json":
191
+ print(json.dumps(summary, indent=2))
192
+ else:
193
+ print(
194
+ f"Recommended bump: {recommendation}\n"
195
+ f"Reports:\n"
196
+ f" - {summary['reports']['changeDetection']}\n"
197
+ f" - {summary['reports']['impactAssessment']}\n"
198
+ f" - {summary['reports']['recommendation']}"
199
+ )
200
+ PY
@@ -0,0 +1,351 @@
1
+ #!/usr/bin/env bash
2
+ # =============================================================================
3
+ # archive-requirement.sh - 需求归档脚本
4
+ # 将已完成或废弃的需求移动到归档目录
5
+ # =============================================================================
6
+
7
+ set -euo pipefail
8
+
9
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10
+ source "$SCRIPT_DIR/common.sh"
11
+
12
+ # =============================================================================
13
+ # 使用说明
14
+ # =============================================================================
15
+ usage() {
16
+ cat << 'EOF'
17
+ Usage: archive-requirement.sh <REQ_ID> [OPTIONS]
18
+
19
+ 归档需求目录到 devflow/archive/{YYYY-MM}/ 下
20
+
21
+ Arguments:
22
+ REQ_ID 需求编号 (e.g., REQ-003, BUG-001)
23
+
24
+ Options:
25
+ --reason REASON 归档原因: completed (默认), deprecated, obsolete, superseded
26
+ --restore 恢复归档的需求到活跃目录
27
+ --list 列出所有归档的需求
28
+ --json 输出 JSON 格式
29
+ --dry-run 仅显示将执行的操作,不实际执行
30
+ --help, -h 显示帮助信息
31
+
32
+ Examples:
33
+ archive-requirement.sh REQ-003 # 归档已完成需求
34
+ archive-requirement.sh REQ-003 --reason deprecated # 标记为废弃归档
35
+ archive-requirement.sh --list # 列出所有归档
36
+ archive-requirement.sh REQ-003 --restore # 恢复归档需求
37
+ EOF
38
+ }
39
+
40
+ # =============================================================================
41
+ # 参数解析
42
+ # =============================================================================
43
+ REQ_ID=""
44
+ REASON="completed"
45
+ RESTORE=false
46
+ LIST_MODE=false
47
+ JSON_MODE=false
48
+ DRY_RUN=false
49
+
50
+ while [[ $# -gt 0 ]]; do
51
+ case "$1" in
52
+ --reason)
53
+ REASON="$2"
54
+ shift 2
55
+ ;;
56
+ --restore)
57
+ RESTORE=true
58
+ shift
59
+ ;;
60
+ --list)
61
+ LIST_MODE=true
62
+ shift
63
+ ;;
64
+ --json)
65
+ JSON_MODE=true
66
+ shift
67
+ ;;
68
+ --dry-run)
69
+ DRY_RUN=true
70
+ shift
71
+ ;;
72
+ --help|-h)
73
+ usage
74
+ exit 0
75
+ ;;
76
+ -*)
77
+ echo "ERROR: Unknown option: $1" >&2
78
+ usage
79
+ exit 1
80
+ ;;
81
+ *)
82
+ if [[ -z "$REQ_ID" ]]; then
83
+ REQ_ID="$1"
84
+ fi
85
+ shift
86
+ ;;
87
+ esac
88
+ done
89
+
90
+ REPO_ROOT=$(get_repo_root)
91
+
92
+ # =============================================================================
93
+ # 列出归档模式
94
+ # =============================================================================
95
+ if [[ "$LIST_MODE" == "true" ]]; then
96
+ if [[ "$JSON_MODE" == "true" ]]; then
97
+ # JSON 格式输出
98
+ archive_base="$REPO_ROOT/devflow/archive"
99
+ echo "["
100
+ first=true
101
+ if [[ -d "$archive_base" ]]; then
102
+ for month_dir in "$archive_base"/*/; do
103
+ [[ -d "$month_dir" ]] || continue
104
+ month=$(basename "$month_dir")
105
+ for req_dir in "$month_dir"*/; do
106
+ [[ -d "$req_dir" ]] || continue
107
+ req_id=$(basename "$req_dir")
108
+ status_file="$req_dir/orchestration_status.json"
109
+ reason="completed"
110
+ archived_at=""
111
+ title=""
112
+ if [[ -f "$status_file" ]]; then
113
+ reason=$(jq -r '.archivedReason // "completed"' "$status_file" 2>/dev/null)
114
+ archived_at=$(jq -r '.archivedAt // ""' "$status_file" 2>/dev/null)
115
+ title=$(jq -r '.title // ""' "$status_file" 2>/dev/null)
116
+ fi
117
+ if [[ "$first" == "true" ]]; then
118
+ first=false
119
+ else
120
+ echo ","
121
+ fi
122
+ printf ' {"reqId": "%s", "title": "%s", "month": "%s", "reason": "%s", "archivedAt": "%s"}' \
123
+ "$req_id" "$title" "$month" "$reason" "$archived_at"
124
+ done
125
+ done
126
+ fi
127
+ echo ""
128
+ echo "]"
129
+ else
130
+ # 人类可读格式
131
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
132
+ echo "📦 归档需求列表"
133
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
134
+ printf "%-10s | %-12s | %-12s | %s\n" "月份" "需求ID" "归档原因" "标题"
135
+ echo "───────────────────────────────────────────────────────────────"
136
+ archive_base="$REPO_ROOT/devflow/archive"
137
+ found=false
138
+ if [[ -d "$archive_base" ]]; then
139
+ for month_dir in "$archive_base"/*/; do
140
+ [[ -d "$month_dir" ]] || continue
141
+ month=$(basename "$month_dir")
142
+ for req_dir in "$month_dir"*/; do
143
+ [[ -d "$req_dir" ]] || continue
144
+ req_id=$(basename "$req_dir")
145
+ status_file="$req_dir/orchestration_status.json"
146
+ reason="completed"
147
+ title=""
148
+ if [[ -f "$status_file" ]]; then
149
+ reason=$(jq -r '.archivedReason // "completed"' "$status_file" 2>/dev/null)
150
+ title=$(jq -r '.title // ""' "$status_file" 2>/dev/null)
151
+ fi
152
+ printf "%-10s | %-12s | %-12s | %s\n" "$month" "$req_id" "$reason" "$title"
153
+ found=true
154
+ done
155
+ done
156
+ fi
157
+ if [[ "$found" == "false" ]]; then
158
+ echo "(暂无归档需求)"
159
+ fi
160
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
161
+ fi
162
+ exit 0
163
+ fi
164
+
165
+ # =============================================================================
166
+ # 验证 REQ_ID
167
+ # =============================================================================
168
+ if [[ -z "$REQ_ID" ]]; then
169
+ echo "ERROR: 必须提供需求ID" >&2
170
+ usage
171
+ exit 1
172
+ fi
173
+
174
+ if ! validate_req_id "$REQ_ID"; then
175
+ exit 1
176
+ fi
177
+
178
+ # =============================================================================
179
+ # 恢复模式
180
+ # =============================================================================
181
+ if [[ "$RESTORE" == "true" ]]; then
182
+ archived_path=$(find_archived_req "$REPO_ROOT" "$REQ_ID")
183
+
184
+ if [[ -z "$archived_path" ]]; then
185
+ echo "ERROR: 归档中未找到 $REQ_ID" >&2
186
+ exit 1
187
+ fi
188
+
189
+ # 确定目标目录
190
+ req_type=$(get_req_type "$REQ_ID")
191
+ if [[ "$req_type" == "bug" ]]; then
192
+ target_dir="$REPO_ROOT/devflow/bugs/$REQ_ID"
193
+ else
194
+ target_dir="$REPO_ROOT/devflow/requirements/$REQ_ID"
195
+ fi
196
+
197
+ # 检查目标是否已存在
198
+ if [[ -d "$target_dir" ]]; then
199
+ echo "ERROR: 目标目录已存在: $target_dir" >&2
200
+ echo "请先删除或重命名现有目录" >&2
201
+ exit 1
202
+ fi
203
+
204
+ if [[ "$DRY_RUN" == "true" ]]; then
205
+ echo "[DRY-RUN] 将移动: $archived_path → $target_dir"
206
+ exit 0
207
+ fi
208
+
209
+ # 执行恢复
210
+ mkdir -p "$(dirname "$target_dir")"
211
+ mv "$archived_path" "$target_dir"
212
+
213
+ # 更新状态文件
214
+ status_file="$target_dir/orchestration_status.json"
215
+ if [[ -f "$status_file" ]]; then
216
+ # 恢复到归档前的状态
217
+ original_status=$(jq -r '.statusBeforeArchive // "release_complete"' "$status_file")
218
+ jq --arg status "$original_status" \
219
+ --arg updated "$(get_beijing_time_iso)" \
220
+ 'del(.archivedAt, .archivedReason, .archiveLocation, .statusBeforeArchive) |
221
+ .status = $status |
222
+ .updatedAt = $updated' \
223
+ "$status_file" > "${status_file}.tmp" && mv "${status_file}.tmp" "$status_file"
224
+ fi
225
+
226
+ # 记录日志
227
+ log_event "$REQ_ID" "需求从归档恢复: $archived_path → $target_dir"
228
+
229
+ if [[ "$JSON_MODE" == "true" ]]; then
230
+ cat << EOF
231
+ {
232
+ "action": "restore",
233
+ "reqId": "$REQ_ID",
234
+ "from": "$archived_path",
235
+ "to": "$target_dir",
236
+ "status": "success"
237
+ }
238
+ EOF
239
+ else
240
+ echo "✅ 需求 $REQ_ID 已从归档恢复"
241
+ echo " 位置: $target_dir"
242
+ fi
243
+ exit 0
244
+ fi
245
+
246
+ # =============================================================================
247
+ # 归档模式
248
+ # =============================================================================
249
+
250
+ # 验证归档原因
251
+ valid_reasons=("completed" "deprecated" "obsolete" "superseded")
252
+ if [[ ! " ${valid_reasons[*]} " =~ " ${REASON} " ]]; then
253
+ echo "ERROR: 无效的归档原因: $REASON" >&2
254
+ echo "有效选项: ${valid_reasons[*]}" >&2
255
+ exit 1
256
+ fi
257
+
258
+ # 检查需求是否已归档
259
+ if is_archived "$REPO_ROOT" "$REQ_ID"; then
260
+ archived_path=$(find_archived_req "$REPO_ROOT" "$REQ_ID")
261
+ echo "ERROR: $REQ_ID 已经在归档中: $archived_path" >&2
262
+ echo "如需重新归档,请先使用 --restore 恢复" >&2
263
+ exit 1
264
+ fi
265
+
266
+ # 获取当前需求目录
267
+ source_dir=$(get_req_dir "$REPO_ROOT" "$REQ_ID")
268
+
269
+ if [[ ! -d "$source_dir" ]]; then
270
+ echo "ERROR: 需求目录不存在: $source_dir" >&2
271
+ exit 1
272
+ fi
273
+
274
+ # 确定归档目标
275
+ archive_month=$(TZ='Asia/Shanghai' date '+%Y-%m')
276
+ archive_dir=$(get_archive_dir "$REPO_ROOT" "$archive_month")
277
+ target_dir="$archive_dir/$REQ_ID"
278
+
279
+ if [[ "$DRY_RUN" == "true" ]]; then
280
+ echo "[DRY-RUN] 将移动: $source_dir → $target_dir"
281
+ echo "[DRY-RUN] 归档原因: $REASON"
282
+ exit 0
283
+ fi
284
+
285
+ # 创建归档目录
286
+ mkdir -p "$archive_dir"
287
+
288
+ # 读取当前状态
289
+ status_file="$source_dir/orchestration_status.json"
290
+ current_status="unknown"
291
+ if [[ -f "$status_file" ]]; then
292
+ current_status=$(jq -r '.status // "unknown"' "$status_file")
293
+ fi
294
+
295
+ # 移动目录
296
+ mv "$source_dir" "$target_dir"
297
+
298
+ # 更新状态文件
299
+ status_file="$target_dir/orchestration_status.json"
300
+ if [[ -f "$status_file" ]]; then
301
+ jq --arg reason "$REASON" \
302
+ --arg archived_at "$(get_beijing_time_iso)" \
303
+ --arg location "$target_dir" \
304
+ --arg prev_status "$current_status" \
305
+ --arg updated "$(get_beijing_time_iso)" \
306
+ '.status = "archived" |
307
+ .archivedReason = $reason |
308
+ .archivedAt = $archived_at |
309
+ .archiveLocation = $location |
310
+ .statusBeforeArchive = $prev_status |
311
+ .updatedAt = $updated' \
312
+ "$status_file" > "${status_file}.tmp" && mv "${status_file}.tmp" "$status_file"
313
+ fi
314
+
315
+ # 记录日志
316
+ log_file="$target_dir/EXECUTION_LOG.md"
317
+ if [[ -f "$log_file" ]]; then
318
+ cat >> "$log_file" << EOF
319
+
320
+ ### $(get_beijing_time)
321
+ **需求归档**
322
+ - 归档原因: $REASON
323
+ - 归档位置: $target_dir
324
+ - 归档前状态: $current_status
325
+ EOF
326
+ fi
327
+
328
+ # 输出结果
329
+ if [[ "$JSON_MODE" == "true" ]]; then
330
+ cat << EOF
331
+ {
332
+ "action": "archive",
333
+ "reqId": "$REQ_ID",
334
+ "from": "$source_dir",
335
+ "to": "$target_dir",
336
+ "reason": "$REASON",
337
+ "previousStatus": "$current_status",
338
+ "archivedAt": "$(get_beijing_time_iso)",
339
+ "status": "success"
340
+ }
341
+ EOF
342
+ else
343
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
344
+ echo "✅ 需求 $REQ_ID 已归档"
345
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
346
+ echo " 原位置: $source_dir"
347
+ echo " 新位置: $target_dir"
348
+ echo " 归档原因: $REASON"
349
+ echo " 归档前状态: $current_status"
350
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
351
+ fi