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,39 @@
1
+ /**
2
+ * T034: QwenEmitter - Qwen 平台输出
3
+ *
4
+ * 输出格式: TOML
5
+ * 目录: .qwen/commands/
6
+ * 字段: description, prompt
7
+ */
8
+ const toml = require('@iarna/toml');
9
+ const BaseEmitter = require('./base-emitter.js');
10
+
11
+ class QwenEmitter extends BaseEmitter {
12
+ get name() {
13
+ return 'qwen';
14
+ }
15
+
16
+ get outputDir() {
17
+ return '.qwen/commands';
18
+ }
19
+
20
+ get fileExtension() {
21
+ return '.toml';
22
+ }
23
+
24
+ /**
25
+ * 格式化为 Qwen TOML 格式
26
+ * - description: 命令描述
27
+ * - prompt: Markdown 正文
28
+ */
29
+ format(ir, transformedContent) {
30
+ const tomlObj = {
31
+ description: ir.frontmatter.description,
32
+ prompt: transformedContent
33
+ };
34
+
35
+ return toml.stringify(tomlObj);
36
+ }
37
+ }
38
+
39
+ module.exports = QwenEmitter;
@@ -0,0 +1,119 @@
1
+ /**
2
+ * T024: Compiler Error Types
3
+ *
4
+ * Custom error classes for Command Emitter:
5
+ * - CompilerError: Base class
6
+ * - MissingFrontmatterError: File lacks YAML frontmatter
7
+ * - InvalidFrontmatterError: Frontmatter validation failed
8
+ * - UnknownAliasError: {SCRIPT:alias} references undefined alias
9
+ * - UnknownTemplateAliasError: {TEMPLATE:alias} references undefined alias
10
+ * - UnknownGuideAliasError: {GUIDE:alias} references undefined alias
11
+ * - WriteError: File write operation failed
12
+ * - ContentTooLargeError: Content exceeds platform limit
13
+ */
14
+
15
+ // ============================================================
16
+ // CompilerError - 基类
17
+ // ============================================================
18
+ class CompilerError extends Error {
19
+ constructor(message) {
20
+ super(message);
21
+ this.name = 'CompilerError';
22
+ Error.captureStackTrace(this, this.constructor);
23
+ }
24
+ }
25
+
26
+ // ============================================================
27
+ // MissingFrontmatterError - 缺少 frontmatter
28
+ // ============================================================
29
+ class MissingFrontmatterError extends CompilerError {
30
+ constructor(filePath) {
31
+ super(`Missing YAML frontmatter in file: ${filePath}`);
32
+ this.name = 'MissingFrontmatterError';
33
+ this.filePath = filePath;
34
+ }
35
+ }
36
+
37
+ // ============================================================
38
+ // InvalidFrontmatterError - frontmatter 格式错误
39
+ // ============================================================
40
+ class InvalidFrontmatterError extends CompilerError {
41
+ constructor(filePath, reason) {
42
+ super(`Invalid frontmatter in ${filePath}: ${reason}`);
43
+ this.name = 'InvalidFrontmatterError';
44
+ this.filePath = filePath;
45
+ this.reason = reason;
46
+ }
47
+ }
48
+
49
+ // ============================================================
50
+ // UnknownAliasError - 未知 script alias
51
+ // ============================================================
52
+ class UnknownAliasError extends CompilerError {
53
+ constructor(filePath, alias) {
54
+ super(`Unknown script alias '${alias}' in file: ${filePath}`);
55
+ this.name = 'UnknownAliasError';
56
+ this.filePath = filePath;
57
+ this.alias = alias;
58
+ }
59
+ }
60
+
61
+ // ============================================================
62
+ // UnknownTemplateAliasError - 未知 template alias
63
+ // ============================================================
64
+ class UnknownTemplateAliasError extends CompilerError {
65
+ constructor(filePath, alias) {
66
+ super(`Unknown template alias '${alias}' in file: ${filePath}`);
67
+ this.name = 'UnknownTemplateAliasError';
68
+ this.filePath = filePath;
69
+ this.alias = alias;
70
+ }
71
+ }
72
+
73
+ // ============================================================
74
+ // UnknownGuideAliasError - 未知 guide alias
75
+ // ============================================================
76
+ class UnknownGuideAliasError extends CompilerError {
77
+ constructor(filePath, alias) {
78
+ super(`Unknown guide alias '${alias}' in file: ${filePath}`);
79
+ this.name = 'UnknownGuideAliasError';
80
+ this.filePath = filePath;
81
+ this.alias = alias;
82
+ }
83
+ }
84
+
85
+ // ============================================================
86
+ // WriteError - 写入失败
87
+ // ============================================================
88
+ class WriteError extends CompilerError {
89
+ constructor(filePath, cause) {
90
+ super(`Failed to write file ${filePath}: ${cause}`);
91
+ this.name = 'WriteError';
92
+ this.filePath = filePath;
93
+ this.cause = cause;
94
+ }
95
+ }
96
+
97
+ // ============================================================
98
+ // ContentTooLargeError - 内容超限
99
+ // ============================================================
100
+ class ContentTooLargeError extends CompilerError {
101
+ constructor(filePath, actualSize, limit) {
102
+ super(`Content too large in ${filePath}: ${actualSize} chars exceeds limit of ${limit}`);
103
+ this.name = 'ContentTooLargeError';
104
+ this.filePath = filePath;
105
+ this.actualSize = actualSize;
106
+ this.limit = limit;
107
+ }
108
+ }
109
+
110
+ module.exports = {
111
+ CompilerError,
112
+ MissingFrontmatterError,
113
+ InvalidFrontmatterError,
114
+ UnknownAliasError,
115
+ UnknownTemplateAliasError,
116
+ UnknownGuideAliasError,
117
+ WriteError,
118
+ ContentTooLargeError
119
+ };
@@ -0,0 +1,256 @@
1
+ /**
2
+ * Compiler Entry Point (v2.0)
3
+ *
4
+ * 编译器主入口:
5
+ * - compile(options): 编译命令文件到目标平台
6
+ * - 协调 parser, transformer, emitters, manifest
7
+ * - 复制资源文件并重写路径
8
+ * - 生成 skills-registry.json 和规则入口文件
9
+ *
10
+ * v2.0 (REQ-006): 支持 --rules, --skills 参数
11
+ */
12
+ const path = require('path');
13
+
14
+ const { parseAllCommands } = require('./parser.js');
15
+ const { transformForPlatform } = require('./transformer.js');
16
+ const { getEmitter, getAllEmitters, PLATFORMS } = require('./emitters/index.js');
17
+ const {
18
+ loadManifest,
19
+ saveManifest,
20
+ needsRecompile,
21
+ addEntry,
22
+ createEntry,
23
+ createManifest,
24
+ hashContent,
25
+ migrateToV2,
26
+ addSkillEntry,
27
+ addRulesEntry,
28
+ needsSkillRecompile,
29
+ needsRulesRecompile,
30
+ MANIFEST_PATH
31
+ } = require('./manifest.js');
32
+ const {
33
+ collectReferencedResources,
34
+ copyResourcesForAllPlatforms,
35
+ mapPathToPlatform
36
+ } = require('./resource-copier.js');
37
+ const { generateSkillsRegistryV2, writeSkillsRegistry } = require('./skills-registry.js');
38
+ const { getRulesEmitter, emitAllRules } = require('./rules-emitters/index.js');
39
+
40
+ // ============================================================
41
+ // compile - 编译主函数
42
+ // ============================================================
43
+ async function compile(options = {}) {
44
+ const {
45
+ sourceDir = '.claude/commands/',
46
+ skillsDir = '.claude/skills/',
47
+ outputBaseDir = '.',
48
+ platforms = PLATFORMS,
49
+ verbose = false,
50
+ check = false,
51
+ rules = true,
52
+ skills = true
53
+ } = options;
54
+
55
+ // 验证平台参数
56
+ for (const platform of platforms) {
57
+ if (!PLATFORMS.includes(platform)) {
58
+ throw new Error(`Unknown platform: ${platform}`);
59
+ }
60
+ }
61
+
62
+ const result = {
63
+ success: true,
64
+ platforms: platforms,
65
+ filesCompiled: 0,
66
+ filesSkipped: 0,
67
+ resourcesCopied: 0,
68
+ resourcesSkipped: 0,
69
+ rulesGenerated: 0,
70
+ skillsRegistered: 0,
71
+ errors: []
72
+ };
73
+
74
+ // 加载 manifest 并迁移到 v2.0
75
+ const manifestPath = path.join(outputBaseDir, MANIFEST_PATH);
76
+ let manifest = await loadManifest(manifestPath);
77
+ manifest = migrateToV2(manifest);
78
+
79
+ // 如果是 check 模式,只做漂移检测
80
+ if (check) {
81
+ const { checkDrift } = require('./manifest.js');
82
+ const drift = await checkDrift(manifest);
83
+ return {
84
+ ...result,
85
+ check: true,
86
+ drift,
87
+ success: drift.length === 0
88
+ };
89
+ }
90
+
91
+ // 生成 skills registry
92
+ let registry = null;
93
+ if (skills) {
94
+ try {
95
+ registry = await generateSkillsRegistryV2(skillsDir);
96
+ await writeSkillsRegistry(registry);
97
+ result.skillsRegistered = registry.skills.length;
98
+
99
+ // 更新 manifest 中的技能记录
100
+ for (const skill of registry.skills) {
101
+ const skillHash = hashContent(JSON.stringify(skill));
102
+ addSkillEntry(manifest, {
103
+ name: skill.name,
104
+ sourceHash: skillHash,
105
+ timestamp: new Date().toISOString()
106
+ });
107
+ }
108
+
109
+ if (verbose) {
110
+ console.log(`Generated skills-registry.json with ${registry.skills.length} skills`);
111
+ }
112
+ } catch (error) {
113
+ result.errors.push(`Skills registry: ${error.message}`);
114
+ }
115
+ }
116
+
117
+ // 解析所有命令文件
118
+ const absoluteSourceDir = path.resolve(sourceDir);
119
+ let irs = [];
120
+ try {
121
+ irs = await parseAllCommands(absoluteSourceDir);
122
+ } catch (error) {
123
+ result.success = false;
124
+ result.errors.push(error.message);
125
+ return result;
126
+ }
127
+
128
+ if (verbose) {
129
+ console.log(`Found ${irs.length} command files`);
130
+ }
131
+
132
+ // 生成规则入口文件
133
+ if (rules && registry) {
134
+ try {
135
+ const commands = irs.map(ir => ({
136
+ name: ir.source.filename.replace(/\.md$/, ''),
137
+ description: ir.frontmatter?.description || ''
138
+ }));
139
+
140
+ const rulesResults = await emitAllRules(registry, commands, { platforms });
141
+
142
+ for (const ruleResult of rulesResults) {
143
+ if (ruleResult.error) {
144
+ result.errors.push(`Rules ${ruleResult.platform}: ${ruleResult.error}`);
145
+ } else {
146
+ result.rulesGenerated++;
147
+
148
+ // 更新 manifest
149
+ addRulesEntry(manifest, ruleResult.platform, {
150
+ path: ruleResult.path,
151
+ hash: ruleResult.hash,
152
+ timestamp: ruleResult.timestamp
153
+ });
154
+
155
+ if (verbose) {
156
+ console.log(`Generated rules entry: ${ruleResult.path}`);
157
+ }
158
+ }
159
+ }
160
+ } catch (error) {
161
+ result.errors.push(`Rules generation: ${error.message}`);
162
+ }
163
+ }
164
+
165
+ // 复制资源文件到各平台目录
166
+ const copyResult = await copyResourcesForAllPlatforms(irs, platforms, { verbose });
167
+ result.resourcesCopied = copyResult.totalCopied;
168
+ result.resourcesSkipped = copyResult.totalSkipped;
169
+
170
+ if (verbose && copyResult.totalCopied > 0) {
171
+ console.log(`Copied ${copyResult.totalCopied} resource files (${copyResult.totalSkipped} unchanged)`);
172
+ }
173
+
174
+ // 为每个平台构建路径映射
175
+ const platformPathMaps = copyResult.allPathMaps;
176
+
177
+ // 编译每个文件到每个平台
178
+ for (const ir of irs) {
179
+ for (const platform of platforms) {
180
+ // 检查是否需要重新编译
181
+ const sourceRelative = path.relative(outputBaseDir, ir.source.path);
182
+ if (!needsRecompile(sourceRelative, ir.source.hash, manifest, platform)) {
183
+ result.filesSkipped++;
184
+ if (verbose) {
185
+ console.log(`Skipped: ${ir.source.filename} -> ${platform} (unchanged)`);
186
+ }
187
+ continue;
188
+ }
189
+
190
+ try {
191
+ // 获取该平台的路径映射
192
+ const pathMap = platformPathMaps[platform] || {};
193
+
194
+ // 转换(传入 pathMap 以重写路径)
195
+ const transformed = transformForPlatform(ir, platform, { pathMap });
196
+
197
+ // 获取 emitter
198
+ const emitter = getEmitter(platform);
199
+
200
+ // 格式化
201
+ const formatted = emitter.format(ir, transformed.body);
202
+
203
+ // 处理拆分文件(Antigravity 可能返回数组)
204
+ if (Array.isArray(formatted)) {
205
+ for (const part of formatted) {
206
+ const emitResult = await emitter.emit(part.filename, part.content);
207
+
208
+ // 更新 manifest
209
+ addEntry(manifest, createEntry({
210
+ source: sourceRelative,
211
+ target: emitResult.path,
212
+ sourceHash: ir.source.hash,
213
+ targetHash: emitResult.hash,
214
+ platform
215
+ }));
216
+
217
+ if (verbose) {
218
+ console.log(`Compiled: ${ir.source.filename} -> ${platform} (${part.filename})`);
219
+ }
220
+ }
221
+ } else {
222
+ const emitResult = await emitter.emit(ir.source.filename, formatted);
223
+
224
+ // 更新 manifest
225
+ addEntry(manifest, createEntry({
226
+ source: sourceRelative,
227
+ target: emitResult.path,
228
+ sourceHash: ir.source.hash,
229
+ targetHash: emitResult.hash,
230
+ platform
231
+ }));
232
+
233
+ if (verbose) {
234
+ console.log(`Compiled: ${ir.source.filename} -> ${platform}`);
235
+ }
236
+ }
237
+
238
+ result.filesCompiled++;
239
+ } catch (error) {
240
+ result.success = false;
241
+ result.errors.push(`${ir.source.filename} -> ${platform}: ${error.message}`);
242
+ }
243
+ }
244
+ }
245
+
246
+ // 保存 manifest
247
+ manifest.generatedAt = new Date().toISOString();
248
+ await saveManifest(manifest, manifestPath);
249
+
250
+ return result;
251
+ }
252
+
253
+ module.exports = {
254
+ compile,
255
+ PLATFORMS
256
+ };
@@ -0,0 +1,242 @@
1
+ /**
2
+ * T039: Manifest Module (v2.0)
3
+ *
4
+ * 管理编译清单:
5
+ * - hashContent(): 计算 SHA-256 哈希
6
+ * - loadManifest() / saveManifest(): 持久化
7
+ * - needsRecompile(): 增量编译判断
8
+ * - addEntry(): 添加/更新条目
9
+ * - checkDrift(): 漂移检测
10
+ *
11
+ * v2.0 新增 (REQ-006):
12
+ * - skills: 技能编译记录
13
+ * - rulesEntry: 规则入口文件记录
14
+ * - migrateToV2(): v1.0 → v2.0 迁移
15
+ */
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+ const crypto = require('crypto');
19
+
20
+ const MANIFEST_PATH = 'devflow/.generated/manifest.json';
21
+ const MANIFEST_VERSION = '2.0';
22
+
23
+ // ============================================================
24
+ // hashContent - 计算 SHA-256 哈希
25
+ // ============================================================
26
+ function hashContent(content) {
27
+ return crypto.createHash('sha256').update(content).digest('hex');
28
+ }
29
+
30
+ // ============================================================
31
+ // createEntry - 创建 manifest 条目
32
+ // ============================================================
33
+ function createEntry({ source, target, sourceHash, targetHash, platform }) {
34
+ return {
35
+ source,
36
+ target,
37
+ hash: sourceHash,
38
+ timestamp: new Date().toISOString(),
39
+ platform
40
+ };
41
+ }
42
+
43
+ // ============================================================
44
+ // loadManifest - 加载现有 manifest
45
+ // ============================================================
46
+ async function loadManifest(manifestPath = MANIFEST_PATH) {
47
+ try {
48
+ const content = await fs.promises.readFile(manifestPath, 'utf8');
49
+ return JSON.parse(content);
50
+ } catch (error) {
51
+ if (error.code === 'ENOENT') {
52
+ return null;
53
+ }
54
+ throw error;
55
+ }
56
+ }
57
+
58
+ // ============================================================
59
+ // saveManifest - 保存 manifest
60
+ // ============================================================
61
+ async function saveManifest(manifest, manifestPath = MANIFEST_PATH) {
62
+ const dir = path.dirname(manifestPath);
63
+ await fs.promises.mkdir(dir, { recursive: true });
64
+ await fs.promises.writeFile(manifestPath, JSON.stringify(manifest, null, 2), 'utf8');
65
+ }
66
+
67
+ // ============================================================
68
+ // needsRecompile - 检查是否需要重新编译
69
+ // ============================================================
70
+ function needsRecompile(sourcePath, sourceHash, manifest, platform) {
71
+ if (!manifest || !manifest.entries) {
72
+ return true;
73
+ }
74
+
75
+ const entry = manifest.entries.find(e => e.source === sourcePath && e.platform === platform);
76
+ if (!entry) {
77
+ return true;
78
+ }
79
+
80
+ return entry.hash !== sourceHash;
81
+ }
82
+
83
+ // ============================================================
84
+ // addEntry - 添加或更新条目
85
+ // ============================================================
86
+ function addEntry(manifest, entry) {
87
+ const existingIndex = manifest.entries.findIndex(e => e.source === entry.source && e.platform === entry.platform);
88
+
89
+ if (existingIndex >= 0) {
90
+ manifest.entries[existingIndex] = entry;
91
+ } else {
92
+ manifest.entries.push(entry);
93
+ }
94
+ }
95
+
96
+ // ============================================================
97
+ // checkDrift - 检查漂移(目标文件被手动修改)
98
+ // ============================================================
99
+ async function checkDrift(manifest) {
100
+ const driftReport = [];
101
+
102
+ if (!manifest || !manifest.entries) {
103
+ return driftReport;
104
+ }
105
+
106
+ for (const entry of manifest.entries) {
107
+ try {
108
+ // 读取目标文件当前内容
109
+ const targetContent = await fs.promises.readFile(entry.target, 'utf8');
110
+ const targetCurrentHash = hashContent(targetContent);
111
+
112
+ // 漂移检测:比较目标文件当前哈希与 manifest 记录的哈希
113
+ // 如果不一致,说明目标文件被手动修改了
114
+ if (targetCurrentHash !== entry.hash) {
115
+ driftReport.push({
116
+ source: entry.source,
117
+ target: entry.target,
118
+ issue: 'target file modified since last compile'
119
+ });
120
+ }
121
+ } catch (error) {
122
+ if (error.code === 'ENOENT') {
123
+ driftReport.push({
124
+ source: entry.source,
125
+ target: entry.target,
126
+ issue: 'target file missing'
127
+ });
128
+ }
129
+ }
130
+ }
131
+
132
+ return driftReport;
133
+ }
134
+
135
+ // ============================================================
136
+ // createManifest - 创建新的空 manifest (v2.0)
137
+ // ============================================================
138
+ function createManifest() {
139
+ return {
140
+ version: MANIFEST_VERSION,
141
+ generatedAt: new Date().toISOString(),
142
+ entries: [],
143
+ skills: [],
144
+ rulesEntry: {}
145
+ };
146
+ }
147
+
148
+ // ============================================================
149
+ // migrateToV2 - 从 v1.0 迁移到 v2.0
150
+ // ============================================================
151
+ function migrateToV2(manifest) {
152
+ if (!manifest) {
153
+ return createManifest();
154
+ }
155
+
156
+ // 已是 v2.0
157
+ if (manifest.version === '2.0' || manifest.version === MANIFEST_VERSION) {
158
+ return manifest;
159
+ }
160
+
161
+ // v1.0 → v2.0 迁移
162
+ return {
163
+ version: MANIFEST_VERSION,
164
+ generatedAt: manifest.generatedAt || new Date().toISOString(),
165
+ entries: manifest.entries || [],
166
+ skills: [],
167
+ rulesEntry: {}
168
+ };
169
+ }
170
+
171
+ // ============================================================
172
+ // addSkillEntry - 添加或更新技能记录
173
+ // ============================================================
174
+ function addSkillEntry(manifest, skillEntry) {
175
+ if (!manifest.skills) {
176
+ manifest.skills = [];
177
+ }
178
+
179
+ const existingIndex = manifest.skills.findIndex(s => s.name === skillEntry.name);
180
+
181
+ if (existingIndex >= 0) {
182
+ manifest.skills[existingIndex] = skillEntry;
183
+ } else {
184
+ manifest.skills.push(skillEntry);
185
+ }
186
+ }
187
+
188
+ // ============================================================
189
+ // addRulesEntry - 添加或更新规则入口文件记录
190
+ // ============================================================
191
+ function addRulesEntry(manifest, platform, rulesEntry) {
192
+ if (!manifest.rulesEntry) {
193
+ manifest.rulesEntry = {};
194
+ }
195
+
196
+ manifest.rulesEntry[platform] = rulesEntry;
197
+ }
198
+
199
+ // ============================================================
200
+ // needsSkillRecompile - 检查技能是否需要重新编译
201
+ // ============================================================
202
+ function needsSkillRecompile(skillName, sourceHash, manifest) {
203
+ if (!manifest || !manifest.skills) {
204
+ return true;
205
+ }
206
+
207
+ const entry = manifest.skills.find(s => s.name === skillName);
208
+ if (!entry) {
209
+ return true;
210
+ }
211
+
212
+ return entry.sourceHash !== sourceHash;
213
+ }
214
+
215
+ // ============================================================
216
+ // needsRulesRecompile - 检查规则入口是否需要重新编译
217
+ // ============================================================
218
+ function needsRulesRecompile(platform, sourceHash, manifest) {
219
+ if (!manifest || !manifest.rulesEntry || !manifest.rulesEntry[platform]) {
220
+ return true;
221
+ }
222
+
223
+ return manifest.rulesEntry[platform].hash !== sourceHash;
224
+ }
225
+
226
+ module.exports = {
227
+ MANIFEST_PATH,
228
+ MANIFEST_VERSION,
229
+ hashContent,
230
+ createEntry,
231
+ loadManifest,
232
+ saveManifest,
233
+ needsRecompile,
234
+ addEntry,
235
+ checkDrift,
236
+ createManifest,
237
+ migrateToV2,
238
+ addSkillEntry,
239
+ addRulesEntry,
240
+ needsSkillRecompile,
241
+ needsRulesRecompile
242
+ };