cc-devflow 2.4.6 → 4.1.0

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 (191) hide show
  1. package/.claude/CLAUDE.md +1065 -48
  2. package/.claude/agents/dev-implementer.md +195 -0
  3. package/.claude/commands/{flow-archive.md → flow/archive.md} +46 -11
  4. package/.claude/commands/flow/context.md +150 -0
  5. package/.claude/commands/flow/delta.md +245 -0
  6. package/.claude/commands/{flow-dev.md → flow/dev.md} +112 -11
  7. package/.claude/commands/flow/init.md +45 -0
  8. package/.claude/commands/flow/quality.md +159 -0
  9. package/.claude/commands/flow/spec.md +186 -0
  10. package/.claude/commands/flow/workspace.md +146 -0
  11. package/.claude/commands/{cancel-ralph.md → util/cancel-ralph.md} +1 -0
  12. package/.claude/config/quality-gates.yml +305 -0
  13. package/.claude/docs/guides/TEAM_MODE_GUIDE.md +313 -0
  14. package/.claude/docs/templates/DELTA_SPEC_TEMPLATE.md +91 -0
  15. package/.claude/docs/templates/DESIGN_DECISIONS_TEMPLATE.md +151 -0
  16. package/.claude/docs/templates/JOURNAL_TEMPLATE.md +75 -0
  17. package/.claude/docs/templates/_shared/CLAUDE.md +36 -0
  18. package/.claude/docs/templates/_shared/CONSTITUTION_CHECK.md +125 -0
  19. package/.claude/docs/templates/_shared/VALIDATION_CHECKLIST.md +187 -0
  20. package/.claude/docs/templates/_shared/YAML_FRONTMATTER.md +164 -0
  21. package/.claude/docs/templates/context/dev.jsonl.template +6 -0
  22. package/.claude/docs/templates/context/epic.jsonl.template +5 -0
  23. package/.claude/docs/templates/context/prd.jsonl.template +4 -0
  24. package/.claude/docs/templates/context/research.jsonl.template +4 -0
  25. package/.claude/docs/templates/context/review.jsonl.template +5 -0
  26. package/.claude/docs/templates/context/tech.jsonl.template +5 -0
  27. package/.claude/hooks/CLAUDE.md +342 -0
  28. package/.claude/hooks/inject-agent-context.ts +480 -0
  29. package/.claude/hooks/inject-skill-context.ts +359 -0
  30. package/.claude/hooks/ralph-loop.ts +931 -0
  31. package/.claude/hooks/task-completed-hook.ts +593 -0
  32. package/.claude/hooks/teammate-idle-hook.ts +690 -0
  33. package/.claude/hooks/types/team-types.d.ts +238 -0
  34. package/.claude/rules/devflow-conventions.md +82 -9
  35. package/.claude/scripts/archive-requirement.sh +44 -1
  36. package/.claude/scripts/common.sh +670 -3
  37. package/.claude/scripts/delta-parser.ts +527 -0
  38. package/.claude/scripts/detect-file-conflicts.sh +151 -0
  39. package/.claude/scripts/flow-context-add.sh +134 -0
  40. package/.claude/scripts/flow-context-init.sh +133 -0
  41. package/.claude/scripts/flow-context-validate.sh +144 -0
  42. package/.claude/scripts/flow-delta-apply.sh +297 -0
  43. package/.claude/scripts/flow-delta-archive.sh +71 -0
  44. package/.claude/scripts/flow-delta-create.sh +202 -0
  45. package/.claude/scripts/flow-delta-list.sh +142 -0
  46. package/.claude/scripts/flow-delta-status.sh +235 -0
  47. package/.claude/scripts/flow-quality-full.sh +184 -0
  48. package/.claude/scripts/flow-quality-quick.sh +64 -0
  49. package/.claude/scripts/flow-workspace-init.sh +117 -0
  50. package/.claude/scripts/flow-workspace-record.sh +164 -0
  51. package/.claude/scripts/flow-workspace-start.sh +88 -0
  52. package/.claude/scripts/get-workflow-status.sh +415 -0
  53. package/.claude/scripts/parse-task-dependencies.js +334 -0
  54. package/.claude/scripts/record-quality-error.sh +165 -0
  55. package/.claude/scripts/run-quality-gates.sh +242 -0
  56. package/.claude/scripts/team-dev-init.sh +319 -0
  57. package/.claude/scripts/team-state-recovery.sh +229 -0
  58. package/.claude/scripts/workflow-status.ts +433 -0
  59. package/.claude/settings.json +19 -0
  60. package/.claude/skills/cc-devflow-orchestrator/SKILL.md +85 -200
  61. package/.claude/skills/domain/using-git-worktrees/SKILL.md +252 -0
  62. package/.claude/skills/domain/using-git-worktrees/assets/SHELL_ALIASES.md +133 -0
  63. package/.claude/skills/domain/using-git-worktrees/context.jsonl +4 -0
  64. package/.claude/skills/domain/using-git-worktrees/scripts/worktree-cleanup.sh +218 -0
  65. package/.claude/skills/domain/using-git-worktrees/scripts/worktree-create.sh +232 -0
  66. package/.claude/skills/domain/using-git-worktrees/scripts/worktree-list.sh +130 -0
  67. package/.claude/skills/domain/using-git-worktrees/scripts/worktree-status.sh +140 -0
  68. package/.claude/skills/domain/using-git-worktrees/scripts/worktree-switch.sh +70 -0
  69. package/.claude/skills/skill-rules.json +72 -1
  70. package/.claude/skills/utility/journey-checker/SKILL.md +199 -0
  71. package/.claude/skills/utility/journey-checker/pressure-scenarios.md +164 -0
  72. package/.claude/skills/utility/skill-creator/LICENSE.txt +202 -0
  73. package/.claude/skills/utility/skill-creator/SKILL.md +356 -0
  74. package/.claude/skills/utility/skill-creator/references/output-patterns.md +82 -0
  75. package/.claude/skills/utility/skill-creator/references/workflows.md +28 -0
  76. package/.claude/skills/utility/skill-creator/scripts/init_skill.py +303 -0
  77. package/.claude/skills/utility/skill-creator/scripts/package_skill.py +110 -0
  78. package/.claude/skills/utility/skill-creator/scripts/quick_validate.py +95 -0
  79. package/.claude/skills/workflow/flow-dev/CLAUDE.md +78 -0
  80. package/.claude/skills/workflow/flow-dev/SKILL.md +96 -0
  81. package/.claude/skills/workflow/flow-dev/assets/IMPLEMENTATION_PLAN_TEMPLATE.md +71 -0
  82. package/.claude/skills/workflow/flow-dev/context.jsonl +8 -0
  83. package/.claude/skills/workflow/flow-dev/dev-implementer.jsonl +8 -0
  84. package/.claude/skills/workflow/flow-dev/scripts/entry-gate.sh +116 -0
  85. package/.claude/skills/workflow/flow-dev/scripts/exit-gate.sh +101 -0
  86. package/.claude/skills/workflow/flow-dev/scripts/task-orchestrator.sh +106 -0
  87. package/.claude/skills/workflow/flow-fix/SKILL.md +105 -0
  88. package/.claude/skills/workflow/flow-fix/context.jsonl +6 -0
  89. package/.claude/skills/workflow/flow-fix/references/bug-analyzer.md +381 -0
  90. package/.claude/skills/workflow/flow-init/SKILL.md +211 -0
  91. package/.claude/skills/workflow/flow-init/assets/BRAINSTORM_TEMPLATE.md +148 -0
  92. package/.claude/skills/workflow/flow-init/assets/INIT_FLOW_TEMPLATE.md +198 -0
  93. package/.claude/skills/workflow/flow-init/assets/RESEARCH_TEMPLATE.md +276 -0
  94. package/.claude/skills/workflow/flow-init/context.jsonl +5 -0
  95. package/.claude/skills/workflow/flow-init/references/flow-researcher.md +132 -0
  96. package/.claude/skills/workflow/flow-init/scripts/check-prerequisites.sh +232 -0
  97. package/.claude/skills/workflow/flow-init/scripts/consolidate-research.sh +182 -0
  98. package/.claude/skills/workflow/flow-init/scripts/create-requirement.sh +515 -0
  99. package/.claude/skills/workflow/flow-init/scripts/generate-research-tasks.sh +157 -0
  100. package/.claude/skills/workflow/flow-init/scripts/populate-research-tasks.sh +284 -0
  101. package/.claude/skills/workflow/flow-init/scripts/validate-research.sh +332 -0
  102. package/.claude/skills/workflow/flow-quality/SKILL.md +94 -0
  103. package/.claude/skills/workflow/flow-quality/context.jsonl +6 -0
  104. package/.claude/skills/workflow/flow-quality/references/code-quality-reviewer.md +205 -0
  105. package/.claude/skills/workflow/flow-quality/references/qa-tester.md +313 -0
  106. package/.claude/skills/workflow/flow-quality/references/security-reviewer.md +314 -0
  107. package/.claude/skills/workflow/flow-quality/references/spec-reviewer.md +221 -0
  108. package/.claude/skills/workflow/flow-release/SKILL.md +126 -0
  109. package/.claude/skills/workflow/flow-release/context.jsonl +7 -0
  110. package/.claude/skills/workflow/flow-release/references/release-manager.md +295 -0
  111. package/.claude/skills/workflow/flow-spec/CLAUDE.md +103 -0
  112. package/.claude/skills/workflow/flow-spec/SKILL.md +545 -0
  113. package/.claude/skills/workflow/flow-spec/context.jsonl +7 -0
  114. package/.claude/skills/workflow/flow-spec/scripts/entry-gate.sh +194 -0
  115. package/.claude/skills/workflow/flow-spec/scripts/exit-gate.sh +244 -0
  116. package/.claude/skills/workflow/flow-spec/scripts/parallel-orchestrator.sh +205 -0
  117. package/.claude/skills/workflow/flow-spec/scripts/team-communication.sh +353 -0
  118. package/.claude/skills/workflow/flow-spec/scripts/team-init.sh +195 -0
  119. package/.claude/skills/workflow/flow-spec/scripts/test-team-mode.sh +496 -0
  120. package/.claude/skills/workflow/flow-spec/team-config.json +165 -0
  121. package/.claude/skills/workflow.yaml +417 -0
  122. package/CHANGELOG.md +254 -0
  123. package/README.md +193 -33
  124. package/README.zh-CN.md +206 -46
  125. package/lib/compiler/CLAUDE.md +77 -46
  126. package/lib/compiler/__tests__/multi-module-emitters.test.js +508 -0
  127. package/lib/compiler/context-expander.js +179 -0
  128. package/lib/compiler/emitters/antigravity-emitter.js +195 -5
  129. package/lib/compiler/emitters/base-emitter.js +217 -2
  130. package/lib/compiler/emitters/codex-emitter.js +200 -4
  131. package/lib/compiler/emitters/cursor-emitter.js +307 -3
  132. package/lib/compiler/emitters/qwen-emitter.js +196 -4
  133. package/lib/compiler/index.js +197 -2
  134. package/lib/compiler/platforms.js +270 -21
  135. package/package.json +1 -1
  136. package/.claude/commands/flow-epic.md +0 -183
  137. package/.claude/commands/flow-init.md +0 -370
  138. package/.claude/commands/flow-prd.md +0 -144
  139. package/.claude/commands/flow-qa.md +0 -93
  140. package/.claude/commands/flow-review.md +0 -257
  141. package/.claude/commands/flow-tech.md +0 -142
  142. package/.claude/commands/flow-ui.md +0 -189
  143. package/.claude/skills/file-header-guardian/SKILL.md +0 -56
  144. package/.claude/skills/skill-developer/ADVANCED.md +0 -197
  145. package/.claude/skills/skill-developer/HOOK_MECHANISMS.md +0 -306
  146. package/.claude/skills/skill-developer/PATTERNS_LIBRARY.md +0 -152
  147. package/.claude/skills/skill-developer/SKILL.md +0 -426
  148. package/.claude/skills/skill-developer/SKILL_RULES_REFERENCE.md +0 -315
  149. package/.claude/skills/skill-developer/TRIGGER_TYPES.md +0 -305
  150. package/.claude/skills/skill-developer/TROUBLESHOOTING.md +0 -514
  151. package/.claude/skills/writing-skills/SKILL.md +0 -655
  152. package/.claude/skills/writing-skills/anthropic-best-practices.md +0 -1150
  153. package/.claude/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +0 -189
  154. package/.claude/skills/writing-skills/graphviz-conventions.dot +0 -172
  155. package/.claude/skills/writing-skills/persuasion-principles.md +0 -187
  156. package/.claude/skills/writing-skills/render-graphs.js +0 -168
  157. package/.claude/skills/writing-skills/testing-skills-with-subagents.md +0 -384
  158. package/.claude/tsc-cache/795ba6e3-b98a-423b-bab2-51aa62812569/affected-repos.txt +0 -1
  159. package/.claude/tsc-cache/ae335694-be5a-4ba4-a1a0-b676c09a7906/affected-repos.txt +0 -1
  160. /package/.claude/commands/{core-architecture.md → core/architecture.md} +0 -0
  161. /package/.claude/commands/{core-guidelines.md → core/guidelines.md} +0 -0
  162. /package/.claude/commands/{core-roadmap.md → core/roadmap.md} +0 -0
  163. /package/.claude/commands/{core-style.md → core/style.md} +0 -0
  164. /package/.claude/commands/{flow-checklist.md → flow/checklist.md} +0 -0
  165. /package/.claude/commands/{flow-clarify.md → flow/clarify.md} +0 -0
  166. /package/.claude/commands/{flow-constitution.md → flow/constitution.md} +0 -0
  167. /package/.claude/commands/{flow-fix.md → flow/fix.md} +0 -0
  168. /package/.claude/commands/{flow-ideate.md → flow/ideate.md} +0 -0
  169. /package/.claude/commands/{flow-new.md → flow/new.md} +0 -0
  170. /package/.claude/commands/{flow-release.md → flow/release.md} +0 -0
  171. /package/.claude/commands/{flow-restart.md → flow/restart.md} +0 -0
  172. /package/.claude/commands/{flow-status.md → flow/status.md} +0 -0
  173. /package/.claude/commands/{flow-update.md → flow/update.md} +0 -0
  174. /package/.claude/commands/{flow-upgrade.md → flow/upgrade.md} +0 -0
  175. /package/.claude/commands/{flow-verify.md → flow/verify.md} +0 -0
  176. /package/.claude/commands/{code-review-high.md → util/code-review.md} +0 -0
  177. /package/.claude/commands/{git-commit.md → util/git-commit.md} +0 -0
  178. /package/.claude/commands/{problem-analyzer.md → util/problem-analyzer.md} +0 -0
  179. /package/.claude/skills/{flow-attention-refresh → domain/attention-refresh}/SKILL.md +0 -0
  180. /package/.claude/skills/{flow-brainstorming → domain/brainstorming}/SKILL.md +0 -0
  181. /package/.claude/skills/{flow-debugging → domain/debugging}/SKILL.md +0 -0
  182. /package/.claude/skills/{flow-finishing-branch → domain/finishing-branch}/SKILL.md +0 -0
  183. /package/.claude/skills/{flow-receiving-review → domain/receiving-review}/SKILL.md +0 -0
  184. /package/.claude/skills/{flow-tdd → domain/tdd}/SKILL.md +0 -0
  185. /package/.claude/skills/{verification-before-completion → domain/verification}/SKILL.md +0 -0
  186. /package/.claude/skills/{constitution-guardian → guardrail/constitution-guardian}/SKILL.md +0 -0
  187. /package/.claude/skills/{devflow-tdd-enforcer → guardrail/tdd-enforcer}/SKILL.md +0 -0
  188. /package/.claude/skills/{devflow-constitution-quick-ref → utility/constitution-quick-ref}/SKILL.md +0 -0
  189. /package/.claude/skills/{devflow-file-standards → utility/file-standards}/SKILL.md +0 -0
  190. /package/.claude/skills/{fractal-docs-generator → utility/fractal-docs}/SKILL.md +0 -0
  191. /package/.claude/skills/{npm-release → utility/npm-release}/SKILL.md +0 -0
@@ -1,12 +1,25 @@
1
1
  /**
2
- * T034: QwenEmitter - Qwen 平台输出
2
+ * T034: QwenEmitter - Qwen 平台输出 (v2.0)
3
3
  *
4
- * 输出格式: TOML
5
- * 目录: .qwen/commands/
6
- * 字段: description, prompt
4
+ * [INPUT]: CommandIR, SKILL.md, agents, rules
5
+ * [OUTPUT]: .qwen/commands/*.toml, .qwen/agents/*.md, CONTEXT.md
6
+ * [POS]: Qwen Code 平台编译器,支持完整功能模块
7
+ * [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
8
+ *
9
+ * 输出格式:
10
+ * - Commands: TOML -> .qwen/commands/
11
+ * - Skills: TOML -> .qwen/commands/
12
+ * - Agents: Markdown (YAML frontmatter) -> .qwen/agents/
13
+ * - Rules: 合并到 CONTEXT.md
14
+ *
15
+ * v2.0: 支持多模块编译
7
16
  */
17
+ const fs = require('fs');
18
+ const path = require('path');
8
19
  const toml = require('@iarna/toml');
20
+ const matter = require('gray-matter');
9
21
  const BaseEmitter = require('./base-emitter.js');
22
+ const { ContextExpander } = require('../context-expander.js');
10
23
 
11
24
  class QwenEmitter extends BaseEmitter {
12
25
  get name() {
@@ -34,6 +47,185 @@ class QwenEmitter extends BaseEmitter {
34
47
 
35
48
  return toml.stringify(tomlObj);
36
49
  }
50
+
51
+ // ----------------------------------------------------------
52
+ // Multi-Module Emit Methods (v2.0)
53
+ // ----------------------------------------------------------
54
+
55
+ /**
56
+ * 编译 Skills 模块
57
+ * .claude/skills/[name]/SKILL.md -> .qwen/commands/[name].toml
58
+ */
59
+ async emitSkills(sourceDir, targetDir) {
60
+ const results = [];
61
+
62
+ if (!fs.existsSync(sourceDir)) {
63
+ return results;
64
+ }
65
+
66
+ // 扫描技能分组目录
67
+ const groupDirs = await fs.promises.readdir(sourceDir, { withFileTypes: true });
68
+
69
+ for (const groupEntry of groupDirs) {
70
+ if (!groupEntry.isDirectory() || groupEntry.name.startsWith('_')) {
71
+ continue;
72
+ }
73
+
74
+ const groupDir = path.join(sourceDir, groupEntry.name);
75
+ const skillEntries = await fs.promises.readdir(groupDir, { withFileTypes: true });
76
+
77
+ for (const skillEntry of skillEntries) {
78
+ if (!skillEntry.isDirectory() || skillEntry.name.startsWith('_')) {
79
+ continue;
80
+ }
81
+
82
+ const skillDir = path.join(groupDir, skillEntry.name);
83
+ const skillMdPath = path.join(skillDir, 'SKILL.md');
84
+
85
+ if (!fs.existsSync(skillMdPath)) {
86
+ continue;
87
+ }
88
+
89
+ try {
90
+ const result = await this._emitSkillAsToml(
91
+ skillEntry.name,
92
+ skillDir,
93
+ skillMdPath,
94
+ targetDir
95
+ );
96
+ results.push(result);
97
+ } catch (error) {
98
+ console.warn(`Warning: Failed to emit skill ${skillEntry.name}: ${error.message}`);
99
+ }
100
+ }
101
+ }
102
+
103
+ return results;
104
+ }
105
+
106
+ /**
107
+ * 将 Skill 转换为 Qwen TOML 命令
108
+ */
109
+ async _emitSkillAsToml(skillName, skillDir, skillMdPath, targetDir) {
110
+ let content = await fs.promises.readFile(skillMdPath, 'utf8');
111
+ const parsed = matter(content);
112
+
113
+ // 展开 context.jsonl
114
+ const contextExpanded = ContextExpander.expandFromSkillDir(skillDir, 'qwen');
115
+
116
+ // 构建 TOML 对象
117
+ let prompt = parsed.content;
118
+ if (contextExpanded) {
119
+ prompt = contextExpanded + '\n' + prompt;
120
+ }
121
+
122
+ // 替换变量占位符为 Qwen 格式
123
+ prompt = prompt.replace(/\$ARGUMENTS/g, '{{args}}');
124
+
125
+ const tomlObj = {
126
+ description: parsed.data.description || `${skillName} skill`,
127
+ prompt: prompt
128
+ };
129
+
130
+ const tomlContent = toml.stringify(tomlObj);
131
+
132
+ // 输出到 .qwen/commands/<skill-name>.toml
133
+ const targetPath = path.join(targetDir, `${skillName}.toml`);
134
+ const result = await this.emitToPath(targetPath, tomlContent);
135
+
136
+ return { ...result, skillName };
137
+ }
138
+
139
+ /**
140
+ * 编译 Agents 模块
141
+ * .claude/agents/[name].md -> .qwen/agents/[name].md
142
+ */
143
+ async emitAgents(sourceDir, targetDir) {
144
+ const results = [];
145
+
146
+ if (!fs.existsSync(sourceDir)) {
147
+ return results;
148
+ }
149
+
150
+ const entries = await fs.promises.readdir(sourceDir, { withFileTypes: true });
151
+
152
+ for (const entry of entries) {
153
+ if (!entry.isFile() || !entry.name.endsWith('.md')) {
154
+ continue;
155
+ }
156
+
157
+ const filePath = path.join(sourceDir, entry.name);
158
+ const content = await fs.promises.readFile(filePath, 'utf8');
159
+ const parsed = matter(content);
160
+ const agentName = entry.name.replace('.md', '');
161
+
162
+ // Qwen agents 支持 ${variable} 模板
163
+ let body = parsed.content;
164
+ // 转换 $ARGUMENTS 为 ${args}
165
+ body = body.replace(/\$ARGUMENTS/g, '${args}');
166
+
167
+ // 重新构建带 frontmatter 的内容
168
+ const frontmatterData = {
169
+ name: parsed.data.name || agentName,
170
+ description: parsed.data.description || `${agentName} agent`
171
+ };
172
+
173
+ if (parsed.data.tools) {
174
+ frontmatterData.tools = parsed.data.tools;
175
+ }
176
+
177
+ const yaml = require('js-yaml');
178
+ const yamlStr = yaml.dump(frontmatterData, {
179
+ lineWidth: -1,
180
+ quotingType: '"',
181
+ forceQuotes: false
182
+ });
183
+
184
+ const finalContent = `---\n${yamlStr}---\n\n${body}`;
185
+
186
+ const targetPath = path.join(targetDir, `${agentName}.md`);
187
+ const result = await this.emitToPath(targetPath, finalContent);
188
+ results.push({ ...result, agentName });
189
+ }
190
+
191
+ return results;
192
+ }
193
+
194
+ /**
195
+ * 编译 Rules 模块
196
+ * .claude/rules/[name].md -> CONTEXT.md (合并)
197
+ */
198
+ async emitRules(sourceDir, targetPath) {
199
+ const results = [];
200
+
201
+ if (!fs.existsSync(sourceDir)) {
202
+ return results;
203
+ }
204
+
205
+ const entries = await fs.promises.readdir(sourceDir, { withFileTypes: true });
206
+ const sections = [];
207
+
208
+ for (const entry of entries) {
209
+ if (!entry.isFile() || !entry.name.endsWith('.md')) {
210
+ continue;
211
+ }
212
+
213
+ const filePath = path.join(sourceDir, entry.name);
214
+ const content = await fs.promises.readFile(filePath, 'utf8');
215
+ const parsed = matter(content);
216
+ const ruleName = entry.name.replace('.md', '');
217
+
218
+ sections.push(`## ${ruleName}\n\n${parsed.content}`);
219
+ }
220
+
221
+ if (sections.length > 0) {
222
+ const merged = `# Project Context\n\n${sections.join('\n\n---\n\n')}`;
223
+ const result = await this.emitToPath(targetPath, merged);
224
+ results.push(result);
225
+ }
226
+
227
+ return results;
228
+ }
37
229
  }
38
230
 
39
231
  module.exports = QwenEmitter;
@@ -1,15 +1,23 @@
1
1
  /**
2
- * Compiler Entry Point (v2.0)
2
+ * Compiler Entry Point (v3.0)
3
+ *
4
+ * [INPUT]: .claude/commands/, .claude/skills/, .claude/agents/, .claude/rules/, .claude/hooks/
5
+ * [OUTPUT]: 各平台目录 (.codex/, .cursor/, .qwen/, .agent/)
6
+ * [POS]: 编译器主入口,协调多模块编译流程
7
+ * [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
3
8
  *
4
9
  * 编译器主入口:
5
10
  * - compile(options): 编译命令文件到目标平台
11
+ * - compileMultiModule(options): 编译所有模块到目标平台 (v3.0)
6
12
  * - 协调 parser, transformer, emitters, manifest
7
13
  * - 复制资源文件并重写路径
8
14
  * - 生成 skills-registry.json 和规则入口文件
9
15
  *
10
16
  * v2.0 (REQ-006): 支持 --rules, --skills 参数
17
+ * v3.0: 支持多模块编译 (skills, commands, agents, rules, hooks)
11
18
  */
12
19
  const path = require('path');
20
+ const fs = require('fs');
13
21
 
14
22
  const { parseAllCommands } = require('./parser.js');
15
23
  const { transformForPlatform } = require('./transformer.js');
@@ -36,6 +44,191 @@ const {
36
44
  } = require('./resource-copier.js');
37
45
  const { generateSkillsRegistryV2, writeSkillsRegistry } = require('./skills-registry.js');
38
46
  const { getRulesEmitter, emitAllRules } = require('./rules-emitters/index.js');
47
+ const { getPlatformConfig, MODULE_TYPES, isModuleSupported } = require('./platforms.js');
48
+
49
+ // ============================================================
50
+ // DEFAULT_MODULES - 默认编译的模块
51
+ // ============================================================
52
+ const DEFAULT_MODULES = ['skills', 'commands', 'agents', 'rules'];
53
+
54
+ // ============================================================
55
+ // compileMultiModule - 多模块编译主函数 (v3.0)
56
+ // ============================================================
57
+ async function compileMultiModule(options = {}) {
58
+ const {
59
+ sourceBaseDir = '.claude/',
60
+ outputBaseDir = '.',
61
+ platforms = PLATFORMS,
62
+ modules = DEFAULT_MODULES,
63
+ verbose = false,
64
+ check = false
65
+ } = options;
66
+
67
+ // 验证平台参数
68
+ for (const platform of platforms) {
69
+ if (!PLATFORMS.includes(platform)) {
70
+ throw new Error(`Unknown platform: ${platform}`);
71
+ }
72
+ }
73
+
74
+ const result = {
75
+ success: true,
76
+ platforms: platforms,
77
+ modules: modules,
78
+ skillsEmitted: 0,
79
+ commandsEmitted: 0,
80
+ agentsEmitted: 0,
81
+ rulesEmitted: 0,
82
+ hooksEmitted: 0,
83
+ errors: []
84
+ };
85
+
86
+ // 加载 manifest
87
+ const manifestPath = path.join(outputBaseDir, MANIFEST_PATH);
88
+ let manifest = await loadManifest(manifestPath);
89
+ manifest = migrateToV2(manifest);
90
+
91
+ // 如果是 check 模式,只做漂移检测
92
+ if (check) {
93
+ const { checkDrift } = require('./manifest.js');
94
+ const drift = await checkDrift(manifest);
95
+ return {
96
+ ...result,
97
+ check: true,
98
+ drift,
99
+ success: drift.length === 0
100
+ };
101
+ }
102
+
103
+ // 为每个平台编译每个模块
104
+ for (const platform of platforms) {
105
+ const emitter = getEmitter(platform);
106
+ const platformConfig = getPlatformConfig(platform);
107
+
108
+ if (verbose) {
109
+ console.log(`\nCompiling for ${platformConfig.name}...`);
110
+ }
111
+
112
+ // 编译 Skills
113
+ if (modules.includes('skills')) {
114
+ try {
115
+ const skillsSourceDir = path.join(sourceBaseDir, 'skills');
116
+ const skillsTargetDir = getSkillsTargetDir(platform, platformConfig);
117
+
118
+ if (fs.existsSync(skillsSourceDir)) {
119
+ const skillResults = await emitter.emitSkills(skillsSourceDir, skillsTargetDir);
120
+ result.skillsEmitted += skillResults.length;
121
+
122
+ if (verbose && skillResults.length > 0) {
123
+ console.log(` Skills: ${skillResults.length} emitted to ${skillsTargetDir}`);
124
+ }
125
+ }
126
+ } catch (error) {
127
+ result.errors.push(`${platform}/skills: ${error.message}`);
128
+ }
129
+ }
130
+
131
+ // 编译 Agents
132
+ if (modules.includes('agents')) {
133
+ try {
134
+ const agentsSourceDir = path.join(sourceBaseDir, 'agents');
135
+ const agentsTargetPath = getAgentsTargetPath(platform, platformConfig);
136
+
137
+ if (fs.existsSync(agentsSourceDir)) {
138
+ const agentResults = await emitter.emitAgents(agentsSourceDir, agentsTargetPath);
139
+ result.agentsEmitted += agentResults.length;
140
+
141
+ if (verbose && agentResults.length > 0) {
142
+ console.log(` Agents: ${agentResults.length} emitted to ${agentsTargetPath}`);
143
+ }
144
+ }
145
+ } catch (error) {
146
+ result.errors.push(`${platform}/agents: ${error.message}`);
147
+ }
148
+ }
149
+
150
+ // 编译 Rules
151
+ if (modules.includes('rules')) {
152
+ try {
153
+ const rulesSourceDir = path.join(sourceBaseDir, 'rules');
154
+ const rulesTargetPath = getRulesTargetPath(platform, platformConfig);
155
+
156
+ if (fs.existsSync(rulesSourceDir)) {
157
+ const ruleResults = await emitter.emitRules(rulesSourceDir, rulesTargetPath);
158
+ result.rulesEmitted += ruleResults.length;
159
+
160
+ if (verbose && ruleResults.length > 0) {
161
+ console.log(` Rules: ${ruleResults.length} emitted to ${rulesTargetPath}`);
162
+ }
163
+ }
164
+ } catch (error) {
165
+ result.errors.push(`${platform}/rules: ${error.message}`);
166
+ }
167
+ }
168
+
169
+ // 编译 Hooks (仅 Cursor 支持)
170
+ if (modules.includes('hooks') && isModuleSupported(platform, 'hooks')) {
171
+ try {
172
+ const hooksSourceDir = path.join(sourceBaseDir, 'hooks');
173
+ const hooksTargetDir = platformConfig.folder;
174
+
175
+ if (fs.existsSync(hooksSourceDir)) {
176
+ const hookResults = await emitter.emitHooks(hooksSourceDir, hooksTargetDir);
177
+ result.hooksEmitted += hookResults.length;
178
+
179
+ if (verbose && hookResults.length > 0) {
180
+ console.log(` Hooks: ${hookResults.length} emitted to ${hooksTargetDir}`);
181
+ }
182
+ }
183
+ } catch (error) {
184
+ result.errors.push(`${platform}/hooks: ${error.message}`);
185
+ }
186
+ }
187
+ }
188
+
189
+ // 保存 manifest
190
+ manifest.generatedAt = new Date().toISOString();
191
+ await saveManifest(manifest, manifestPath);
192
+
193
+ // 设置成功状态
194
+ result.success = result.errors.length === 0;
195
+
196
+ return result;
197
+ }
198
+
199
+ // ============================================================
200
+ // Helper Functions - 获取目标路径
201
+ // ============================================================
202
+
203
+ function getSkillsTargetDir(platform, config) {
204
+ const skillsConfig = config.skills;
205
+ if (!skillsConfig) {
206
+ return path.join(config.folder, 'skills');
207
+ }
208
+ return path.join(config.folder, skillsConfig.dir || 'skills');
209
+ }
210
+
211
+ function getAgentsTargetPath(platform, config) {
212
+ const agentsConfig = config.agents;
213
+ if (!agentsConfig) {
214
+ return 'AGENTS.md';
215
+ }
216
+ if (agentsConfig.outputFile) {
217
+ return agentsConfig.outputFile;
218
+ }
219
+ return path.join(config.folder, agentsConfig.dir || 'agents');
220
+ }
221
+
222
+ function getRulesTargetPath(platform, config) {
223
+ const rulesConfig = config.rules;
224
+ if (!rulesConfig) {
225
+ return path.join(config.folder, 'rules');
226
+ }
227
+ if (rulesConfig.outputFile) {
228
+ return rulesConfig.outputFile;
229
+ }
230
+ return path.join(config.folder, rulesConfig.dir || 'rules');
231
+ }
39
232
 
40
233
  // ============================================================
41
234
  // compile - 编译主函数
@@ -252,5 +445,7 @@ async function compile(options = {}) {
252
445
 
253
446
  module.exports = {
254
447
  compile,
255
- PLATFORMS
448
+ compileMultiModule,
449
+ PLATFORMS,
450
+ DEFAULT_MODULES
256
451
  };