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,144 @@
1
+ /**
2
+ * T023: Zod Schemas for Command Emitter
3
+ *
4
+ * Defines validation schemas for:
5
+ * - PlaceholderSchema: {SCRIPT:*}, {AGENT_SCRIPT}, $ARGUMENTS
6
+ * - FrontmatterSchema: YAML frontmatter fields
7
+ * - CommandIRSchema: Intermediate Representation
8
+ * - ManifestEntrySchema: Single compilation record
9
+ * - ManifestSchema: Complete manifest file
10
+ */
11
+ const { z } = require('zod');
12
+
13
+ // ============================================================
14
+ // PlaceholderSchema - 占位符定义
15
+ // ============================================================
16
+ const PlaceholderSchema = z.object({
17
+ type: z.enum(['SCRIPT', 'TEMPLATE', 'GUIDE', 'AGENT_SCRIPT', 'ARGUMENTS']),
18
+ raw: z.string(),
19
+ alias: z.string().optional(),
20
+ position: z.object({
21
+ start: z.number(),
22
+ end: z.number()
23
+ })
24
+ });
25
+
26
+ // ============================================================
27
+ // ScriptPathSchema - 脚本路径安全验证 (SECURITY FIX: FINDING-001)
28
+ // ============================================================
29
+ const ScriptPathSchema = z.string()
30
+ .min(1, 'Script path cannot be empty')
31
+ .refine(
32
+ (p) => !p.includes('../') && !p.startsWith('/'),
33
+ { message: 'Script path must not contain ../ or be absolute' }
34
+ )
35
+ .refine(
36
+ (p) => p.startsWith('.claude/scripts/'),
37
+ { message: 'Script path must be within .claude/scripts/' }
38
+ );
39
+
40
+ // ============================================================
41
+ // TemplatePathSchema - 模板路径验证
42
+ // ============================================================
43
+ const TemplatePathSchema = z.string()
44
+ .min(1, 'Template path cannot be empty')
45
+ .refine(
46
+ (p) => !p.includes('../') && !p.startsWith('/'),
47
+ { message: 'Template path must not contain ../ or be absolute' }
48
+ )
49
+ .refine(
50
+ (p) => p.startsWith('.claude/docs/templates/'),
51
+ { message: 'Template path must be within .claude/docs/templates/' }
52
+ );
53
+
54
+ // ============================================================
55
+ // GuidePathSchema - 指南路径验证
56
+ // ============================================================
57
+ const GuidePathSchema = z.string()
58
+ .min(1, 'Guide path cannot be empty')
59
+ .refine(
60
+ (p) => !p.includes('../') && !p.startsWith('/'),
61
+ { message: 'Guide path must not contain ../ or be absolute' }
62
+ )
63
+ .refine(
64
+ (p) => p.startsWith('.claude/docs/guides/'),
65
+ { message: 'Guide path must be within .claude/docs/guides/' }
66
+ );
67
+
68
+ // ============================================================
69
+ // AgentScriptsSchema - 跨平台脚本定义
70
+ // ============================================================
71
+ const AgentScriptsSchema = z.object({
72
+ sh: z.string().optional(),
73
+ ps: z.string().optional()
74
+ }).optional();
75
+
76
+ // ============================================================
77
+ // FrontmatterSchema - YAML frontmatter 验证
78
+ // ============================================================
79
+ const FrontmatterSchema = z.object({
80
+ name: z.string().min(1, 'name is required'),
81
+ description: z.string().min(1, 'description is required'),
82
+ scripts: z.record(ScriptPathSchema).optional(), // ✅ SECURITY: Use strict path validation
83
+ templates: z.record(TemplatePathSchema).optional(), // ✅ NEW: Template references
84
+ guides: z.record(GuidePathSchema).optional(), // ✅ NEW: Guide references
85
+ agent_scripts: AgentScriptsSchema
86
+ });
87
+
88
+ // ============================================================
89
+ // SourceSchema - 源文件信息
90
+ // ============================================================
91
+ const SourceSchema = z.object({
92
+ path: z.string(),
93
+ filename: z.string(),
94
+ hash: z.string()
95
+ });
96
+
97
+ // ============================================================
98
+ // CommandIRSchema - 命令中间表示
99
+ // ============================================================
100
+ const CommandIRSchema = z.object({
101
+ source: SourceSchema,
102
+ frontmatter: FrontmatterSchema,
103
+ body: z.string(),
104
+ placeholders: z.array(PlaceholderSchema)
105
+ });
106
+
107
+ // ============================================================
108
+ // ManifestEntrySchema - 单条编译记录
109
+ // ============================================================
110
+ const ManifestEntrySchema = z.object({
111
+ source: z.string(),
112
+ target: z.string(),
113
+ hash: z.string(),
114
+ timestamp: z.string().refine(
115
+ (val) => !isNaN(Date.parse(val)),
116
+ { message: 'timestamp must be a valid ISO 8601 date' }
117
+ ),
118
+ platform: z.enum(['codex', 'cursor', 'qwen', 'antigravity'])
119
+ });
120
+
121
+ // ============================================================
122
+ // ManifestSchema - 完整 manifest 文件
123
+ // ============================================================
124
+ const ManifestSchema = z.object({
125
+ version: z.string(),
126
+ generatedAt: z.string().refine(
127
+ (val) => !isNaN(Date.parse(val)),
128
+ { message: 'generatedAt must be a valid ISO 8601 date' }
129
+ ),
130
+ entries: z.array(ManifestEntrySchema)
131
+ });
132
+
133
+ module.exports = {
134
+ PlaceholderSchema,
135
+ ScriptPathSchema,
136
+ TemplatePathSchema,
137
+ GuidePathSchema,
138
+ AgentScriptsSchema,
139
+ FrontmatterSchema,
140
+ SourceSchema,
141
+ CommandIRSchema,
142
+ ManifestEntrySchema,
143
+ ManifestSchema
144
+ };
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Skills Registry Generator V2
3
+ *
4
+ * 从 .claude/skills/ 生成 Skills Registry:
5
+ * - 扫描技能目录提取 SKILL.md frontmatter
6
+ * - 合并 skill-rules.json 触发规则
7
+ * - 输出标准化 SkillRegistry JSON
8
+ *
9
+ * Reference: REQ-006/data-model.md#SkillRegistry
10
+ */
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+ const matter = require('gray-matter');
14
+
15
+ // ============================================================
16
+ // Constants
17
+ // ============================================================
18
+ const REGISTRY_VERSION = '1.0';
19
+ const REGISTRY_OUTPUT_PATH = 'devflow/.generated/skills-registry.json';
20
+
21
+ // ============================================================
22
+ // generateSkillsRegistry - 保留向后兼容
23
+ // ============================================================
24
+ function generateSkillsRegistry(skillsDir) {
25
+ const registry = [];
26
+ const absoluteDir = path.resolve(skillsDir);
27
+
28
+ if (!fs.existsSync(absoluteDir)) {
29
+ return registry;
30
+ }
31
+
32
+ const entries = fs.readdirSync(absoluteDir, { withFileTypes: true });
33
+
34
+ for (const entry of entries) {
35
+ if (!entry.isDirectory() || entry.name.startsWith('_')) {
36
+ continue;
37
+ }
38
+
39
+ const skillDir = path.join(absoluteDir, entry.name);
40
+ const skillMdPath = path.join(skillDir, 'SKILL.md');
41
+
42
+ if (!fs.existsSync(skillMdPath)) {
43
+ continue;
44
+ }
45
+
46
+ try {
47
+ const skillMdContent = fs.readFileSync(skillMdPath, 'utf8');
48
+ const parsed = matter(skillMdContent);
49
+
50
+ registry.push({
51
+ name: parsed.data.name || entry.name,
52
+ description: parsed.data.description || '',
53
+ type: parsed.data.type || 'utility',
54
+ path: skillDir,
55
+ triggers: []
56
+ });
57
+ } catch (error) {
58
+ console.warn(`Warning: Failed to parse skill ${entry.name}: ${error.message}`);
59
+ }
60
+ }
61
+
62
+ return registry;
63
+ }
64
+
65
+ // ============================================================
66
+ // generateSkillsRegistryV2 - 合并 skill-rules.json + SKILL.md
67
+ // ============================================================
68
+ async function generateSkillsRegistryV2(skillsDir) {
69
+ const absoluteDir = path.resolve(skillsDir);
70
+ const skills = [];
71
+
72
+ // 读取顶层 skill-rules.json
73
+ const skillRulesPath = path.join(absoluteDir, 'skill-rules.json');
74
+ let skillRules = { skills: {} };
75
+
76
+ if (fs.existsSync(skillRulesPath)) {
77
+ try {
78
+ const content = fs.readFileSync(skillRulesPath, 'utf8');
79
+ skillRules = JSON.parse(content);
80
+ } catch (error) {
81
+ console.warn(`Warning: Failed to parse skill-rules.json: ${error.message}`);
82
+ }
83
+ }
84
+
85
+ // 扫描技能目录
86
+ if (!fs.existsSync(absoluteDir)) {
87
+ return createRegistry(skills);
88
+ }
89
+
90
+ const entries = fs.readdirSync(absoluteDir, { withFileTypes: true });
91
+
92
+ for (const entry of entries) {
93
+ // 跳过非目录和 _ 前缀目录
94
+ if (!entry.isDirectory() || entry.name.startsWith('_')) {
95
+ continue;
96
+ }
97
+
98
+ const skillDir = path.join(absoluteDir, entry.name);
99
+ const skillMdPath = path.join(skillDir, 'SKILL.md');
100
+
101
+ // 必须有 SKILL.md
102
+ if (!fs.existsSync(skillMdPath)) {
103
+ continue;
104
+ }
105
+
106
+ try {
107
+ const skillEntry = parseSkillEntry(entry.name, skillDir, skillMdPath, skillRules);
108
+ if (skillEntry) {
109
+ skills.push(skillEntry);
110
+ }
111
+ } catch (error) {
112
+ console.warn(`Warning: Failed to parse skill ${entry.name}: ${error.message}`);
113
+ }
114
+ }
115
+
116
+ return createRegistry(skills);
117
+ }
118
+
119
+ // ============================================================
120
+ // parseSkillEntry - 解析单个技能
121
+ // ============================================================
122
+ function parseSkillEntry(skillName, _skillDir, skillMdPath, skillRules) {
123
+ const skillMdContent = fs.readFileSync(skillMdPath, 'utf8');
124
+ const parsed = matter(skillMdContent);
125
+
126
+ // 从 skill-rules.json 获取额外配置
127
+ const ruleConfig = skillRules.skills?.[skillName] || {};
128
+
129
+ // 合并 SKILL.md frontmatter 与 skill-rules.json
130
+ const entry = {
131
+ name: parsed.data.name || skillName,
132
+ description: parsed.data.description || ruleConfig.description || '',
133
+ type: ruleConfig.type || parsed.data.type || 'utility',
134
+ enforcement: ruleConfig.enforcement || 'suggest',
135
+ priority: ruleConfig.priority || 'medium',
136
+ skillPath: path.relative(process.cwd(), skillMdPath),
137
+ triggers: buildTriggers(ruleConfig)
138
+ };
139
+
140
+ return entry;
141
+ }
142
+
143
+ // ============================================================
144
+ // buildTriggers - 构建触发器结构
145
+ // ============================================================
146
+ function buildTriggers(ruleConfig) {
147
+ const triggers = {};
148
+
149
+ // Prompt triggers
150
+ if (ruleConfig.promptTriggers) {
151
+ triggers.prompt = {
152
+ keywords: ruleConfig.promptTriggers.keywords || [],
153
+ intentPatterns: ruleConfig.promptTriggers.intentPatterns || []
154
+ };
155
+ }
156
+
157
+ // File triggers
158
+ if (ruleConfig.fileTriggers) {
159
+ triggers.file = {
160
+ pathPatterns: ruleConfig.fileTriggers.pathPatterns || [],
161
+ contentPatterns: ruleConfig.fileTriggers.contentPatterns || []
162
+ };
163
+ }
164
+
165
+ return triggers;
166
+ }
167
+
168
+ // ============================================================
169
+ // createRegistry - 创建注册表结构
170
+ // ============================================================
171
+ function createRegistry(skills) {
172
+ return {
173
+ version: REGISTRY_VERSION,
174
+ generatedAt: new Date().toISOString(),
175
+ skills
176
+ };
177
+ }
178
+
179
+ // ============================================================
180
+ // writeSkillsRegistry - 写入注册表文件
181
+ // ============================================================
182
+ async function writeSkillsRegistry(registry) {
183
+ const outputDir = path.dirname(REGISTRY_OUTPUT_PATH);
184
+
185
+ if (!fs.existsSync(outputDir)) {
186
+ fs.mkdirSync(outputDir, { recursive: true });
187
+ }
188
+
189
+ fs.writeFileSync(REGISTRY_OUTPUT_PATH, JSON.stringify(registry, null, 2));
190
+
191
+ return REGISTRY_OUTPUT_PATH;
192
+ }
193
+
194
+ // ============================================================
195
+ // formatAsMarkdownTable - 转换为 Markdown 表格
196
+ // ============================================================
197
+ function formatAsMarkdownTable(registry) {
198
+ const skills = registry.skills || registry;
199
+
200
+ if (skills.length === 0) {
201
+ return 'No skills registered.';
202
+ }
203
+
204
+ const lines = [
205
+ '| Name | Description | Type | Enforcement | Priority |',
206
+ '|------|-------------|------|-------------|----------|'
207
+ ];
208
+
209
+ for (const skill of skills) {
210
+ lines.push(
211
+ `| ${skill.name} | ${skill.description} | ${skill.type} | ${skill.enforcement || 'suggest'} | ${skill.priority || 'medium'} |`
212
+ );
213
+ }
214
+
215
+ return lines.join('\n');
216
+ }
217
+
218
+ module.exports = {
219
+ generateSkillsRegistry,
220
+ generateSkillsRegistryV2,
221
+ writeSkillsRegistry,
222
+ formatAsMarkdownTable,
223
+ REGISTRY_VERSION,
224
+ REGISTRY_OUTPUT_PATH
225
+ };
@@ -0,0 +1,236 @@
1
+ /**
2
+ * T028: Transformer Module
3
+ *
4
+ * Transforms CommandIR for target platforms:
5
+ * - Expands {SCRIPT:alias} to "bash <path>"
6
+ * - Inlines {TEMPLATE:alias} with template file content
7
+ * - Inlines {GUIDE:alias} with guide file content
8
+ * - Expands {AGENT_SCRIPT} with platform-specific __AGENT__ substitution
9
+ * - Maps $ARGUMENTS to platform-specific syntax:
10
+ * - codex/cursor: $ARGUMENTS (unchanged)
11
+ * - qwen: {{args}}
12
+ * - antigravity: [arguments]
13
+ * - Rewrites .claude/ paths to platform-specific paths via pathMap
14
+ */
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ // ============================================================
19
+ // Platform Argument Mapping
20
+ // ============================================================
21
+ const ARGUMENT_MAPPING = {
22
+ codex: '$ARGUMENTS',
23
+ cursor: '$ARGUMENTS',
24
+ qwen: '{{args}}',
25
+ antigravity: '[arguments]'
26
+ };
27
+
28
+ // ============================================================
29
+ // readFileContent - 读取文件内容,带缓存
30
+ // ============================================================
31
+ const fileCache = new Map();
32
+
33
+ function readFileContent(filePath) {
34
+ // 检查缓存
35
+ if (fileCache.has(filePath)) {
36
+ return fileCache.get(filePath);
37
+ }
38
+
39
+ // 解析相对路径
40
+ const absolutePath = path.resolve(process.cwd(), filePath);
41
+
42
+ try {
43
+ if (!fs.existsSync(absolutePath)) {
44
+ console.warn(`Warning: File not found: ${absolutePath}`);
45
+ return `[File not found: ${filePath}]`;
46
+ }
47
+
48
+ const content = fs.readFileSync(absolutePath, 'utf8');
49
+ fileCache.set(filePath, content);
50
+ return content;
51
+ } catch (error) {
52
+ console.warn(`Warning: Cannot read file: ${absolutePath} - ${error.message}`);
53
+ return `[Cannot read: ${filePath}]`;
54
+ }
55
+ }
56
+
57
+ // ============================================================
58
+ // clearFileCache - 清除文件缓存(用于测试)
59
+ // ============================================================
60
+ function clearFileCache() {
61
+ fileCache.clear();
62
+ }
63
+
64
+ // ============================================================
65
+ // expandScriptPlaceholders - 展开 {SCRIPT:alias} 占位符
66
+ // 智能处理:如果前面已有 bash,则只替换路径;否则加 bash 前缀
67
+ // ============================================================
68
+ function expandScriptPlaceholders(content, scripts) {
69
+ if (!scripts) return content;
70
+
71
+ // 先处理已有 bash 前缀的情况: bash {SCRIPT:xxx} → bash path
72
+ content = content.replace(/bash\s+\{SCRIPT:([^}]+)\}/g, (match, alias) => {
73
+ const scriptPath = scripts[alias];
74
+ if (scriptPath) {
75
+ return `bash ${scriptPath}`;
76
+ }
77
+ return match;
78
+ });
79
+
80
+ // 再处理没有 bash 前缀的情况: {SCRIPT:xxx} → bash path
81
+ return content.replace(/\{SCRIPT:([^}]+)\}/g, (match, alias) => {
82
+ const scriptPath = scripts[alias];
83
+ if (scriptPath) {
84
+ return `bash ${scriptPath}`;
85
+ }
86
+ return match; // 保留原样,由 parser 阶段验证
87
+ });
88
+ }
89
+
90
+ // ============================================================
91
+ // expandTemplatePlaceholders - 展开 {TEMPLATE:alias} 占位符
92
+ // 将占位符替换为模板文件的实际内容
93
+ // ============================================================
94
+ function expandTemplatePlaceholders(content, templates, options = {}) {
95
+ if (!templates) return content;
96
+
97
+ const { inline = false } = options;
98
+
99
+ return content.replace(/\{TEMPLATE:([^}]+)\}/g, (match, alias) => {
100
+ const templatePath = templates[alias];
101
+ if (templatePath) {
102
+ if (inline) {
103
+ // 内联模式:读取文件内容并嵌入
104
+ const templateContent = readFileContent(templatePath);
105
+ return `\n<!-- Inlined from: ${templatePath} -->\n${templateContent}\n<!-- End of: ${templatePath} -->\n`;
106
+ }
107
+ // 默认模式:返回路径
108
+ return templatePath;
109
+ }
110
+ return match;
111
+ });
112
+ }
113
+
114
+ // ============================================================
115
+ // expandGuidePlaceholders - 展开 {GUIDE:alias} 占位符
116
+ // 将占位符替换为指南文件的实际内容
117
+ // ============================================================
118
+ function expandGuidePlaceholders(content, guides, options = {}) {
119
+ if (!guides) return content;
120
+
121
+ const { inline = false } = options;
122
+
123
+ return content.replace(/\{GUIDE:([^}]+)\}/g, (match, alias) => {
124
+ const guidePath = guides[alias];
125
+ if (guidePath) {
126
+ if (inline) {
127
+ // 内联模式:读取文件内容并嵌入
128
+ const guideContent = readFileContent(guidePath);
129
+ return `\n<!-- Inlined from: ${guidePath} -->\n${guideContent}\n<!-- End of: ${guidePath} -->\n`;
130
+ }
131
+ // 默认模式:返回路径
132
+ return guidePath;
133
+ }
134
+ return match;
135
+ });
136
+ }
137
+
138
+ // ============================================================
139
+ // expandAgentScript - 展开 {AGENT_SCRIPT} 占位符
140
+ // ============================================================
141
+ function expandAgentScript(content, agentScripts, platform) {
142
+ if (!agentScripts || !agentScripts.sh) {
143
+ return content;
144
+ }
145
+
146
+ // 替换 __AGENT__ 为平台名称
147
+ const scriptContent = agentScripts.sh.replace(/__AGENT__/g, platform);
148
+
149
+ // 展开 {AGENT_SCRIPT}
150
+ return content.replace(/\{AGENT_SCRIPT\}/g, scriptContent);
151
+ }
152
+
153
+ // ============================================================
154
+ // mapArguments - 映射 $ARGUMENTS 到平台语法
155
+ // ============================================================
156
+ function mapArguments(content, platform) {
157
+ const targetSyntax = ARGUMENT_MAPPING[platform];
158
+ if (!targetSyntax || targetSyntax === '$ARGUMENTS') {
159
+ return content;
160
+ }
161
+
162
+ return content.replace(/\$ARGUMENTS/g, targetSyntax);
163
+ }
164
+
165
+ // ============================================================
166
+ // rewritePaths - 重写内容中的 .claude/ 路径为平台路径
167
+ // ============================================================
168
+ function rewritePaths(content, pathMap) {
169
+ if (!pathMap || Object.keys(pathMap).length === 0) {
170
+ return content;
171
+ }
172
+
173
+ let result = content;
174
+
175
+ // 按路径长度降序排序,避免短路径替换长路径的部分
176
+ const sortedPaths = Object.keys(pathMap).sort((a, b) => b.length - a.length);
177
+
178
+ for (const sourcePath of sortedPaths) {
179
+ const targetPath = pathMap[sourcePath];
180
+ // 全局替换
181
+ result = result.split(sourcePath).join(targetPath);
182
+ }
183
+
184
+ return result;
185
+ }
186
+
187
+ // ============================================================
188
+ // transformForPlatform - 主转换函数
189
+ // ============================================================
190
+ function transformForPlatform(ir, platform, options = {}) {
191
+ let body = ir.body;
192
+
193
+ // 默认关闭内联,保持引用(仅替换为路径)
194
+ const inlineOptions = { inline: options.inline === true };
195
+ const pathMap = options.pathMap || {};
196
+
197
+ // 1. 展开 {SCRIPT:alias} - 第一轮
198
+ body = expandScriptPlaceholders(body, ir.frontmatter.scripts);
199
+
200
+ // 2. 展开 {TEMPLATE:alias} - 内联模板内容
201
+ body = expandTemplatePlaceholders(body, ir.frontmatter.templates, inlineOptions);
202
+
203
+ // 3. 展开 {GUIDE:alias} - 内联指南内容
204
+ body = expandGuidePlaceholders(body, ir.frontmatter.guides, inlineOptions);
205
+
206
+ // 4. 递归展开内联内容中的 {SCRIPT:alias}
207
+ // 模板/指南中可能也包含 {SCRIPT:xxx},需要用原始 frontmatter 的 scripts 展开
208
+ body = expandScriptPlaceholders(body, ir.frontmatter.scripts);
209
+
210
+ // 5. 展开 {AGENT_SCRIPT}
211
+ body = expandAgentScript(body, ir.frontmatter.agent_scripts, platform);
212
+
213
+ // 6. 映射 $ARGUMENTS
214
+ body = mapArguments(body, platform);
215
+
216
+ // 7. 重写 .claude/ 路径为平台路径
217
+ body = rewritePaths(body, pathMap);
218
+
219
+ return {
220
+ body,
221
+ frontmatter: ir.frontmatter
222
+ };
223
+ }
224
+
225
+ module.exports = {
226
+ transformForPlatform,
227
+ expandScriptPlaceholders,
228
+ expandTemplatePlaceholders,
229
+ expandGuidePlaceholders,
230
+ expandAgentScript,
231
+ mapArguments,
232
+ rewritePaths,
233
+ readFileContent,
234
+ clearFileCache,
235
+ ARGUMENT_MAPPING
236
+ };
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "cc-devflow",
3
+ "version": "1.0.1",
4
+ "description": "DevFlow CLI tool",
5
+ "main": "bin/cc-devflow.js",
6
+ "bin": {
7
+ "cc-devflow": "bin/cc-devflow-cli.js"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "lib/",
12
+ "config/",
13
+ ".claude/",
14
+ "docs/",
15
+ "README.md",
16
+ "README.zh-CN.md",
17
+ "CHANGELOG.md",
18
+ "LICENSE",
19
+ "package.json"
20
+ ],
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "license": "MIT",
25
+ "scripts": {
26
+ "prepublishOnly": "node scripts/validate-publish.js",
27
+ "test": "jest",
28
+ "start": "node bin/cc-devflow.js",
29
+ "adapt": "node bin/adapt.js",
30
+ "adapt:check": "node bin/adapt.js --check",
31
+ "adapt:skills": "node bin/adapt.js --skills",
32
+ "adapt:rules": "node bin/adapt.js --rules",
33
+ "adapt:codex": "node bin/adapt.js --platform codex",
34
+ "adapt:cursor": "node bin/adapt.js --platform cursor",
35
+ "adapt:qwen": "node bin/adapt.js --platform qwen",
36
+ "adapt:antigravity": "node bin/adapt.js --platform antigravity"
37
+ },
38
+ "dependencies": {
39
+ "gray-matter": "^4.0.3",
40
+ "@iarna/toml": "^2.2.5",
41
+ "js-yaml": "^4.1.0",
42
+ "zod": "^3.22.4"
43
+ },
44
+ "devDependencies": {
45
+ "jest": "^29.7.0"
46
+ },
47
+ "engines": {
48
+ "node": ">=18"
49
+ }
50
+ }