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,174 @@
1
+ /**
2
+ * T010: Incremental Compilation Tests
3
+ *
4
+ * 测试增量编译:
5
+ * 1. 无变更时跳过所有文件
6
+ * 2. skill.md 变更时重新生成 registry
7
+ * 3. skill-rules.json 变更时重新生成 registry
8
+ * 4. Manifest skills/rulesEntry 字段正确更新
9
+ *
10
+ * Reference: quickstart.md#4.4
11
+ */
12
+
13
+ const path = require('path');
14
+ const fs = require('fs');
15
+
16
+ describe('Incremental Compilation', () => {
17
+ describe('Skills Registry Incremental', () => {
18
+ test('should skip registry generation when no changes', async () => {
19
+ // 模拟场景:上次编译后无任何变更
20
+ const { compile } = require('../index');
21
+ const { loadManifest, createManifest, addSkillEntry } = require('../manifest');
22
+
23
+ // 预期:输出显示 "No changes detected" 或跳过计数
24
+ // 实际实现需要在 Phase 4 完成
25
+
26
+ // 占位测试:检查增量编译逻辑存在
27
+ expect(typeof compile).toBe('function');
28
+ });
29
+
30
+ test('should regenerate registry when skill.md changed', async () => {
31
+ // 模拟场景:修改了 .claude/skills/xxx/skill.md
32
+ // 预期:registry 重新生成,manifest.skills 更新
33
+
34
+ const { needsSkillRecompile, addSkillEntry, createManifest, hashContent } = require('../manifest');
35
+
36
+ const manifest = createManifest();
37
+ const oldHash = hashContent('old content');
38
+ const newHash = hashContent('new content');
39
+
40
+ addSkillEntry(manifest, {
41
+ name: 'test-skill',
42
+ sourceHash: oldHash,
43
+ timestamp: new Date().toISOString()
44
+ });
45
+
46
+ // 验证变更检测
47
+ expect(needsSkillRecompile('test-skill', newHash, manifest)).toBe(true);
48
+ expect(needsSkillRecompile('test-skill', oldHash, manifest)).toBe(false);
49
+ });
50
+
51
+ test('should regenerate registry when skill-rules.json changed', async () => {
52
+ // skill-rules.json 变更应触发所有技能重新编译
53
+ const { needsSkillRecompile, createManifest } = require('../manifest');
54
+
55
+ const manifest = createManifest();
56
+
57
+ // 新的 skill-rules.json 意味着所有技能都需要重新检查
58
+ expect(needsSkillRecompile('any-skill', 'newhash', manifest)).toBe(true);
59
+ });
60
+
61
+ test('should update manifest.skills after regeneration', async () => {
62
+ const { addSkillEntry, createManifest, hashContent } = require('../manifest');
63
+
64
+ const manifest = createManifest();
65
+
66
+ // 添加技能
67
+ addSkillEntry(manifest, {
68
+ name: 'skill-1',
69
+ sourceHash: hashContent('content 1'),
70
+ timestamp: new Date().toISOString()
71
+ });
72
+
73
+ addSkillEntry(manifest, {
74
+ name: 'skill-2',
75
+ sourceHash: hashContent('content 2'),
76
+ timestamp: new Date().toISOString()
77
+ });
78
+
79
+ expect(manifest.skills.length).toBe(2);
80
+ expect(manifest.skills.find(s => s.name === 'skill-1')).toBeDefined();
81
+ expect(manifest.skills.find(s => s.name === 'skill-2')).toBeDefined();
82
+ });
83
+ });
84
+
85
+ describe('Rules Entry Incremental', () => {
86
+ test('should skip rules generation when no changes', async () => {
87
+ const { needsRulesRecompile, addRulesEntry, createManifest, hashContent } = require('../manifest');
88
+
89
+ const manifest = createManifest();
90
+ const hash = hashContent('rules content');
91
+
92
+ addRulesEntry(manifest, 'cursor', {
93
+ path: '.cursor/rules/devflow.mdc',
94
+ hash: hash,
95
+ timestamp: new Date().toISOString()
96
+ });
97
+
98
+ // 相同 hash 不需要重新编译
99
+ expect(needsRulesRecompile('cursor', hash, manifest)).toBe(false);
100
+ });
101
+
102
+ test('should regenerate rules when registry changed', async () => {
103
+ const { needsRulesRecompile, createManifest } = require('../manifest');
104
+
105
+ const manifest = createManifest();
106
+
107
+ // 新平台或变更的 registry 需要重新编译规则
108
+ expect(needsRulesRecompile('cursor', 'newhash', manifest)).toBe(true);
109
+ });
110
+
111
+ test('should update manifest.rulesEntry after regeneration', async () => {
112
+ const { addRulesEntry, createManifest, hashContent } = require('../manifest');
113
+
114
+ const manifest = createManifest();
115
+
116
+ // 添加四个平台的规则入口
117
+ const platforms = ['cursor', 'codex', 'qwen', 'antigravity'];
118
+
119
+ for (const platform of platforms) {
120
+ addRulesEntry(manifest, platform, {
121
+ path: `.${platform}/rules/devflow`,
122
+ hash: hashContent(`${platform} content`),
123
+ timestamp: new Date().toISOString()
124
+ });
125
+ }
126
+
127
+ expect(Object.keys(manifest.rulesEntry).length).toBe(4);
128
+ expect(manifest.rulesEntry.cursor).toBeDefined();
129
+ expect(manifest.rulesEntry.codex).toBeDefined();
130
+ expect(manifest.rulesEntry.qwen).toBeDefined();
131
+ expect(manifest.rulesEntry.antigravity).toBeDefined();
132
+ });
133
+ });
134
+
135
+ describe('End-to-end Incremental Flow', () => {
136
+ test('should track full incremental state', async () => {
137
+ const {
138
+ createManifest,
139
+ addSkillEntry,
140
+ addRulesEntry,
141
+ needsSkillRecompile,
142
+ needsRulesRecompile,
143
+ hashContent
144
+ } = require('../manifest');
145
+
146
+ // 初始编译
147
+ const manifest = createManifest();
148
+
149
+ // 编译技能
150
+ const skill1Hash = hashContent('skill 1 content');
151
+ addSkillEntry(manifest, {
152
+ name: 'skill-1',
153
+ sourceHash: skill1Hash,
154
+ timestamp: new Date().toISOString()
155
+ });
156
+
157
+ // 编译规则
158
+ const cursorHash = hashContent('cursor rules');
159
+ addRulesEntry(manifest, 'cursor', {
160
+ path: '.cursor/rules/devflow.mdc',
161
+ hash: cursorHash,
162
+ timestamp: new Date().toISOString()
163
+ });
164
+
165
+ // 验证增量状态
166
+ expect(needsSkillRecompile('skill-1', skill1Hash, manifest)).toBe(false);
167
+ expect(needsRulesRecompile('cursor', cursorHash, manifest)).toBe(false);
168
+
169
+ // 模拟变更
170
+ const newSkill1Hash = hashContent('skill 1 updated');
171
+ expect(needsSkillRecompile('skill-1', newSkill1Hash, manifest)).toBe(true);
172
+ });
173
+ });
174
+ });
@@ -0,0 +1,174 @@
1
+ /**
2
+ * T012: Integration Test for Full Compilation
3
+ *
4
+ * 测试完整编译流程:
5
+ * 1. 运行 npm run adapt 等效操作
6
+ * 2. 验证 4 个平台规则入口文件存在
7
+ * 3. 验证 skills-registry.json 存在
8
+ * 4. 验证 manifest.json 是 v2.0
9
+ * 5. 验证统计数据输出
10
+ *
11
+ * Reference: quickstart.md#2.1
12
+ */
13
+
14
+ const path = require('path');
15
+ const fs = require('fs');
16
+ const os = require('os');
17
+
18
+ describe('Full Compilation Integration', () => {
19
+ // 这些测试依赖 Phase 3/4 的实现
20
+ // 在实现前应该失败
21
+
22
+ describe('compile() full flow', () => {
23
+ test('should compile all platforms and generate rules entry files', async () => {
24
+ // Phase 3/4 实现后此测试应通过
25
+ const { compile } = require('../index');
26
+
27
+ // 当前 compile 可能不支持完整功能
28
+ // 验证函数存在
29
+ expect(typeof compile).toBe('function');
30
+
31
+ // TODO: Phase 4 完成后取消注释
32
+ // const result = await compile({
33
+ // sourceDir: '.claude/commands/',
34
+ // skillsDir: '.claude/skills/',
35
+ // rules: true,
36
+ // skills: true
37
+ // });
38
+ //
39
+ // expect(result.success).toBe(true);
40
+ // expect(result.rulesGenerated).toBe(4);
41
+ // expect(result.skillsRegistered).toBeGreaterThan(0);
42
+ });
43
+
44
+ test('should generate 4 platform rule entry files', async () => {
45
+ const { PLATFORMS, getRulesEntryPath } = require('../platforms');
46
+
47
+ // 验证平台配置
48
+ expect(PLATFORMS).toContain('cursor');
49
+ expect(PLATFORMS).toContain('codex');
50
+ expect(PLATFORMS).toContain('qwen');
51
+ expect(PLATFORMS).toContain('antigravity');
52
+
53
+ // 验证规则入口路径
54
+ expect(getRulesEntryPath('cursor')).toBe('.cursor/rules/devflow.mdc');
55
+ expect(getRulesEntryPath('codex')).toBe('.codex/skills/cc-devflow/SKILL.md');
56
+ expect(getRulesEntryPath('qwen')).toBe('.qwen/commands/devflow.toml');
57
+ expect(getRulesEntryPath('antigravity')).toBe('.agent/rules/rules.md');
58
+ });
59
+
60
+ test('should generate skills-registry.json', async () => {
61
+ // 验证输出路径常量
62
+ const SKILLS_REGISTRY_PATH = 'devflow/.generated/skills-registry.json';
63
+
64
+ expect(SKILLS_REGISTRY_PATH).toBe('devflow/.generated/skills-registry.json');
65
+
66
+ // TODO: Phase 3 完成后验证文件生成
67
+ // const content = fs.readFileSync(SKILLS_REGISTRY_PATH, 'utf8');
68
+ // const registry = JSON.parse(content);
69
+ // expect(registry.version).toBe('1.0');
70
+ // expect(registry.skills).toBeDefined();
71
+ });
72
+
73
+ test('should generate manifest.json v2.0', async () => {
74
+ const { MANIFEST_PATH, MANIFEST_VERSION } = require('../manifest');
75
+
76
+ expect(MANIFEST_PATH).toBe('devflow/.generated/manifest.json');
77
+ expect(MANIFEST_VERSION).toBe('2.0');
78
+
79
+ // TODO: Phase 4 完成后验证文件生成
80
+ // const content = fs.readFileSync(MANIFEST_PATH, 'utf8');
81
+ // const manifest = JSON.parse(content);
82
+ // expect(manifest.version).toBe('2.0');
83
+ // expect(manifest.skills).toBeDefined();
84
+ // expect(manifest.rulesEntry).toBeDefined();
85
+ });
86
+
87
+ test('should return compilation statistics', async () => {
88
+ // 验证返回结构
89
+ const expectedStats = {
90
+ success: true,
91
+ filesCompiled: 0,
92
+ filesSkipped: 0,
93
+ resourcesCopied: 0,
94
+ resourcesSkipped: 0,
95
+ rulesGenerated: 0,
96
+ skillsRegistered: 0,
97
+ errors: []
98
+ };
99
+
100
+ // 验证结构存在
101
+ expect(expectedStats).toHaveProperty('success');
102
+ expect(expectedStats).toHaveProperty('filesCompiled');
103
+ expect(expectedStats).toHaveProperty('rulesGenerated');
104
+ expect(expectedStats).toHaveProperty('skillsRegistered');
105
+ });
106
+ });
107
+
108
+ describe('Platform output verification', () => {
109
+ test('should verify Cursor MDC format', async () => {
110
+ const matter = require('gray-matter');
111
+
112
+ // 预期的 MDC 格式
113
+ const expectedMDC = `---
114
+ description: "CC-DevFlow Rules"
115
+ globs: ["devflow/**/*", ".claude/**/*"]
116
+ alwaysApply: true
117
+ ---
118
+
119
+ # CC-DevFlow Rules
120
+ `;
121
+
122
+ const parsed = matter(expectedMDC);
123
+
124
+ expect(parsed.data.description).toBeDefined();
125
+ expect(parsed.data.globs).toBeDefined();
126
+ expect(parsed.data.alwaysApply).toBe(true);
127
+ });
128
+
129
+ test('should verify Qwen TOML format', async () => {
130
+ const TOML = require('@iarna/toml');
131
+
132
+ // 预期的 TOML 格式
133
+ const expectedTOML = `[skill]
134
+ name = "cc-devflow"
135
+ description = "CC-DevFlow development workflow system"
136
+
137
+ [commands]
138
+ flow-init = { description = "Initialize requirement" }
139
+ `;
140
+
141
+ expect(() => TOML.parse(expectedTOML)).not.toThrow();
142
+
143
+ const parsed = TOML.parse(expectedTOML);
144
+ expect(parsed.skill.name).toBe('cc-devflow');
145
+ expect(parsed.commands['flow-init']).toBeDefined();
146
+ });
147
+
148
+ test('should verify Antigravity size limit', async () => {
149
+ const { PLATFORM_CONFIG } = require('../platforms');
150
+
151
+ const antigravityConfig = PLATFORM_CONFIG.antigravity;
152
+
153
+ expect(antigravityConfig.limits.maxFileChars).toBe(12000);
154
+ });
155
+ });
156
+
157
+ describe('Error handling', () => {
158
+ test('should handle missing source directory gracefully', async () => {
159
+ const { generateSkillsRegistry } = require('../skills-registry');
160
+
161
+ // 不存在的目录应返回空数组
162
+ const result = generateSkillsRegistry('/nonexistent/path');
163
+
164
+ expect(Array.isArray(result)).toBe(true);
165
+ expect(result.length).toBe(0);
166
+ });
167
+
168
+ test('should reject invalid platform', () => {
169
+ const { getPlatformConfig } = require('../platforms');
170
+
171
+ expect(() => getPlatformConfig('invalid')).toThrow(/Unknown platform/);
172
+ });
173
+ });
174
+ });
@@ -0,0 +1,233 @@
1
+ /**
2
+ * T009: Manifest v2.0 Schema Tests
3
+ *
4
+ * 测试 Manifest v2.0:
5
+ * 1. v2.0 schema 接受 skills 和 rulesEntry 字段
6
+ * 2. v1.0 → v2.0 向后兼容迁移
7
+ * 3. Hash 格式验证 (64 字符十六进制)
8
+ * 4. Timestamp 格式验证 (ISO8601)
9
+ *
10
+ * Reference: data-model.md#ManifestV2
11
+ */
12
+
13
+ const {
14
+ MANIFEST_VERSION,
15
+ createManifest,
16
+ migrateToV2,
17
+ addSkillEntry,
18
+ addRulesEntry,
19
+ needsSkillRecompile,
20
+ needsRulesRecompile,
21
+ hashContent
22
+ } = require('../manifest');
23
+
24
+ describe('Manifest v2.0', () => {
25
+ describe('createManifest()', () => {
26
+ test('should create v2.0 manifest with skills and rulesEntry fields', () => {
27
+ const manifest = createManifest();
28
+
29
+ expect(manifest.version).toBe('2.0');
30
+ expect(manifest).toHaveProperty('generatedAt');
31
+ expect(manifest).toHaveProperty('entries');
32
+ expect(manifest).toHaveProperty('skills');
33
+ expect(manifest).toHaveProperty('rulesEntry');
34
+
35
+ expect(Array.isArray(manifest.entries)).toBe(true);
36
+ expect(Array.isArray(manifest.skills)).toBe(true);
37
+ expect(typeof manifest.rulesEntry).toBe('object');
38
+ });
39
+
40
+ test('should generate valid ISO8601 timestamp', () => {
41
+ const manifest = createManifest();
42
+
43
+ // ISO8601 格式验证
44
+ expect(() => new Date(manifest.generatedAt)).not.toThrow();
45
+ expect(new Date(manifest.generatedAt).toISOString()).toBe(manifest.generatedAt);
46
+ });
47
+ });
48
+
49
+ describe('migrateToV2()', () => {
50
+ test('should migrate v1.0 manifest to v2.0', () => {
51
+ const v1Manifest = {
52
+ version: '1.0.0',
53
+ generatedAt: '2025-01-01T00:00:00.000Z',
54
+ entries: [
55
+ { source: 'test.md', target: 'out/test.md', hash: 'abc', platform: 'codex' }
56
+ ]
57
+ };
58
+
59
+ const v2Manifest = migrateToV2(v1Manifest);
60
+
61
+ expect(v2Manifest.version).toBe('2.0');
62
+ expect(v2Manifest.entries).toEqual(v1Manifest.entries);
63
+ expect(v2Manifest.skills).toEqual([]);
64
+ expect(v2Manifest.rulesEntry).toEqual({});
65
+ });
66
+
67
+ test('should preserve v2.0 manifest unchanged', () => {
68
+ const v2Manifest = {
69
+ version: '2.0',
70
+ generatedAt: '2025-01-01T00:00:00.000Z',
71
+ entries: [],
72
+ skills: [{ name: 'test', sourceHash: 'abc', timestamp: '2025-01-01T00:00:00.000Z' }],
73
+ rulesEntry: { cursor: { path: '.cursor/rules/devflow.mdc', hash: 'def' } }
74
+ };
75
+
76
+ const result = migrateToV2(v2Manifest);
77
+
78
+ expect(result).toEqual(v2Manifest);
79
+ });
80
+
81
+ test('should create new v2.0 manifest from null', () => {
82
+ const result = migrateToV2(null);
83
+
84
+ expect(result.version).toBe('2.0');
85
+ expect(result.skills).toEqual([]);
86
+ expect(result.rulesEntry).toEqual({});
87
+ });
88
+ });
89
+
90
+ describe('addSkillEntry()', () => {
91
+ test('should add new skill entry', () => {
92
+ const manifest = createManifest();
93
+ const skillEntry = {
94
+ name: 'cc-devflow-orchestrator',
95
+ sourceHash: 'a'.repeat(64),
96
+ timestamp: new Date().toISOString()
97
+ };
98
+
99
+ addSkillEntry(manifest, skillEntry);
100
+
101
+ expect(manifest.skills.length).toBe(1);
102
+ expect(manifest.skills[0]).toEqual(skillEntry);
103
+ });
104
+
105
+ test('should update existing skill entry', () => {
106
+ const manifest = createManifest();
107
+ const oldEntry = {
108
+ name: 'test-skill',
109
+ sourceHash: 'a'.repeat(64),
110
+ timestamp: '2025-01-01T00:00:00.000Z'
111
+ };
112
+ const newEntry = {
113
+ name: 'test-skill',
114
+ sourceHash: 'b'.repeat(64),
115
+ timestamp: '2025-01-02T00:00:00.000Z'
116
+ };
117
+
118
+ addSkillEntry(manifest, oldEntry);
119
+ addSkillEntry(manifest, newEntry);
120
+
121
+ expect(manifest.skills.length).toBe(1);
122
+ expect(manifest.skills[0].sourceHash).toBe('b'.repeat(64));
123
+ });
124
+ });
125
+
126
+ describe('addRulesEntry()', () => {
127
+ test('should add rules entry for platform', () => {
128
+ const manifest = createManifest();
129
+ const rulesEntry = {
130
+ path: '.cursor/rules/devflow.mdc',
131
+ hash: 'c'.repeat(64),
132
+ timestamp: new Date().toISOString()
133
+ };
134
+
135
+ addRulesEntry(manifest, 'cursor', rulesEntry);
136
+
137
+ expect(manifest.rulesEntry.cursor).toEqual(rulesEntry);
138
+ });
139
+
140
+ test('should update existing rules entry', () => {
141
+ const manifest = createManifest();
142
+ const oldEntry = { path: '.cursor/rules/devflow.mdc', hash: 'a'.repeat(64) };
143
+ const newEntry = { path: '.cursor/rules/devflow.mdc', hash: 'b'.repeat(64) };
144
+
145
+ addRulesEntry(manifest, 'cursor', oldEntry);
146
+ addRulesEntry(manifest, 'cursor', newEntry);
147
+
148
+ expect(manifest.rulesEntry.cursor.hash).toBe('b'.repeat(64));
149
+ });
150
+ });
151
+
152
+ describe('needsSkillRecompile()', () => {
153
+ test('should return true for new skill', () => {
154
+ const manifest = createManifest();
155
+
156
+ const result = needsSkillRecompile('new-skill', 'somehash', manifest);
157
+
158
+ expect(result).toBe(true);
159
+ });
160
+
161
+ test('should return true when hash changed', () => {
162
+ const manifest = createManifest();
163
+ addSkillEntry(manifest, {
164
+ name: 'test-skill',
165
+ sourceHash: 'oldhash',
166
+ timestamp: new Date().toISOString()
167
+ });
168
+
169
+ const result = needsSkillRecompile('test-skill', 'newhash', manifest);
170
+
171
+ expect(result).toBe(true);
172
+ });
173
+
174
+ test('should return false when hash unchanged', () => {
175
+ const manifest = createManifest();
176
+ const hash = 'samehash';
177
+ addSkillEntry(manifest, {
178
+ name: 'test-skill',
179
+ sourceHash: hash,
180
+ timestamp: new Date().toISOString()
181
+ });
182
+
183
+ const result = needsSkillRecompile('test-skill', hash, manifest);
184
+
185
+ expect(result).toBe(false);
186
+ });
187
+ });
188
+
189
+ describe('needsRulesRecompile()', () => {
190
+ test('should return true for new platform', () => {
191
+ const manifest = createManifest();
192
+
193
+ const result = needsRulesRecompile('cursor', 'somehash', manifest);
194
+
195
+ expect(result).toBe(true);
196
+ });
197
+
198
+ test('should return true when hash changed', () => {
199
+ const manifest = createManifest();
200
+ addRulesEntry(manifest, 'cursor', {
201
+ path: '.cursor/rules/devflow.mdc',
202
+ hash: 'oldhash',
203
+ timestamp: new Date().toISOString()
204
+ });
205
+
206
+ const result = needsRulesRecompile('cursor', 'newhash', manifest);
207
+
208
+ expect(result).toBe(true);
209
+ });
210
+
211
+ test('should return false when hash unchanged', () => {
212
+ const manifest = createManifest();
213
+ const hash = 'samehash';
214
+ addRulesEntry(manifest, 'cursor', {
215
+ path: '.cursor/rules/devflow.mdc',
216
+ hash: hash,
217
+ timestamp: new Date().toISOString()
218
+ });
219
+
220
+ const result = needsRulesRecompile('cursor', hash, manifest);
221
+
222
+ expect(result).toBe(false);
223
+ });
224
+ });
225
+
226
+ describe('Hash format validation', () => {
227
+ test('hashContent should return 64-char hex string', () => {
228
+ const hash = hashContent('test content');
229
+
230
+ expect(hash).toMatch(/^[a-f0-9]{64}$/);
231
+ });
232
+ });
233
+ });