claude-code-workflow 6.3.26 → 6.3.28

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 (129) hide show
  1. package/.claude/CLAUDE.md +7 -1
  2. package/.claude/agents/action-planning-agent.md +1 -0
  3. package/.claude/agents/cli-discuss-agent.md +391 -0
  4. package/.claude/agents/cli-execution-agent.md +2 -0
  5. package/.claude/agents/cli-explore-agent.md +2 -1
  6. package/.claude/agents/cli-lite-planning-agent.md +1 -0
  7. package/.claude/agents/cli-planning-agent.md +1 -0
  8. package/.claude/agents/code-developer.md +1 -0
  9. package/.claude/agents/conceptual-planning-agent.md +2 -0
  10. package/.claude/agents/context-search-agent.md +1 -0
  11. package/.claude/agents/debug-explore-agent.md +2 -0
  12. package/.claude/agents/doc-generator.md +1 -0
  13. package/.claude/agents/issue-plan-agent.md +2 -1
  14. package/.claude/agents/issue-queue-agent.md +2 -1
  15. package/.claude/agents/memory-bridge.md +2 -0
  16. package/.claude/agents/test-context-search-agent.md +2 -0
  17. package/.claude/agents/test-fix-agent.md +1 -0
  18. package/.claude/agents/ui-design-agent.md +2 -0
  19. package/.claude/agents/universal-executor.md +1 -0
  20. package/.claude/commands/issue/execute.md +141 -163
  21. package/.claude/commands/workflow/lite-lite-lite.md +798 -0
  22. package/.claude/commands/workflow/multi-cli-plan.md +510 -0
  23. package/.claude/skills/ccw/SKILL.md +262 -372
  24. package/.claude/skills/ccw/command.json +547 -0
  25. package/.claude/skills/ccw-help/SKILL.md +46 -107
  26. package/.claude/skills/ccw-help/command.json +511 -0
  27. package/.claude/skills/skill-tuning/SKILL.md +303 -0
  28. package/.claude/skills/skill-tuning/phases/actions/action-abort.md +164 -0
  29. package/.claude/skills/skill-tuning/phases/actions/action-analyze-requirements.md +406 -0
  30. package/.claude/skills/skill-tuning/phases/actions/action-apply-fix.md +206 -0
  31. package/.claude/skills/skill-tuning/phases/actions/action-complete.md +195 -0
  32. package/.claude/skills/skill-tuning/phases/actions/action-diagnose-agent.md +317 -0
  33. package/.claude/skills/skill-tuning/phases/actions/action-diagnose-context.md +243 -0
  34. package/.claude/skills/skill-tuning/phases/actions/action-diagnose-dataflow.md +318 -0
  35. package/.claude/skills/skill-tuning/phases/actions/action-diagnose-docs.md +299 -0
  36. package/.claude/skills/skill-tuning/phases/actions/action-diagnose-memory.md +269 -0
  37. package/.claude/skills/skill-tuning/phases/actions/action-diagnose-token-consumption.md +200 -0
  38. package/.claude/skills/skill-tuning/phases/actions/action-gemini-analysis.md +322 -0
  39. package/.claude/skills/skill-tuning/phases/actions/action-generate-report.md +228 -0
  40. package/.claude/skills/skill-tuning/phases/actions/action-init.md +149 -0
  41. package/.claude/skills/skill-tuning/phases/actions/action-propose-fixes.md +317 -0
  42. package/.claude/skills/skill-tuning/phases/actions/action-verify.md +222 -0
  43. package/.claude/skills/skill-tuning/phases/orchestrator.md +377 -0
  44. package/.claude/skills/skill-tuning/phases/state-schema.md +378 -0
  45. package/.claude/skills/skill-tuning/specs/category-mappings.json +284 -0
  46. package/.claude/skills/skill-tuning/specs/dimension-mapping.md +212 -0
  47. package/.claude/skills/skill-tuning/specs/problem-taxonomy.md +318 -0
  48. package/.claude/skills/skill-tuning/specs/quality-gates.md +263 -0
  49. package/.claude/skills/skill-tuning/specs/skill-authoring-principles.md +189 -0
  50. package/.claude/skills/skill-tuning/specs/tuning-strategies.md +1537 -0
  51. package/.claude/skills/skill-tuning/templates/diagnosis-report.md +153 -0
  52. package/.claude/skills/skill-tuning/templates/fix-proposal.md +204 -0
  53. package/.claude/workflows/cli-templates/schemas/multi-cli-discussion-schema.json +421 -0
  54. package/.claude/workflows/cli-tools-usage.md +0 -41
  55. package/ccw/dist/core/auth/csrf-middleware.d.ts.map +1 -1
  56. package/ccw/dist/core/auth/csrf-middleware.js +3 -1
  57. package/ccw/dist/core/auth/csrf-middleware.js.map +1 -1
  58. package/ccw/dist/core/data-aggregator.d.ts +2 -0
  59. package/ccw/dist/core/data-aggregator.d.ts.map +1 -1
  60. package/ccw/dist/core/data-aggregator.js +5 -2
  61. package/ccw/dist/core/data-aggregator.js.map +1 -1
  62. package/ccw/dist/core/lite-scanner.d.ts +2 -1
  63. package/ccw/dist/core/lite-scanner.d.ts.map +1 -1
  64. package/ccw/dist/core/lite-scanner.js +295 -6
  65. package/ccw/dist/core/lite-scanner.js.map +1 -1
  66. package/ccw/dist/core/routes/codexlens/config-handlers.d.ts.map +1 -1
  67. package/ccw/dist/core/routes/codexlens/config-handlers.js +5 -5
  68. package/ccw/dist/core/routes/codexlens/config-handlers.js.map +1 -1
  69. package/ccw/dist/core/routes/session-routes.d.ts.map +1 -1
  70. package/ccw/dist/core/routes/session-routes.js +166 -48
  71. package/ccw/dist/core/routes/session-routes.js.map +1 -1
  72. package/ccw/dist/core/routes/system-routes.d.ts.map +1 -1
  73. package/ccw/dist/core/routes/system-routes.js +87 -0
  74. package/ccw/dist/core/routes/system-routes.js.map +1 -1
  75. package/ccw/dist/core/server.js +2 -2
  76. package/ccw/dist/core/server.js.map +1 -1
  77. package/ccw/scripts/IMPLEMENTATION-SUMMARY.md +226 -0
  78. package/ccw/scripts/QUICK-REFERENCE.md +135 -0
  79. package/ccw/scripts/README-memory-embedder.md +157 -0
  80. package/ccw/scripts/__pycache__/memory_embedder.cpython-313.pyc +0 -0
  81. package/ccw/scripts/__pycache__/test_memory_embedder.cpython-313-pytest-8.4.2.pyc +0 -0
  82. package/ccw/scripts/memory-embedder-example.ts +184 -0
  83. package/ccw/scripts/memory_embedder.py +428 -0
  84. package/ccw/scripts/test_memory_embedder.py +245 -0
  85. package/ccw/src/core/auth/csrf-middleware.ts +3 -1
  86. package/ccw/src/core/data-aggregator.ts +7 -2
  87. package/ccw/src/core/lite-scanner.ts +440 -6
  88. package/ccw/src/core/routes/codexlens/config-handlers.ts +12 -9
  89. package/ccw/src/core/routes/session-routes.ts +201 -48
  90. package/ccw/src/core/routes/system-routes.ts +102 -0
  91. package/ccw/src/core/server.ts +2 -2
  92. package/ccw/src/templates/dashboard-css/01-base.css +8 -0
  93. package/ccw/src/templates/dashboard-css/02-session.css +81 -0
  94. package/ccw/src/templates/dashboard-css/04-lite-tasks.css +2442 -0
  95. package/ccw/src/templates/dashboard-css/21-cli-toolmgmt.css +157 -0
  96. package/ccw/src/templates/dashboard-css/32-issue-manager.css +23 -0
  97. package/ccw/src/templates/dashboard-js/components/cli-stream-viewer.js +38 -4
  98. package/ccw/src/templates/dashboard-js/components/hook-manager.js +38 -13
  99. package/ccw/src/templates/dashboard-js/components/navigation.js +24 -4
  100. package/ccw/src/templates/dashboard-js/i18n.js +194 -6
  101. package/ccw/src/templates/dashboard-js/views/api-settings.js +32 -0
  102. package/ccw/src/templates/dashboard-js/views/claude-manager.js +44 -3
  103. package/ccw/src/templates/dashboard-js/views/cli-manager.js +303 -31
  104. package/ccw/src/templates/dashboard-js/views/history.js +44 -6
  105. package/ccw/src/templates/dashboard-js/views/home.js +1 -0
  106. package/ccw/src/templates/dashboard-js/views/issue-manager.js +54 -7
  107. package/ccw/src/templates/dashboard-js/views/lite-tasks.js +1817 -4
  108. package/ccw/src/templates/dashboard.html +5 -0
  109. package/package.json +2 -1
  110. package/.claude/skills/ccw/index/command-capabilities.json +0 -127
  111. package/.claude/skills/ccw/index/intent-rules.json +0 -136
  112. package/.claude/skills/ccw/index/workflow-chains.json +0 -451
  113. package/.claude/skills/ccw/phases/actions/bugfix.md +0 -218
  114. package/.claude/skills/ccw/phases/actions/coupled.md +0 -194
  115. package/.claude/skills/ccw/phases/actions/docs.md +0 -93
  116. package/.claude/skills/ccw/phases/actions/full.md +0 -154
  117. package/.claude/skills/ccw/phases/actions/issue.md +0 -201
  118. package/.claude/skills/ccw/phases/actions/rapid.md +0 -104
  119. package/.claude/skills/ccw/phases/actions/review-fix.md +0 -84
  120. package/.claude/skills/ccw/phases/actions/tdd.md +0 -66
  121. package/.claude/skills/ccw/phases/actions/ui.md +0 -79
  122. package/.claude/skills/ccw/phases/orchestrator.md +0 -435
  123. package/.claude/skills/ccw/specs/intent-classification.md +0 -336
  124. package/.claude/skills/ccw-help/index/all-agents.json +0 -82
  125. package/.claude/skills/ccw-help/index/all-commands.json +0 -882
  126. package/.claude/skills/ccw-help/index/by-category.json +0 -914
  127. package/.claude/skills/ccw-help/index/by-use-case.json +0 -896
  128. package/.claude/skills/ccw-help/index/command-relationships.json +0 -160
  129. package/.claude/skills/ccw-help/index/essential-commands.json +0 -112
@@ -0,0 +1,406 @@
1
+ # Action: Analyze Requirements
2
+
3
+ 将用户问题描述拆解为多个分析维度,匹配 Spec,评估覆盖度,检测歧义。
4
+
5
+ ## Purpose
6
+
7
+ - 将单一用户描述拆解为多个独立关注维度
8
+ - 为每个维度匹配 problem-taxonomy(检测)+ tuning-strategies(修复)
9
+ - 以"有修复策略"为标准判断是否满足需求
10
+ - 检测歧义并在必要时请求用户澄清
11
+
12
+ ## Preconditions
13
+
14
+ - [ ] `state.status === 'running'`
15
+ - [ ] `state.target_skill !== null`
16
+ - [ ] `state.completed_actions.includes('action-init')`
17
+ - [ ] `!state.completed_actions.includes('action-analyze-requirements')`
18
+
19
+ ## Execution
20
+
21
+ ### Phase 1: 维度拆解 (Gemini CLI)
22
+
23
+ 调用 Gemini 对用户描述进行语义分析,拆解为独立维度:
24
+
25
+ ```javascript
26
+ async function analyzeDimensions(state, workDir) {
27
+ const prompt = `
28
+ PURPOSE: 分析用户问题描述,拆解为独立的关注维度
29
+ TASK:
30
+ • 识别用户描述中的多个关注点(每个关注点应该是独立的、可单独分析的)
31
+ • 为每个关注点提取关键词(中英文均可)
32
+ • 推断可能的问题类别:
33
+ - context_explosion: 上下文/Token 相关
34
+ - memory_loss: 遗忘/约束丢失相关
35
+ - dataflow_break: 状态/数据流相关
36
+ - agent_failure: Agent/子任务相关
37
+ - prompt_quality: 提示词/输出质量相关
38
+ - architecture: 架构/结构相关
39
+ - performance: 性能/效率相关
40
+ - error_handling: 错误/异常处理相关
41
+ - output_quality: 输出质量/验证相关
42
+ - user_experience: 交互/体验相关
43
+ • 评估推断置信度 (0-1)
44
+
45
+ INPUT:
46
+ User description: ${state.user_issue_description}
47
+ Target skill: ${state.target_skill.name}
48
+ Skill structure: ${JSON.stringify(state.target_skill.phases)}
49
+
50
+ MODE: analysis
51
+ CONTEXT: @specs/problem-taxonomy.md @specs/dimension-mapping.md
52
+ EXPECTED: JSON (不要包含 markdown 代码块标记)
53
+ {
54
+ "dimensions": [
55
+ {
56
+ "id": "DIM-001",
57
+ "description": "关注点的简短描述",
58
+ "keywords": ["关键词1", "关键词2"],
59
+ "inferred_category": "问题类别",
60
+ "confidence": 0.85,
61
+ "reasoning": "推断理由"
62
+ }
63
+ ],
64
+ "analysis_notes": "整体分析说明"
65
+ }
66
+ RULES:
67
+ - 每个维度必须独立,不重叠
68
+ - 低于 0.5 置信度的推断应标注需要澄清
69
+ - 如果用户描述非常模糊,至少提取一个 "general" 维度
70
+ `;
71
+
72
+ const cliCommand = `ccw cli -p "${escapeForShell(prompt)}" --tool gemini --mode analysis --cd "${state.target_skill.path}"`;
73
+
74
+ console.log('Phase 1: 执行 Gemini 维度拆解分析...');
75
+
76
+ const result = Bash({
77
+ command: cliCommand,
78
+ run_in_background: true,
79
+ timeout: 300000
80
+ });
81
+
82
+ return result;
83
+ }
84
+ ```
85
+
86
+ ### Phase 2: Spec 匹配
87
+
88
+ 基于 `specs/category-mappings.json` 配置为每个维度匹配检测模式和修复策略:
89
+
90
+ ```javascript
91
+ // 加载集中式映射配置
92
+ const mappings = JSON.parse(Read('specs/category-mappings.json'));
93
+
94
+ function matchSpecs(dimensions) {
95
+ return dimensions.map(dim => {
96
+ // 匹配 taxonomy pattern
97
+ const taxonomyMatch = findTaxonomyMatch(dim.inferred_category);
98
+
99
+ // 匹配 strategy
100
+ const strategyMatch = findStrategyMatch(dim.inferred_category);
101
+
102
+ // 判断是否满足(核心标准:有修复策略)
103
+ const hasFix = strategyMatch !== null && strategyMatch.strategies.length > 0;
104
+
105
+ return {
106
+ dimension_id: dim.id,
107
+ taxonomy_match: taxonomyMatch,
108
+ strategy_match: strategyMatch,
109
+ has_fix: hasFix,
110
+ needs_gemini_analysis: taxonomyMatch === null || mappings.categories[dim.inferred_category]?.needs_gemini_analysis
111
+ };
112
+ });
113
+ }
114
+
115
+ function findTaxonomyMatch(category) {
116
+ const config = mappings.categories[category];
117
+ if (!config || config.pattern_ids.length === 0) return null;
118
+
119
+ return {
120
+ category: category,
121
+ pattern_ids: config.pattern_ids,
122
+ severity_hint: config.severity_hint
123
+ };
124
+ }
125
+
126
+ function findStrategyMatch(category) {
127
+ const config = mappings.categories[category];
128
+ if (!config) {
129
+ // Fallback to custom from config
130
+ return mappings.fallback;
131
+ }
132
+
133
+ return {
134
+ strategies: config.strategies,
135
+ risk_levels: config.risk_levels
136
+ };
137
+ }
138
+ ```
139
+
140
+ ### Phase 3: 覆盖度评估
141
+
142
+ 评估所有维度的 Spec 覆盖情况:
143
+
144
+ ```javascript
145
+ function evaluateCoverage(specMatches) {
146
+ const total = specMatches.length;
147
+ const withDetection = specMatches.filter(m => m.taxonomy_match !== null).length;
148
+ const withFix = specMatches.filter(m => m.has_fix).length;
149
+
150
+ const rate = total > 0 ? Math.round((withFix / total) * 100) : 0;
151
+
152
+ let status;
153
+ if (rate >= 80) {
154
+ status = 'satisfied';
155
+ } else if (rate >= 50) {
156
+ status = 'partial';
157
+ } else {
158
+ status = 'unsatisfied';
159
+ }
160
+
161
+ return {
162
+ total_dimensions: total,
163
+ with_detection: withDetection,
164
+ with_fix_strategy: withFix,
165
+ coverage_rate: rate,
166
+ status: status
167
+ };
168
+ }
169
+ ```
170
+
171
+ ### Phase 4: 歧义检测
172
+
173
+ 识别需要用户澄清的歧义点:
174
+
175
+ ```javascript
176
+ function detectAmbiguities(dimensions, specMatches) {
177
+ const ambiguities = [];
178
+
179
+ for (const dim of dimensions) {
180
+ const match = specMatches.find(m => m.dimension_id === dim.id);
181
+
182
+ // 检测1: 低置信度 (< 0.5)
183
+ if (dim.confidence < 0.5) {
184
+ ambiguities.push({
185
+ dimension_id: dim.id,
186
+ type: 'vague_description',
187
+ description: `维度 "${dim.description}" 描述模糊,推断置信度低 (${dim.confidence})`,
188
+ possible_interpretations: suggestInterpretations(dim),
189
+ needs_clarification: true
190
+ });
191
+ }
192
+
193
+ // 检测2: 无匹配类别
194
+ if (!match || (!match.taxonomy_match && !match.strategy_match)) {
195
+ ambiguities.push({
196
+ dimension_id: dim.id,
197
+ type: 'no_category_match',
198
+ description: `维度 "${dim.description}" 无法匹配到已知问题类别`,
199
+ possible_interpretations: ['custom'],
200
+ needs_clarification: true
201
+ });
202
+ }
203
+
204
+ // 检测3: 关键词冲突(可能属于多个类别)
205
+ if (dim.keywords.length > 3 && hasConflictingKeywords(dim.keywords)) {
206
+ ambiguities.push({
207
+ dimension_id: dim.id,
208
+ type: 'conflicting_keywords',
209
+ description: `维度 "${dim.description}" 的关键词可能指向多个不同问题`,
210
+ possible_interpretations: inferMultipleCategories(dim.keywords),
211
+ needs_clarification: true
212
+ });
213
+ }
214
+ }
215
+
216
+ return ambiguities;
217
+ }
218
+
219
+ function suggestInterpretations(dim) {
220
+ // 基于 mappings 配置推荐可能的解释
221
+ const categories = Object.keys(mappings.categories).filter(
222
+ cat => cat !== 'authoring_principles_violation' // 排除内部检测类别
223
+ );
224
+ return categories.slice(0, 4); // 返回最常见的 4 个作为选项
225
+ }
226
+
227
+ function hasConflictingKeywords(keywords) {
228
+ // 检查关键词是否指向不同方向
229
+ const categoryHints = keywords.map(k => getKeywordCategoryHint(k));
230
+ const uniqueCategories = [...new Set(categoryHints.filter(c => c))];
231
+ return uniqueCategories.length > 1;
232
+ }
233
+
234
+ function getKeywordCategoryHint(keyword) {
235
+ // 从 mappings.keywords 构建查找表(合并中英文关键词)
236
+ const keywordMap = {
237
+ ...mappings.keywords.chinese,
238
+ ...mappings.keywords.english
239
+ };
240
+ return keywordMap[keyword.toLowerCase()];
241
+ }
242
+ ```
243
+
244
+ ## User Interaction
245
+
246
+ 如果检测到需要澄清的歧义,暂停并询问用户:
247
+
248
+ ```javascript
249
+ async function handleAmbiguities(ambiguities, dimensions) {
250
+ const needsClarification = ambiguities.filter(a => a.needs_clarification);
251
+
252
+ if (needsClarification.length === 0) {
253
+ return null; // 无需澄清
254
+ }
255
+
256
+ const questions = needsClarification.slice(0, 4).map(a => {
257
+ const dim = dimensions.find(d => d.id === a.dimension_id);
258
+
259
+ return {
260
+ question: `关于 "${dim.description}",您具体指的是?`,
261
+ header: a.dimension_id,
262
+ options: a.possible_interpretations.map(interp => ({
263
+ label: getCategoryLabel(interp),
264
+ description: getCategoryDescription(interp)
265
+ })),
266
+ multiSelect: false
267
+ };
268
+ });
269
+
270
+ return await AskUserQuestion({ questions });
271
+ }
272
+
273
+ function getCategoryLabel(category) {
274
+ // 从 mappings 配置加载标签
275
+ return mappings.category_labels_chinese[category] || category;
276
+ }
277
+
278
+ function getCategoryDescription(category) {
279
+ // 从 mappings 配置加载描述
280
+ return mappings.category_descriptions[category] || 'Requires further analysis';
281
+ }
282
+ ```
283
+
284
+ ## Output
285
+
286
+ ### State Updates
287
+
288
+ ```javascript
289
+ return {
290
+ stateUpdates: {
291
+ requirement_analysis: {
292
+ status: ambiguities.some(a => a.needs_clarification) ? 'needs_clarification' : 'completed',
293
+ analyzed_at: new Date().toISOString(),
294
+ dimensions: dimensions,
295
+ spec_matches: specMatches,
296
+ coverage: coverageResult,
297
+ ambiguities: ambiguities
298
+ },
299
+ // 根据分析结果自动优化 focus_areas
300
+ focus_areas: deriveOptimalFocusAreas(specMatches)
301
+ },
302
+ outputFiles: [
303
+ `${workDir}/requirement-analysis.json`,
304
+ `${workDir}/requirement-analysis.md`
305
+ ],
306
+ summary: generateSummary(dimensions, coverageResult, ambiguities)
307
+ };
308
+
309
+ function deriveOptimalFocusAreas(specMatches) {
310
+ const coreCategories = ['context', 'memory', 'dataflow', 'agent'];
311
+ const matched = specMatches
312
+ .filter(m => m.taxonomy_match !== null)
313
+ .map(m => {
314
+ // 映射到诊断 focus_area
315
+ const category = m.taxonomy_match.category;
316
+ if (category === 'context_explosion' || category === 'performance') return 'context';
317
+ if (category === 'memory_loss') return 'memory';
318
+ if (category === 'dataflow_break') return 'dataflow';
319
+ if (category === 'agent_failure' || category === 'error_handling') return 'agent';
320
+ return null;
321
+ })
322
+ .filter(f => f && coreCategories.includes(f));
323
+
324
+ // 去重
325
+ return [...new Set(matched)];
326
+ }
327
+
328
+ function generateSummary(dimensions, coverage, ambiguities) {
329
+ const dimCount = dimensions.length;
330
+ const coverageStatus = coverage.status;
331
+ const ambiguityCount = ambiguities.filter(a => a.needs_clarification).length;
332
+
333
+ let summary = `分析完成:${dimCount} 个维度`;
334
+ summary += `,覆盖度 ${coverage.coverage_rate}% (${coverageStatus})`;
335
+
336
+ if (ambiguityCount > 0) {
337
+ summary += `,${ambiguityCount} 个歧义点待澄清`;
338
+ }
339
+
340
+ return summary;
341
+ }
342
+ ```
343
+
344
+ ### Output Files
345
+
346
+ #### requirement-analysis.json
347
+
348
+ ```json
349
+ {
350
+ "timestamp": "2024-01-01T00:00:00Z",
351
+ "target_skill": "skill-name",
352
+ "user_description": "原始用户描述",
353
+ "dimensions": [...],
354
+ "spec_matches": [...],
355
+ "coverage": {...},
356
+ "ambiguities": [...],
357
+ "derived_focus_areas": [...]
358
+ }
359
+ ```
360
+
361
+ #### requirement-analysis.md
362
+
363
+ ```markdown
364
+ # 需求分析报告
365
+
366
+ ## 用户描述
367
+ > ${user_issue_description}
368
+
369
+ ## 维度拆解
370
+
371
+ | ID | 描述 | 类别 | 置信度 |
372
+ |----|------|------|--------|
373
+ | DIM-001 | ... | ... | 0.85 |
374
+
375
+ ## Spec 匹配
376
+
377
+ | 维度 | 检测模式 | 修复策略 | 是否满足 |
378
+ |------|----------|----------|----------|
379
+ | DIM-001 | CTX-001,002 | sliding_window | ✓ |
380
+
381
+ ## 覆盖度评估
382
+
383
+ - 总维度数: N
384
+ - 有检测手段: M
385
+ - 有修复策略: K (满足标准)
386
+ - 覆盖率: X%
387
+ - 状态: satisfied/partial/unsatisfied
388
+
389
+ ## 歧义点
390
+
391
+ (如有)
392
+ ```
393
+
394
+ ## Error Handling
395
+
396
+ | Error | Recovery |
397
+ |-------|----------|
398
+ | Gemini CLI 超时 | 重试一次,仍失败则使用简化分析 |
399
+ | JSON 解析失败 | 尝试修复 JSON 或使用默认维度 |
400
+ | 无法匹配任何类别 | 全部归类为 custom,触发 Gemini 深度分析 |
401
+
402
+ ## Next Actions
403
+
404
+ - 如果 `requirement_analysis.status === 'completed'`: 继续到 `action-diagnose-*`
405
+ - 如果 `requirement_analysis.status === 'needs_clarification'`: 等待用户澄清后重新执行
406
+ - 如果 `coverage.status === 'unsatisfied'`: 自动触发 `action-gemini-analysis` 进行深度分析
@@ -0,0 +1,206 @@
1
+ # Action: Apply Fix
2
+
3
+ Apply a selected fix to the target skill with backup and rollback capability.
4
+
5
+ ## Purpose
6
+
7
+ - Apply fix changes to target skill files
8
+ - Create backup before modifications
9
+ - Track applied fixes for verification
10
+ - Support rollback if needed
11
+
12
+ ## Preconditions
13
+
14
+ - [ ] state.status === 'running'
15
+ - [ ] state.pending_fixes.length > 0
16
+ - [ ] state.proposed_fixes contains the fix to apply
17
+
18
+ ## Execution
19
+
20
+ ```javascript
21
+ async function execute(state, workDir) {
22
+ const pendingFixes = state.pending_fixes;
23
+ const proposedFixes = state.proposed_fixes;
24
+ const targetPath = state.target_skill.path;
25
+ const backupDir = state.backup_dir;
26
+
27
+ if (pendingFixes.length === 0) {
28
+ return {
29
+ stateUpdates: {},
30
+ outputFiles: [],
31
+ summary: 'No pending fixes to apply'
32
+ };
33
+ }
34
+
35
+ // Get next fix to apply
36
+ const fixId = pendingFixes[0];
37
+ const fix = proposedFixes.find(f => f.id === fixId);
38
+
39
+ if (!fix) {
40
+ return {
41
+ stateUpdates: {
42
+ pending_fixes: pendingFixes.slice(1),
43
+ errors: [...state.errors, {
44
+ action: 'action-apply-fix',
45
+ message: `Fix ${fixId} not found in proposals`,
46
+ timestamp: new Date().toISOString(),
47
+ recoverable: true
48
+ }]
49
+ },
50
+ outputFiles: [],
51
+ summary: `Fix ${fixId} not found, skipping`
52
+ };
53
+ }
54
+
55
+ console.log(`Applying fix ${fix.id}: ${fix.description}`);
56
+
57
+ // Create fix-specific backup
58
+ const fixBackupDir = `${backupDir}/before-${fix.id}`;
59
+ Bash(`mkdir -p "${fixBackupDir}"`);
60
+
61
+ const appliedChanges = [];
62
+ let success = true;
63
+
64
+ for (const change of fix.changes) {
65
+ try {
66
+ // Resolve file path (handle wildcards)
67
+ let targetFiles = [];
68
+ if (change.file.includes('*')) {
69
+ targetFiles = Glob(`${targetPath}/${change.file}`);
70
+ } else {
71
+ targetFiles = [`${targetPath}/${change.file}`];
72
+ }
73
+
74
+ for (const targetFile of targetFiles) {
75
+ // Backup original
76
+ const relativePath = targetFile.replace(targetPath + '/', '');
77
+ const backupPath = `${fixBackupDir}/${relativePath}`;
78
+
79
+ if (Glob(targetFile).length > 0) {
80
+ const originalContent = Read(targetFile);
81
+ Bash(`mkdir -p "$(dirname "${backupPath}")"`);
82
+ Write(backupPath, originalContent);
83
+ }
84
+
85
+ // Apply change based on action type
86
+ if (change.action === 'modify' && change.diff) {
87
+ // For now, append the diff as a comment/note
88
+ // Real implementation would parse and apply the diff
89
+ const existingContent = Read(targetFile);
90
+
91
+ // Simple diff application: look for context and apply
92
+ // This is a simplified version - real implementation would be more sophisticated
93
+ const newContent = existingContent + `\n\n<!-- Applied fix ${fix.id}: ${fix.description} -->\n`;
94
+
95
+ Write(targetFile, newContent);
96
+
97
+ appliedChanges.push({
98
+ file: relativePath,
99
+ action: 'modified',
100
+ backup: backupPath
101
+ });
102
+ } else if (change.action === 'create') {
103
+ Write(targetFile, change.new_content || '');
104
+ appliedChanges.push({
105
+ file: relativePath,
106
+ action: 'created',
107
+ backup: null
108
+ });
109
+ }
110
+ }
111
+ } catch (error) {
112
+ console.log(`Error applying change to ${change.file}: ${error.message}`);
113
+ success = false;
114
+ }
115
+ }
116
+
117
+ // Record applied fix
118
+ const appliedFix = {
119
+ fix_id: fix.id,
120
+ applied_at: new Date().toISOString(),
121
+ success: success,
122
+ backup_path: fixBackupDir,
123
+ verification_result: 'pending',
124
+ rollback_available: true,
125
+ changes_made: appliedChanges
126
+ };
127
+
128
+ // Update applied fixes log
129
+ const appliedFixesPath = `${workDir}/fixes/applied-fixes.json`;
130
+ let existingApplied = [];
131
+ try {
132
+ existingApplied = JSON.parse(Read(appliedFixesPath));
133
+ } catch (e) {
134
+ existingApplied = [];
135
+ }
136
+ existingApplied.push(appliedFix);
137
+ Write(appliedFixesPath, JSON.stringify(existingApplied, null, 2));
138
+
139
+ return {
140
+ stateUpdates: {
141
+ applied_fixes: [...state.applied_fixes, appliedFix],
142
+ pending_fixes: pendingFixes.slice(1) // Remove applied fix from pending
143
+ },
144
+ outputFiles: [appliedFixesPath],
145
+ summary: `Applied fix ${fix.id}: ${success ? 'success' : 'partial'}, ${appliedChanges.length} files modified`
146
+ };
147
+ }
148
+ ```
149
+
150
+ ## State Updates
151
+
152
+ ```javascript
153
+ return {
154
+ stateUpdates: {
155
+ applied_fixes: [...existingApplied, newAppliedFix],
156
+ pending_fixes: remainingPendingFixes
157
+ }
158
+ };
159
+ ```
160
+
161
+ ## Rollback Function
162
+
163
+ ```javascript
164
+ async function rollbackFix(fixId, state, workDir) {
165
+ const appliedFix = state.applied_fixes.find(f => f.fix_id === fixId);
166
+
167
+ if (!appliedFix || !appliedFix.rollback_available) {
168
+ throw new Error(`Cannot rollback fix ${fixId}`);
169
+ }
170
+
171
+ const backupDir = appliedFix.backup_path;
172
+ const targetPath = state.target_skill.path;
173
+
174
+ // Restore from backup
175
+ const backupFiles = Glob(`${backupDir}/**/*`);
176
+ for (const backupFile of backupFiles) {
177
+ const relativePath = backupFile.replace(backupDir + '/', '');
178
+ const targetFile = `${targetPath}/${relativePath}`;
179
+ const content = Read(backupFile);
180
+ Write(targetFile, content);
181
+ }
182
+
183
+ return {
184
+ stateUpdates: {
185
+ applied_fixes: state.applied_fixes.map(f =>
186
+ f.fix_id === fixId
187
+ ? { ...f, rollback_available: false, verification_result: 'rolled_back' }
188
+ : f
189
+ )
190
+ }
191
+ };
192
+ }
193
+ ```
194
+
195
+ ## Error Handling
196
+
197
+ | Error Type | Recovery |
198
+ |------------|----------|
199
+ | File not found | Skip file, log warning |
200
+ | Write permission error | Retry with sudo or report |
201
+ | Backup creation failed | Abort fix, don't modify |
202
+
203
+ ## Next Actions
204
+
205
+ - If pending_fixes.length > 0: action-apply-fix (continue)
206
+ - If all fixes applied: action-verify