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
@@ -0,0 +1,359 @@
1
+ #!/usr/bin/env npx ts-node
2
+ /**
3
+ * [INPUT]: 依赖 workflow.yaml 的 Skill 定义,依赖各 Skill 的 context.jsonl
4
+ * [OUTPUT]: 对外提供 PreToolUse 钩子,自动注入 Skill 上下文
5
+ * [POS]: hooks/ 的核心上下文注入器,被所有 Skill 调用时触发
6
+ * [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
7
+ *
8
+ * =============================================================================
9
+ * CC-DevFlow Skill Context Injection Hook (借鉴 Trellis)
10
+ * =============================================================================
11
+ *
12
+ * 核心设计哲学:
13
+ * - Skill 调用时自动注入所需上下文
14
+ * - 通过 context.jsonl 定义每个 Skill 的上下文需求
15
+ * - 支持变量替换 ({REQ} → 实际 REQ-ID)
16
+ * - 可选文件缺失时不报错
17
+ *
18
+ * 触发条件:PreToolUse (Skill tool 调用前)
19
+ */
20
+
21
+ import * as fs from 'fs';
22
+ import * as path from 'path';
23
+
24
+ // =============================================================================
25
+ // 类型定义
26
+ // =============================================================================
27
+
28
+ interface ContextEntry {
29
+ file: string;
30
+ reason?: string;
31
+ optional?: boolean;
32
+ type?: 'file' | 'directory';
33
+ }
34
+
35
+ interface HookInput {
36
+ tool_name: string;
37
+ tool_input: {
38
+ skill?: string;
39
+ prompt?: string;
40
+ [key: string]: unknown;
41
+ };
42
+ cwd: string;
43
+ }
44
+
45
+ interface HookOutput {
46
+ hookSpecificOutput: {
47
+ hookEventName: string;
48
+ permissionDecision: string;
49
+ updatedInput?: Record<string, unknown>;
50
+ };
51
+ }
52
+
53
+ // =============================================================================
54
+ // 路径常量
55
+ // =============================================================================
56
+
57
+ const DIR_SKILLS = '.claude/skills';
58
+ const DIR_WORKFLOW = 'workflow';
59
+ const DIR_DOMAIN = 'domain';
60
+ const DIR_GUARDRAIL = 'guardrail';
61
+ const DIR_UTILITY = 'utility';
62
+ const FILE_CONTEXT = 'context.jsonl';
63
+ const DIR_REQUIREMENTS = 'devflow/requirements';
64
+
65
+ // =============================================================================
66
+ // 工具函数
67
+ // =============================================================================
68
+
69
+ /**
70
+ * 查找 Git 仓库根目录
71
+ */
72
+ function findRepoRoot(startPath: string): string | null {
73
+ let current = path.resolve(startPath);
74
+ while (current !== path.dirname(current)) {
75
+ if (fs.existsSync(path.join(current, '.git'))) {
76
+ return current;
77
+ }
78
+ current = path.dirname(current);
79
+ }
80
+ return null;
81
+ }
82
+
83
+ /**
84
+ * 从 orchestration_status.json 获取当前 REQ-ID
85
+ */
86
+ function getCurrentReqId(repoRoot: string): string | null {
87
+ // 方法1: 从最近修改的 requirements 目录推断
88
+ const reqDir = path.join(repoRoot, DIR_REQUIREMENTS);
89
+ if (!fs.existsSync(reqDir)) return null;
90
+
91
+ try {
92
+ const dirs = fs.readdirSync(reqDir)
93
+ .filter(d => d.startsWith('REQ-'))
94
+ .map(d => ({
95
+ name: d,
96
+ mtime: fs.statSync(path.join(reqDir, d)).mtime.getTime()
97
+ }))
98
+ .sort((a, b) => b.mtime - a.mtime);
99
+
100
+ return dirs.length > 0 ? dirs[0].name : null;
101
+ } catch {
102
+ return null;
103
+ }
104
+ }
105
+
106
+ /**
107
+ * 替换路径中的变量
108
+ */
109
+ function replaceVariables(filePath: string, reqId: string | null): string {
110
+ if (!reqId) return filePath;
111
+ return filePath.replace(/{REQ}/g, reqId);
112
+ }
113
+
114
+ /**
115
+ * 读取文件内容
116
+ */
117
+ function readFileContent(basePath: string, filePath: string): string | null {
118
+ const fullPath = path.join(basePath, filePath);
119
+ if (!fs.existsSync(fullPath) || !fs.statSync(fullPath).isFile()) {
120
+ return null;
121
+ }
122
+ try {
123
+ return fs.readFileSync(fullPath, 'utf-8');
124
+ } catch {
125
+ return null;
126
+ }
127
+ }
128
+
129
+ /**
130
+ * 读取目录中的所有 .md 文件
131
+ */
132
+ function readDirectoryContents(
133
+ basePath: string,
134
+ dirPath: string,
135
+ maxFiles = 20
136
+ ): Array<[string, string]> {
137
+ const fullPath = path.join(basePath, dirPath);
138
+ if (!fs.existsSync(fullPath) || !fs.statSync(fullPath).isDirectory()) {
139
+ return [];
140
+ }
141
+
142
+ const results: Array<[string, string]> = [];
143
+ try {
144
+ const mdFiles = fs.readdirSync(fullPath)
145
+ .filter(f => f.endsWith('.md'))
146
+ .sort()
147
+ .slice(0, maxFiles);
148
+
149
+ for (const filename of mdFiles) {
150
+ const fileFull = path.join(fullPath, filename);
151
+ const relativePath = path.join(dirPath, filename);
152
+ try {
153
+ const content = fs.readFileSync(fileFull, 'utf-8');
154
+ results.push([relativePath, content]);
155
+ } catch {
156
+ continue;
157
+ }
158
+ }
159
+ } catch {
160
+ // ignore
161
+ }
162
+ return results;
163
+ }
164
+
165
+ /**
166
+ * 解析 JSONL 文件并读取引用的文件内容
167
+ */
168
+ function readJsonlEntries(
169
+ basePath: string,
170
+ jsonlPath: string,
171
+ reqId: string | null
172
+ ): Array<[string, string]> {
173
+ const fullPath = path.join(basePath, jsonlPath);
174
+ if (!fs.existsSync(fullPath)) {
175
+ return [];
176
+ }
177
+
178
+ const results: Array<[string, string]> = [];
179
+ try {
180
+ const lines = fs.readFileSync(fullPath, 'utf-8').split('\n');
181
+ for (const line of lines) {
182
+ const trimmed = line.trim();
183
+ if (!trimmed) continue;
184
+
185
+ try {
186
+ const entry: ContextEntry = JSON.parse(trimmed);
187
+ const filePath = replaceVariables(entry.file, reqId);
188
+ const entryType = entry.type || 'file';
189
+
190
+ if (entryType === 'directory') {
191
+ const dirContents = readDirectoryContents(basePath, filePath);
192
+ results.push(...dirContents);
193
+ } else {
194
+ const content = readFileContent(basePath, filePath);
195
+ if (content) {
196
+ results.push([filePath, content]);
197
+ } else if (!entry.optional) {
198
+ // 非可选文件缺失,记录警告但继续
199
+ console.error(`[inject-skill-context] Warning: Required file not found: ${filePath}`);
200
+ }
201
+ }
202
+ } catch {
203
+ continue;
204
+ }
205
+ }
206
+ } catch {
207
+ // ignore
208
+ }
209
+ return results;
210
+ }
211
+
212
+ /**
213
+ * 查找 Skill 目录
214
+ */
215
+ function findSkillPath(repoRoot: string, skillName: string): string | null {
216
+ // 搜索顺序: workflow → domain → guardrail → utility → 根目录
217
+ const searchDirs = [DIR_WORKFLOW, DIR_DOMAIN, DIR_GUARDRAIL, DIR_UTILITY, ''];
218
+
219
+ for (const subDir of searchDirs) {
220
+ const skillPath = path.join(repoRoot, DIR_SKILLS, subDir, skillName);
221
+ if (fs.existsSync(skillPath) && fs.existsSync(path.join(skillPath, 'SKILL.md'))) {
222
+ return skillPath;
223
+ }
224
+ }
225
+
226
+ // 兼容旧结构:直接在 skills/ 下
227
+ const legacyPath = path.join(repoRoot, DIR_SKILLS, skillName);
228
+ if (fs.existsSync(legacyPath) && fs.existsSync(path.join(legacyPath, 'SKILL.md'))) {
229
+ return legacyPath;
230
+ }
231
+
232
+ return null;
233
+ }
234
+
235
+ /**
236
+ * 获取 Skill 的上下文
237
+ */
238
+ function getSkillContext(
239
+ repoRoot: string,
240
+ skillPath: string,
241
+ reqId: string | null
242
+ ): string {
243
+ const contextParts: string[] = [];
244
+
245
+ // 1. 读取 Skill 的 context.jsonl
246
+ const contextJsonl = path.join(skillPath, FILE_CONTEXT);
247
+ const relativeContextPath = path.relative(repoRoot, contextJsonl);
248
+
249
+ if (fs.existsSync(contextJsonl)) {
250
+ const entries = readJsonlEntries(repoRoot, relativeContextPath, reqId);
251
+ for (const [filePath, content] of entries) {
252
+ contextParts.push(`=== ${filePath} ===\n${content}`);
253
+ }
254
+ }
255
+
256
+ return contextParts.join('\n\n');
257
+ }
258
+
259
+ /**
260
+ * 构建增强后的 prompt
261
+ */
262
+ function buildEnhancedPrompt(
263
+ originalPrompt: string,
264
+ context: string,
265
+ skillName: string
266
+ ): string {
267
+ if (!context) {
268
+ return originalPrompt;
269
+ }
270
+
271
+ return `# Skill Context Injection
272
+
273
+ The following context has been automatically injected for skill: ${skillName}
274
+
275
+ ---
276
+
277
+ ${context}
278
+
279
+ ---
280
+
281
+ ## Original Task
282
+
283
+ ${originalPrompt}`;
284
+ }
285
+
286
+ // =============================================================================
287
+ // 主函数
288
+ // =============================================================================
289
+
290
+ function main(): void {
291
+ let inputData: HookInput;
292
+
293
+ try {
294
+ const stdin = fs.readFileSync(0, 'utf-8');
295
+ inputData = JSON.parse(stdin);
296
+ } catch {
297
+ process.exit(0);
298
+ }
299
+
300
+ const toolName = inputData.tool_name || '';
301
+
302
+ // 只处理 Skill tool 调用
303
+ if (toolName !== 'Skill') {
304
+ process.exit(0);
305
+ }
306
+
307
+ const toolInput = inputData.tool_input || {};
308
+ const skillName = toolInput.skill as string;
309
+ const originalPrompt = (toolInput.prompt as string) || '';
310
+ const cwd = inputData.cwd || process.cwd();
311
+
312
+ if (!skillName) {
313
+ process.exit(0);
314
+ }
315
+
316
+ // 查找仓库根目录
317
+ const repoRoot = findRepoRoot(cwd);
318
+ if (!repoRoot) {
319
+ process.exit(0);
320
+ }
321
+
322
+ // 查找 Skill 路径
323
+ const skillPath = findSkillPath(repoRoot, skillName);
324
+ if (!skillPath) {
325
+ // Skill 不存在或没有 context.jsonl,不注入
326
+ process.exit(0);
327
+ }
328
+
329
+ // 获取当前 REQ-ID
330
+ const reqId = getCurrentReqId(repoRoot);
331
+
332
+ // 获取上下文
333
+ const context = getSkillContext(repoRoot, skillPath, reqId);
334
+
335
+ if (!context) {
336
+ // 没有上下文需要注入
337
+ process.exit(0);
338
+ }
339
+
340
+ // 构建增强后的 prompt
341
+ const enhancedPrompt = buildEnhancedPrompt(originalPrompt, context, skillName);
342
+
343
+ // 返回更新后的输入
344
+ const output: HookOutput = {
345
+ hookSpecificOutput: {
346
+ hookEventName: 'PreToolUse',
347
+ permissionDecision: 'allow',
348
+ updatedInput: {
349
+ ...toolInput,
350
+ prompt: enhancedPrompt
351
+ }
352
+ }
353
+ };
354
+
355
+ console.log(JSON.stringify(output, null, 0));
356
+ process.exit(0);
357
+ }
358
+
359
+ main();