@mycodemap/mycodemap 0.1.0 → 0.1.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 (64) hide show
  1. package/CHANGELOG.md +86 -6
  2. package/README.md +172 -80
  3. package/dist/cli/commands/cycles.d.ts.map +1 -1
  4. package/dist/cli/commands/cycles.js +2 -0
  5. package/dist/cli/commands/cycles.js.map +1 -1
  6. package/dist/cli/commands/init.d.ts.map +1 -1
  7. package/dist/cli/commands/init.js +3 -1
  8. package/dist/cli/commands/init.js.map +1 -1
  9. package/dist/cli/commands/logs.d.ts +5 -0
  10. package/dist/cli/commands/logs.d.ts.map +1 -0
  11. package/dist/cli/commands/logs.js +189 -0
  12. package/dist/cli/commands/logs.js.map +1 -0
  13. package/dist/cli/commands/report.d.ts +12 -0
  14. package/dist/cli/commands/report.d.ts.map +1 -0
  15. package/dist/cli/commands/report.js +158 -0
  16. package/dist/cli/commands/report.js.map +1 -0
  17. package/dist/cli/commands/watch-foreground.d.ts.map +1 -1
  18. package/dist/cli/commands/watch-foreground.js +2 -0
  19. package/dist/cli/commands/watch-foreground.js.map +1 -1
  20. package/dist/cli/commands/watch.d.ts.map +1 -1
  21. package/dist/cli/commands/watch.js +2 -0
  22. package/dist/cli/commands/watch.js.map +1 -1
  23. package/dist/cli/first-run-guide.d.ts +23 -0
  24. package/dist/cli/first-run-guide.d.ts.map +1 -0
  25. package/dist/cli/first-run-guide.js +83 -0
  26. package/dist/cli/first-run-guide.js.map +1 -0
  27. package/dist/cli/index.js +63 -0
  28. package/dist/cli/index.js.map +1 -1
  29. package/dist/cli/platform-check.d.ts +21 -0
  30. package/dist/cli/platform-check.d.ts.map +1 -0
  31. package/dist/cli/platform-check.js +94 -0
  32. package/dist/cli/platform-check.js.map +1 -0
  33. package/dist/cli/tree-sitter-check.d.ts +35 -0
  34. package/dist/cli/tree-sitter-check.d.ts.map +1 -0
  35. package/dist/cli/tree-sitter-check.js +133 -0
  36. package/dist/cli/tree-sitter-check.js.map +1 -0
  37. package/dist/cli/utils/sanitize.d.ts +54 -0
  38. package/dist/cli/utils/sanitize.d.ts.map +1 -0
  39. package/dist/cli/utils/sanitize.js +131 -0
  40. package/dist/cli/utils/sanitize.js.map +1 -0
  41. package/docs/AI_ASSISTANT_SETUP.md +743 -0
  42. package/docs/CI_GATEWAY_DESIGN.md +784 -0
  43. package/docs/OMC_TEAM_DEBUG_REPORT.md +285 -0
  44. package/docs/PUBLISH_NPM_DESIGN_FINAL.md +485 -0
  45. package/docs/REFACTOR_ARCHITECTURE_OVERVIEW.md +552 -0
  46. package/docs/REFACTOR_CONFIDENCE_DESIGN.md +244 -0
  47. package/docs/REFACTOR_GIT_ANALYZER_DESIGN.md +785 -0
  48. package/docs/REFACTOR_ORCHESTRATOR_DESIGN.md +1065 -0
  49. package/docs/REFACTOR_REQUIREMENTS.md +970 -0
  50. package/docs/REFACTOR_RESULT_FUSION_DESIGN.md +315 -0
  51. package/docs/REFACTOR_TEST_LINKER_DESIGN.md +311 -0
  52. package/docs/SETUP_GUIDE.md +407 -0
  53. package/docs/archive/AI_INTEGRATION_GUIDE_ARCHIVED.md +385 -0
  54. package/docs/archive/PUBLISH_NPM_DESIGN_V1.md +1693 -0
  55. package/docs/archive/PUBLISH_NPM_DESIGN_V2.md +390 -0
  56. package/docs/archive/TASK_DESIGN_COVERAGE_REPORT.md +314 -0
  57. package/docs/plans/POST_TASK_PLAN.md +129 -0
  58. package/docs/plans/archive/2026-03-03-deps-path-extension-fix.md +186 -0
  59. package/examples/README.md +61 -0
  60. package/examples/claude/codemap-skill.md +94 -0
  61. package/examples/codex/codemap-agent.md +66 -0
  62. package/examples/copilot/copilot-instructions.md +24 -0
  63. package/examples/kimi/codemap-skill.md +92 -0
  64. package/package.json +5 -3
@@ -0,0 +1,1065 @@
1
+ # CLI 命令与编排层详细设计
2
+
3
+ > 版本: 2.5
4
+ > 所属模块: 编排层 - CLI 命令与工具编排器
5
+
6
+ ---
7
+
8
+ ## 1. 工具编排器设计
9
+
10
+ ### 1.1 核心类
11
+
12
+ ```typescript
13
+ // src/orchestrator/tool-orchestrator.ts
14
+
15
+ class ToolOrchestrator {
16
+ // 超时配置(毫秒)
17
+ private readonly DEFAULT_TIMEOUT = 30000;
18
+
19
+ // 日志记录器
20
+ private logger = console;
21
+
22
+ // 预定义回退链(仅内部调试用,默认关闭)
23
+ // 用户可见输出必须走 CodeMap 语义链路
24
+ private fallbackChains: Record<string, string[]> = {
25
+ 'ast-grep': ['rg-internal'], // AST搜索 → 文本搜索(内部)
26
+ 'codemap': ['rg-internal'], // 结构分析 → 文本搜索(内部)
27
+ };
28
+ }
29
+ ```
30
+
31
+ ### 1.2 超时控制
32
+
33
+ ```typescript
34
+ /**
35
+ * 带超时控制的工具执行
36
+ */
37
+ async runToolWithTimeout(
38
+ tool: string,
39
+ intent: CodemapIntent,
40
+ timeout: number = this.DEFAULT_TIMEOUT
41
+ ): Promise<UnifiedResult[]> {
42
+ try {
43
+ this.logger.debug(`执行工具: ${tool}, 超时: ${timeout}ms`);
44
+
45
+ const controller = new AbortController();
46
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
47
+
48
+ const results = await this.runTool(tool, intent, { signal: controller.signal });
49
+ clearTimeout(timeoutId);
50
+
51
+ this.logger.debug(`工具 ${tool} 执行成功,返回 ${results.length} 条结果`);
52
+ return results;
53
+ } catch (error) {
54
+ if (error instanceof Error && error.name === 'AbortError') {
55
+ this.logger.warn(`工具 ${tool} 执行超时 (${timeout}ms)`);
56
+ } else {
57
+ this.logger.error(`工具 ${tool} 执行失败: ${error}`);
58
+ }
59
+ // 超时或错误时返回空结果,触发回退
60
+ return [];
61
+ }
62
+ }
63
+ ```
64
+
65
+ ### 1.3 错误隔离
66
+
67
+ ```typescript
68
+ /**
69
+ * 错误隔离的工具执行
70
+ */
71
+ async runToolSafely(
72
+ tool: string,
73
+ intent: CodemapIntent
74
+ ): Promise<{ results: UnifiedResult[]; error?: Error }> {
75
+ try {
76
+ const results = await this.runToolWithTimeout(tool, intent);
77
+ return { results };
78
+ } catch (error) {
79
+ this.logger.error(`工具 ${tool} 执行异常:`, error);
80
+ return { results: [], error: error as Error };
81
+ }
82
+ }
83
+ ```
84
+
85
+ ### 1.4 回退执行
86
+
87
+ ```typescript
88
+ async executeWithFallback(
89
+ intent: CodemapIntent,
90
+ primaryTool: string
91
+ ): Promise<{ results: UnifiedResult[]; tool: string; confidence: ConfidenceResult }> {
92
+ // 1. 执行主工具
93
+ let results = await this.runTool(primaryTool, intent);
94
+ let confidence = calculateConfidence(results, intent.intent);
95
+
96
+ // 2. 检查是否需要回退(低于当前 intent 的中等阈值)
97
+ const threshold = getThreshold(intent.intent, 'medium');
98
+ if (confidence.score < threshold) {
99
+ const fallbackTools = this.fallbackChains[primaryTool] || [];
100
+
101
+ for (const fallbackTool of fallbackTools) {
102
+ console.warn(`[LOW CONFIDENCE] ${primaryTool} confidence: ${confidence.score.toFixed(2)}, trying ${fallbackTool}...`);
103
+
104
+ const fallbackResults = await this.runTool(fallbackTool, intent);
105
+ const fallbackConfidence = calculateConfidence(fallbackResults, intent.intent);
106
+
107
+ // 3. 合并结果(去重 + 排序)
108
+ results = this.mergeResults(results, fallbackResults);
109
+
110
+ // 更新置信度(取最大值)
111
+ confidence = {
112
+ score: Math.max(confidence.score, fallbackConfidence.score),
113
+ level: confidence.score > fallbackConfidence.score ? confidence.level : fallbackConfidence.level,
114
+ reasons: [...confidence.reasons, ...fallbackConfidence.reasons]
115
+ };
116
+
117
+ // 4. 达到阈值则停止回退
118
+ if (confidence.score >= threshold) {
119
+ confidence.reasons.push(`回退到 ${fallbackTool} 后达到阈值`);
120
+ break;
121
+ }
122
+ }
123
+ }
124
+
125
+ return { results, tool: primaryTool, confidence };
126
+ }
127
+ ```
128
+
129
+ ---
130
+
131
+ ## 2. 工具适配器设计
132
+
133
+ ### 2.1 适配器基类
134
+
135
+ ```typescript
136
+ interface ToolAdapter {
137
+ name: string;
138
+ weight: number;
139
+ isAvailable(): Promise<boolean>;
140
+ execute(keywords: string[], options: ToolOptions): Promise<UnifiedResult[]>;
141
+ }
142
+ ```
143
+
144
+ ### 2.2 ast-grep 适配器
145
+
146
+ ```typescript
147
+ // src/orchestrator/adapters/ast-grep-adapter.ts
148
+
149
+ class AstGrepAdapter implements ToolAdapter {
150
+ readonly name = 'ast-grep';
151
+ readonly weight = 1.0;
152
+ private available: boolean | null = null;
153
+
154
+ /**
155
+ * 检测 ast-grep 是否可用
156
+ * 如果不可用,后续调用会自动回退到内部文本兜底链路
157
+ */
158
+ async isAvailable(): Promise<boolean> {
159
+ if (this.available !== null) return this.available;
160
+
161
+ try {
162
+ // 使用 execFile 避免命令注入风险
163
+ await execFile('sg', ['--version']);
164
+ this.available = true;
165
+ } catch {
166
+ this.available = false;
167
+ }
168
+ return this.available;
169
+ }
170
+
171
+ async execute(keywords: string[], options: ToolOptions): Promise<UnifiedResult[]> {
172
+ // 先检查是否可用
173
+ if (!(await this.isAvailable())) {
174
+ throw new Error('ast-grep 不可用');
175
+ }
176
+
177
+ // 使用 spawn/execFile 避免命令注入风险
178
+ const args = ['-p', '.', '--json', ...keywords];
179
+ const { stdout } = await execFile('sg', args);
180
+
181
+ // ast-grep JSON 输出是匹配对象流,每行一个 JSON 对象
182
+ const results: UnifiedResult[] = [];
183
+ const lines = stdout.split('\n').filter(line => line.trim());
184
+
185
+ for (const line of lines) {
186
+ try {
187
+ const r = JSON.parse(line);
188
+ // 兼容两种输出格式:直接对象或 { results: [...] } 包装
189
+ const matches = r.results || [r];
190
+ for (const match of matches) {
191
+ results.push({
192
+ id: `ast-grep-${match.file}-${match.line}`,
193
+ source: 'ast-grep',
194
+ toolScore: match.score || 0.9,
195
+ type: 'code',
196
+ file: match.file,
197
+ line: match.line,
198
+ content: this.truncateByToken(match.content, 160),
199
+ relevance: match.score || 0.9,
200
+ keywords
201
+ });
202
+ }
203
+ } catch {
204
+ // 跳过无法解析的行
205
+ }
206
+ }
207
+
208
+ return results;
209
+ }
210
+
211
+ /**
212
+ * 按 token 数量截断内容
213
+ */
214
+ private truncateByToken(content: string, maxTokens: number): string {
215
+ const tokens = content.split(/[\s\u4e00-\u9fa5]/).filter(Boolean);
216
+ if (tokens.length <= maxTokens) return content;
217
+ return tokens.slice(0, maxTokens).join(' ') + '...';
218
+ }
219
+ }
220
+ ```
221
+
222
+ ---
223
+
224
+ ## 3. 意图路由设计
225
+
226
+ ### 3.1 路由接口
227
+
228
+ ```typescript
229
+ interface CodemapIntent {
230
+ intent: IntentType;
231
+ targets: string[];
232
+ keywords: string[];
233
+ scope: 'direct' | 'transitive';
234
+ tool: string;
235
+ }
236
+
237
+ class IntentRouter {
238
+ route(args: AnalyzeArgs): CodemapIntent {
239
+ // 根据参数确定 intent 类型
240
+ // ...
241
+ }
242
+ }
243
+ ```
244
+
245
+ ### 3.2 命令映射
246
+
247
+ | analyze 参数 | 底层复用 | 增强点 |
248
+ |--------------|----------|--------|
249
+ | `--intent impact` | `ImpactCommand` | + ast-grep 搜索 + Git 分析 + 置信度 |
250
+ | `--intent dependency` | `DepsCommand` | + Token 裁剪 |
251
+ | `--intent complexity` | `ComplexityCommand` | + Token 裁剪 |
252
+ | `--intent search` | 新实现 | 使用 ast-grep + 置信度 |
253
+ | `--intent overview` | 新实现 | 使用 Codemap 核心 |
254
+ | `--intent documentation` | 新实现 | 使用 codemap 搜索 Markdown 文件 |
255
+ | `--intent refactor` | 新实现 | 使用 ast-grep |
256
+
257
+ ---
258
+
259
+ ## 4. AnalyzeCommand 实现
260
+
261
+ ### 4.1 命令类
262
+
263
+ ```typescript
264
+ // src/cli/commands/analyze.ts
265
+
266
+ export class AnalyzeCommand {
267
+ private orchestrator = new ToolOrchestrator();
268
+ private router = new IntentRouter();
269
+ private fusion = new ResultFusion();
270
+
271
+ // 复用现有命令
272
+ private impactCmd = new ImpactCommand();
273
+ private depsCmd = new DepsCommand();
274
+ private complexityCmd = new ComplexityCommand();
275
+
276
+ async run(args: AnalyzeArgs): Promise<void> {
277
+ const intent = this.router.route(args);
278
+ const outputMode = args.outputMode || 'human';
279
+
280
+ switch (intent.intent) {
281
+ case 'impact':
282
+ // 复用现有 impact + 增强
283
+ const impactResult = await this.impactCmd.run({
284
+ targets: intent.targets,
285
+ scope: intent.scope
286
+ });
287
+ // 额外调用 ast-grep 增强搜索
288
+ const searchResult = await this.orchestrator.runTool('ast-grep', intent.keywords);
289
+ // 融合结果:展平为单一数组
290
+ return this.output(this.fuseResults(...impactResult, ...searchResult));
291
+
292
+ case 'dependency':
293
+ const depsResult = await this.depsCmd.run({ targets: intent.targets });
294
+ return this.output(this.formatOutput(depsResult, args));
295
+
296
+ case 'complexity':
297
+ const complexityResult = await this.complexityCmd.run({ targets: intent.targets });
298
+ return this.output(this.formatOutput(complexityResult, args));
299
+
300
+ case 'search':
301
+ case 'overview':
302
+ case 'documentation':
303
+ case 'refactor':
304
+ // 新功能,走编排器(带置信度和回退)
305
+ const { results, tool, confidence } = await this.orchestrator.executeWithFallback(
306
+ intent,
307
+ intent.tool
308
+ );
309
+ // machine/json 模式禁止额外前缀日志,保证纯 JSON 输出契约
310
+ if (outputMode === 'human' && !args.json) {
311
+ console.log(`Tool: ${tool}, Confidence: ${confidence.level} (${confidence.score.toFixed(2)})`);
312
+ }
313
+ return this.output(results);
314
+ }
315
+ }
316
+
317
+ private fuseResults(...results: UnifiedResult[]): UnifiedResult[] {
318
+ // 展平所有结果
319
+ const allResults = results.flat();
320
+ const byTool = new Map<string, UnifiedResult[]>();
321
+ allResults.forEach(r => {
322
+ const existing = byTool.get(r.source) || [];
323
+ existing.push(r);
324
+ byTool.set(r.source, existing);
325
+ });
326
+ return this.fusion.fuse(byTool, { topK: 8, keywordWeights: {} });
327
+ }
328
+ }
329
+ ```
330
+
331
+ ---
332
+
333
+ ## 5. 向后兼容
334
+
335
+ ### 5.1 ImpactCommand 增强模式
336
+
337
+ ```typescript
338
+ // src/cli/commands/impact.ts
339
+
340
+ export class ImpactCommand {
341
+ // 保持原有接口不变
342
+ async run(args: ImpactArgs): Promise<UnifiedResult[]> {
343
+ // 原有逻辑...
344
+ }
345
+
346
+ // 新增:增强模式(供 analyze 调用)
347
+ async runEnhanced(args: ImpactArgs): Promise<UnifiedResult[]> {
348
+ const basic = await this.run(args);
349
+ return this.toUnifiedResults(basic);
350
+ }
351
+
352
+ private toUnifiedResults(basic: ImpactResult): UnifiedResult[] {
353
+ // 转换为统一格式
354
+ return basic.dependencies.map(d => ({
355
+ id: `impact-${d.file}`,
356
+ source: 'codemap',
357
+ toolScore: d.score || 0.9,
358
+ type: 'file',
359
+ file: d.file,
360
+ relevance: d.score || 0.9,
361
+ keywords: [],
362
+ metadata: { dependencies: d.dependents }
363
+ }));
364
+ }
365
+ }
366
+ ```
367
+
368
+ ---
369
+
370
+ ## 6. 模块依赖图
371
+
372
+ ```
373
+ CLI 入口
374
+
375
+
376
+ AnalyzeCommand (analyze.ts)
377
+
378
+ ├──────▶ IntentRouter (intent-router.ts)
379
+
380
+ ├──────▶ ToolOrchestrator (tool-orchestrator.ts)
381
+ │ │
382
+ │ ├─────▶ AstGrepAdapter (ast-grep-adapter.ts)
383
+ │ ├─────▶ CodemapAdapter (codemap-adapter.ts)
384
+ │ ├─────▶ RgInternalAdapter (rg-adapter.ts, 内部兜底)
385
+ │ │
386
+ │ └─────▶ ResultFusion (result-fusion.ts)
387
+ │ │
388
+ │ └─────▶ Confidence (confidence.ts)
389
+
390
+ └──────▶ 现有命令 (impact.ts, deps.ts, complexity.ts)
391
+ ```
392
+
393
+ ---
394
+
395
+ ## 7. 配置设计
396
+
397
+ ```json
398
+ {
399
+ "orchestrator": {
400
+ "enabled": true,
401
+ "tools": {
402
+ "ast-grep": { "enabled": true, "command": "sg", "required": false },
403
+ "rg-internal": { "enabled": false, "command": "rg", "required": false }
404
+ },
405
+ "output": {
406
+ "topK": 8,
407
+ "maxTokenPerItem": 160
408
+ },
409
+ "confidence": {
410
+ "thresholds": {
411
+ "high": 0.6,
412
+ "medium": 0.3
413
+ }
414
+ },
415
+ "fallback": {
416
+ "enabled": true
417
+ }
418
+ }
419
+ }
420
+ ```
421
+
422
+ ---
423
+
424
+ ## 8. 工作流编排器设计 (v2.5 规划)
425
+
426
+ ### 8.1 设计目标
427
+
428
+ 串联所有模块的"粘合剂",解决阶段割裂问题:
429
+
430
+ | 问题 | 解决方案 |
431
+ |------|----------|
432
+ | 阶段连接不紧密 | 状态机 + 检查点机制 |
433
+ | 容易迷失阶段 | 交互式工作流引导 |
434
+ | 中断后无法恢复 | 上下文持久化 |
435
+ | 交付物不明确 | 阶段契约定义 |
436
+
437
+ ### 8.2 核心概念
438
+
439
+ #### 工作流阶段定义
440
+
441
+ ```typescript
442
+ // src/orchestrator/workflow/types.ts
443
+
444
+ type WorkflowPhase =
445
+ | 'reference' // 参考搜索
446
+ | 'impact' // 影响分析
447
+ | 'risk' // 风险评估
448
+ | 'implementation' // 代码实现
449
+ | 'commit' // 提交验证
450
+ | 'ci'; // CI 流水线
451
+
452
+ interface PhaseDefinition {
453
+ name: WorkflowPhase;
454
+ action: 'analyze' | 'ci' | 'manual'; // 阶段执行方式
455
+ analyzeIntent?: IntentType; // 仅 action=analyze 时需要
456
+ ciCommand?: string; // 仅 action=ci 时需要
457
+ entryCondition: PhaseCondition; // 入口条件
458
+ deliverables: Deliverable[]; // 交付物
459
+ nextPhase?: WorkflowPhase; // 下一阶段
460
+ commands: string[]; // 可执行的命令
461
+ }
462
+
463
+ interface PhaseCondition {
464
+ minConfidence?: number; // 最低置信度
465
+ requiredArtifacts?: string[]; // 必需的产物
466
+ }
467
+
468
+ interface Deliverable {
469
+ name: string;
470
+ path: string;
471
+ validator: (path: string) => boolean;
472
+ }
473
+ ```
474
+
475
+ #### 工作流上下文
476
+
477
+ ```typescript
478
+ // src/orchestrator/workflow/workflow-context.ts
479
+
480
+ interface WorkflowContext {
481
+ id: string; // 工作流实例 ID
482
+ task: string; // 用户任务描述
483
+ currentPhase: WorkflowPhase;
484
+ phaseStatus: PhaseStatus;
485
+
486
+ // 阶段产物(自动传递)
487
+ artifacts: Map<WorkflowPhase, PhaseArtifacts>;
488
+
489
+ // 分析结果缓存
490
+ cachedResults: {
491
+ reference?: UnifiedResult[];
492
+ impact?: UnifiedResult[];
493
+ risk?: RiskScore;
494
+ };
495
+
496
+ // 用户确认状态
497
+ userConfirmed: Set<WorkflowPhase>;
498
+
499
+ // 时间戳
500
+ startedAt: Date;
501
+ updatedAt: Date;
502
+ }
503
+
504
+ interface PhaseArtifacts {
505
+ phase: WorkflowPhase;
506
+ results?: UnifiedResult[];
507
+ confidence?: ConfidenceResult;
508
+ metadata?: Record<string, unknown>;
509
+ createdAt: Date;
510
+ }
511
+
512
+ type PhaseStatus = 'pending' | 'running' | 'completed' | 'verified' | 'skipped';
513
+ ```
514
+
515
+ ### 8.3 工作流编排器类
516
+
517
+ ```typescript
518
+ // src/orchestrator/workflow/workflow-orchestrator.ts
519
+
520
+ class WorkflowOrchestrator {
521
+ private context: WorkflowContext | null = null;
522
+ private phaseDefinitions: Map<WorkflowPhase, PhaseDefinition>;
523
+ private persistence: WorkflowPersistence;
524
+
525
+ constructor() {
526
+ this.phaseDefinitions = this.initializePhaseDefinitions();
527
+ this.persistence = new WorkflowPersistence();
528
+ }
529
+
530
+ /**
531
+ * 启动新的工作流
532
+ */
533
+ async start(task: string): Promise<WorkflowContext> {
534
+ this.context = {
535
+ id: this.generateId(),
536
+ task,
537
+ currentPhase: 'reference',
538
+ phaseStatus: 'pending',
539
+ artifacts: new Map(),
540
+ cachedResults: {},
541
+ userConfirmed: new Set(),
542
+ startedAt: new Date(),
543
+ updatedAt: new Date()
544
+ };
545
+
546
+ // 保存初始状态
547
+ await this.persistence.save(this.context);
548
+
549
+ return this.context;
550
+ }
551
+
552
+ /**
553
+ * 执行当前阶段
554
+ */
555
+ async executeCurrentPhase(analyzeArgs: AnalyzeArgs): Promise<PhaseResult> {
556
+ if (!this.context) {
557
+ throw new Error('No active workflow. Call start() first.');
558
+ }
559
+
560
+ const phase = this.context.currentPhase;
561
+ const definition = this.phaseDefinitions.get(phase);
562
+
563
+ if (!definition) {
564
+ throw new Error(`Unknown phase: ${phase}`);
565
+ }
566
+
567
+ // 更新状态为 running
568
+ this.context.phaseStatus = 'running';
569
+ await this.persistence.save(this.context);
570
+
571
+ // 按阶段执行方式运行(避免将非 analyze 阶段误当作 intent)
572
+ const results = await this.runPhase(definition, analyzeArgs);
573
+
574
+ // 仅 analyze 阶段计算置信度
575
+ const confidence = definition.action === 'analyze' && definition.analyzeIntent
576
+ ? calculateConfidence(results, definition.analyzeIntent)
577
+ : { score: 1, level: 'high', reasons: ['non-analyze phase'] };
578
+
579
+ // 保存产物
580
+ const artifacts: PhaseArtifacts = {
581
+ phase,
582
+ results,
583
+ confidence,
584
+ createdAt: new Date()
585
+ };
586
+ this.context.artifacts.set(phase, artifacts);
587
+ this.context.cachedResults[phase] = results;
588
+
589
+ // 更新状态为 completed
590
+ this.context.phaseStatus = 'completed';
591
+ this.context.updatedAt = new Date();
592
+ await this.persistence.save(this.context);
593
+
594
+ return { artifacts, confidence, canProceed: this.checkProceedCondition(confidence) };
595
+ }
596
+
597
+ private async runPhase(
598
+ definition: PhaseDefinition,
599
+ analyzeArgs: AnalyzeArgs
600
+ ): Promise<UnifiedResult[]> {
601
+ if (definition.action === 'analyze' && definition.analyzeIntent) {
602
+ return this.runAnalysis(definition.analyzeIntent, analyzeArgs);
603
+ }
604
+ if (definition.action === 'ci' && definition.ciCommand) {
605
+ await this.runCICommand(definition.ciCommand);
606
+ return [];
607
+ }
608
+ return [];
609
+ }
610
+
611
+ /**
612
+ * 验证是否可以进入下一阶段
613
+ */
614
+ private checkProceedCondition(confidence: ConfidenceResult): boolean {
615
+ const phase = this.context!.currentPhase;
616
+ const definition = this.phaseDefinitions.get(phase);
617
+
618
+ if (!definition) return false;
619
+
620
+ const { entryCondition } = definition;
621
+
622
+ // 检查置信度
623
+ if (entryCondition.minConfidence && confidence.score < entryCondition.minConfidence) {
624
+ return false;
625
+ }
626
+
627
+ return true;
628
+ }
629
+
630
+ /**
631
+ * 推进到下一阶段
632
+ */
633
+ async proceedToNextPhase(): Promise<WorkflowPhase> {
634
+ if (!this.context) {
635
+ throw new Error('No active workflow');
636
+ }
637
+
638
+ const current = this.context.currentPhase;
639
+ const definition = this.phaseDefinitions.get(current);
640
+
641
+ if (!definition?.nextPhase) {
642
+ throw new Error('No next phase available');
643
+ }
644
+
645
+ // 验证当前阶段已完成
646
+ if (this.context.phaseStatus !== 'completed') {
647
+ throw new Error(`Current phase ${current} is not completed`);
648
+ }
649
+
650
+ // 标记当前阶段为 verified
651
+ this.context.phaseStatus = 'verified';
652
+
653
+ // 推进到下一阶段
654
+ this.context.currentPhase = definition.nextPhase;
655
+ this.context.phaseStatus = 'pending';
656
+ this.context.updatedAt = new Date();
657
+
658
+ await this.persistence.save(this.context);
659
+
660
+ return definition.nextPhase;
661
+ }
662
+
663
+ /**
664
+ * 获取工作流状态
665
+ */
666
+ async getStatus(): Promise<WorkflowStatus> {
667
+ if (!this.context) {
668
+ this.context = await this.persistence.loadActive();
669
+ }
670
+ if (!this.context) return { active: false };
671
+
672
+ return {
673
+ active: true,
674
+ task: this.context.task,
675
+ currentPhase: this.context.currentPhase,
676
+ phaseStatus: this.context.phaseStatus,
677
+ progress: this.calculateProgress(),
678
+ artifacts: Array.from(this.context.artifacts.keys())
679
+ };
680
+ }
681
+
682
+ private calculateProgress(): number {
683
+ const totalPhases = this.phaseDefinitions.size;
684
+ const completedPhases = Array.from(this.context!.artifacts.keys()).length;
685
+ return (completedPhases / totalPhases) * 100;
686
+ }
687
+
688
+ private initializePhaseDefinitions(): Map<WorkflowPhase, PhaseDefinition> {
689
+ return new Map([
690
+ ['reference', {
691
+ name: 'reference',
692
+ action: 'analyze',
693
+ analyzeIntent: 'reference',
694
+ entryCondition: { minConfidence: 0.3 },
695
+ deliverables: [
696
+ { name: 'reference-results', path: '.mycodemap/workflow/reference.json', validator: () => true }
697
+ ],
698
+ nextPhase: 'impact',
699
+ commands: ['codemap analyze --intent reference']
700
+ }],
701
+ ['impact', {
702
+ name: 'impact',
703
+ action: 'analyze',
704
+ analyzeIntent: 'impact',
705
+ entryCondition: { minConfidence: 0.4 },
706
+ deliverables: [
707
+ { name: 'impact-report', path: '.mycodemap/workflow/impact.json', validator: () => true }
708
+ ],
709
+ nextPhase: 'risk',
710
+ commands: ['codemap analyze --intent impact']
711
+ }],
712
+ ['risk', {
713
+ name: 'risk',
714
+ action: 'ci',
715
+ ciCommand: 'codemap ci assess-risk --threshold 0.7',
716
+ entryCondition: {},
717
+ deliverables: [
718
+ { name: 'risk-assessment', path: '.mycodemap/workflow/risk.json', validator: () => true }
719
+ ],
720
+ nextPhase: 'implementation',
721
+ commands: ['codemap ci assess-risk']
722
+ }],
723
+ ['implementation', {
724
+ name: 'implementation',
725
+ action: 'manual',
726
+ entryCondition: {},
727
+ deliverables: [
728
+ { name: 'implementation', path: 'src/', validator: () => true }
729
+ ],
730
+ nextPhase: 'commit',
731
+ commands: []
732
+ }],
733
+ ['commit', {
734
+ name: 'commit',
735
+ action: 'manual',
736
+ entryCondition: {},
737
+ deliverables: [
738
+ { name: 'commit', path: '.git/COMMIT_EDITMSG', validator: () => true }
739
+ ],
740
+ nextPhase: 'ci',
741
+ commands: ['git commit']
742
+ }],
743
+ ['ci', {
744
+ name: 'ci',
745
+ action: 'ci',
746
+ ciCommand: 'npm test && codemap ci check-commits && codemap ci check-headers && codemap ci check-output-contract',
747
+ entryCondition: {},
748
+ deliverables: [],
749
+ commands: []
750
+ }]
751
+ ]);
752
+ }
753
+ }
754
+ ```
755
+
756
+ ### 8.4 工作流持久化
757
+
758
+ ```typescript
759
+ // src/orchestrator/workflow/workflow-persistence.ts
760
+
761
+ class WorkflowPersistence {
762
+ private storagePath = '.codemap/workflow';
763
+ private activePath = '.mycodemap/workflow/active.json';
764
+
765
+ async save(context: WorkflowContext): Promise<void> {
766
+ const fs = require('fs').promises;
767
+ const path = require('path');
768
+
769
+ // 确保目录存在
770
+ await fs.mkdir(this.storagePath, { recursive: true });
771
+
772
+ const filePath = path.join(this.storagePath, `${context.id}.json`);
773
+ await fs.writeFile(filePath, JSON.stringify(this.serialize(context), null, 2));
774
+ await fs.writeFile(this.activePath, JSON.stringify({ id: context.id }, null, 2));
775
+ }
776
+
777
+ async load(id: string): Promise<WorkflowContext | null> {
778
+ const fs = require('fs').promises;
779
+ const path = require('path');
780
+
781
+ const filePath = path.join(this.storagePath, `${id}.json`);
782
+
783
+ try {
784
+ const content = await fs.readFile(filePath, 'utf-8');
785
+ return this.deserialize(JSON.parse(content));
786
+ } catch {
787
+ return null;
788
+ }
789
+ }
790
+
791
+ async loadActive(): Promise<WorkflowContext | null> {
792
+ const fs = require('fs').promises;
793
+ try {
794
+ const content = await fs.readFile(this.activePath, 'utf-8');
795
+ const { id } = JSON.parse(content);
796
+ return id ? this.load(id) : null;
797
+ } catch {
798
+ return null;
799
+ }
800
+ }
801
+
802
+ async list(): Promise<WorkflowSummary[]> {
803
+ const fs = require('fs').promises;
804
+ const path = require('path');
805
+
806
+ const dir = path.join(process.cwd(), this.storagePath);
807
+
808
+ try {
809
+ const files = await fs.readdir(dir);
810
+ const summaries: WorkflowSummary[] = [];
811
+
812
+ for (const file of files) {
813
+ if (!file.endsWith('.json')) continue;
814
+
815
+ const content = await fs.readFile(path.join(dir, file), 'utf-8');
816
+ const ctx = JSON.parse(content);
817
+
818
+ summaries.push({
819
+ id: ctx.id,
820
+ task: ctx.task,
821
+ currentPhase: ctx.currentPhase,
822
+ phaseStatus: ctx.phaseStatus,
823
+ updatedAt: ctx.updatedAt
824
+ });
825
+ }
826
+
827
+ return summaries;
828
+ } catch {
829
+ return [];
830
+ }
831
+ }
832
+
833
+ async delete(id: string): Promise<void> {
834
+ const fs = require('fs').promises;
835
+ const path = require('path');
836
+
837
+ const filePath = path.join(this.storagePath, `${id}.json`);
838
+ await fs.unlink(filePath);
839
+ }
840
+
841
+ private serialize(context: WorkflowContext) {
842
+ return {
843
+ ...context,
844
+ artifacts: Array.from(context.artifacts.entries()),
845
+ userConfirmed: Array.from(context.userConfirmed.values())
846
+ };
847
+ }
848
+
849
+ private deserialize(raw: any): WorkflowContext {
850
+ return {
851
+ ...raw,
852
+ artifacts: new Map(raw.artifacts || []),
853
+ userConfirmed: new Set(raw.userConfirmed || []),
854
+ startedAt: new Date(raw.startedAt),
855
+ updatedAt: new Date(raw.updatedAt)
856
+ };
857
+ }
858
+ }
859
+ ```
860
+
861
+ ### 8.5 工作流 CLI 交互
862
+
863
+ ```typescript
864
+ // src/cli/commands/workflow.ts
865
+
866
+ import { WorkflowOrchestrator } from '../../orchestrator/workflow/workflow-orchestrator';
867
+ import { Command } from 'commander';
868
+
869
+ const workflow = new Command('workflow').description('Workflow management');
870
+
871
+ workflow.command('start')
872
+ .description('Start a new development workflow')
873
+ .argument('<task>', 'Task description')
874
+ .action(async (task: string) => {
875
+ const orchestrator = new WorkflowOrchestrator();
876
+ const context = await orchestrator.start(task);
877
+
878
+ console.log(`
879
+ [WORKFLOW STARTED]
880
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
881
+
882
+ Task: ${task}
883
+ ID: ${context.id}
884
+ Phase: ${context.currentPhase}
885
+
886
+ Next steps:
887
+ 1. codemap workflow status # 查看当前状态
888
+ 2. codemap analyze --intent reference --keywords ...
889
+ 3. codemap workflow proceed # 进入下一阶段
890
+ `);
891
+ });
892
+
893
+ workflow.command('status')
894
+ .description('Show current workflow status')
895
+ .action(async () => {
896
+ const orchestrator = new WorkflowOrchestrator();
897
+ const status = await orchestrator.getStatus();
898
+
899
+ if (!status.active) {
900
+ console.log('No active workflow. Run "codemap workflow start" first.');
901
+ return;
902
+ }
903
+
904
+ console.log(`
905
+ [WORKFLOW STATUS]
906
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
907
+
908
+ Task: ${status.task}
909
+ Phase: ${status.currentPhase}
910
+ Status: ${status.phaseStatus}
911
+ Progress: ${status.progress.toFixed(0)}%
912
+
913
+ Completed phases: ${status.artifacts?.join(', ') || 'none'}
914
+ `);
915
+ });
916
+
917
+ workflow.command('visualize')
918
+ .description('Visualize current workflow status')
919
+ .action(async () => {
920
+ // 读取活动工作流并渲染 ASCII 视图
921
+ });
922
+
923
+ workflow.command('template')
924
+ .description('Workflow template management')
925
+ .command('apply <name>')
926
+ .action(async (name: string) => {
927
+ // 对活动工作流应用模板并持久化
928
+ });
929
+
930
+ workflow.command('proceed')
931
+ .description('Proceed to next phase')
932
+ .option('-f, --force', 'Skip verification')
933
+ .action(async (options) => {
934
+ const orchestrator = new WorkflowOrchestrator();
935
+ const status = await orchestrator.getStatus();
936
+
937
+ if (!status.active) {
938
+ console.log('No active workflow.');
939
+ return;
940
+ }
941
+
942
+ if (status.phaseStatus !== 'completed' && !options.force) {
943
+ console.log(`Current phase ${status.currentPhase} is not completed. Use --force to override.`);
944
+ return;
945
+ }
946
+
947
+ const next = await orchestrator.proceedToNextPhase();
948
+
949
+ console.log(`
950
+ [PHASE COMPLETED]
951
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
952
+
953
+ Current phase: ${status.currentPhase}
954
+ Status: ${status.phaseStatus}
955
+ Next phase: ${next}
956
+
957
+ Type "codemap workflow proceed" to continue to next phase.
958
+ `);
959
+ });
960
+
961
+ export default workflow;
962
+ ```
963
+
964
+ ### 8.6 阶段连接机制
965
+
966
+ #### 检查点验证
967
+
968
+ ```typescript
969
+ // 每个阶段结束时验证交付物
970
+
971
+ class PhaseCheckpoint {
972
+ /**
973
+ * 验证阶段交付物
974
+ */
975
+ async validate(phase: WorkflowPhase, artifacts: PhaseArtifacts): Promise<CheckpointResult> {
976
+ const definition = this.getPhaseDefinition(phase);
977
+ const results: CheckItem[] = [];
978
+
979
+ for (const deliverable of definition.deliverables) {
980
+ const exists = await this.checkFileExists(deliverable.path);
981
+ const valid = deliverable.validator(deliverable.path);
982
+
983
+ results.push({
984
+ name: deliverable.name,
985
+ path: deliverable.path,
986
+ exists,
987
+ valid
988
+ });
989
+ }
990
+
991
+ return {
992
+ passed: results.every(r => r.exists && r.valid),
993
+ items: results
994
+ };
995
+ }
996
+ }
997
+ ```
998
+
999
+ #### 置信度引导
1000
+
1001
+ ```typescript
1002
+ // 根据置信度决定是否自动推进或等待用户确认
1003
+
1004
+ class ConfidenceGuide {
1005
+ /**
1006
+ * 获取置信度指导建议
1007
+ */
1008
+ getGuidance(confidence: ConfidenceResult, phase: WorkflowPhase): Guidance {
1009
+ if (confidence.level === 'high') {
1010
+ return {
1011
+ action: 'auto-proceed',
1012
+ message: `High confidence (${confidence.score.toFixed(2)}), proceeding to next phase...`
1013
+ };
1014
+ }
1015
+
1016
+ if (confidence.level === 'medium') {
1017
+ return {
1018
+ action: 'confirm-proceed',
1019
+ message: `Medium confidence (${confidence.score.toFixed(2)}), review results before proceeding?`,
1020
+ suggestion: 'Run additional analysis with broader scope'
1021
+ };
1022
+ }
1023
+
1024
+ return {
1025
+ action: 'hold',
1026
+ message: `Low confidence (${confidence.score.toFixed(2)}), current phase needs more work`,
1027
+ suggestion: confidence.reasons.join('; ')
1028
+ };
1029
+ }
1030
+ }
1031
+ ```
1032
+
1033
+ ### 8.7 模块依赖图
1034
+
1035
+ ```
1036
+ 工作流编排器 (workflow-orchestrator.ts)
1037
+
1038
+ ├── 依赖: IntentRouter (intent-router.ts)
1039
+ ├── 依赖: ToolOrchestrator (tool-orchestrator.ts)
1040
+ ├── 依赖: ConfidenceCalculator (confidence.ts)
1041
+ ├── 依赖: ResultFusion (result-fusion.ts)
1042
+ ├── 依赖: GitAnalyzer (git-analyzer.ts)
1043
+ ├── 依赖: AIFeedGenerator (ai-feed-generator.ts)
1044
+ ├── 依赖: TestLinker (test-linker.ts)
1045
+
1046
+ └── 被以下模块使用:
1047
+ └── CLI Commands (workflow.ts)
1048
+ ```
1049
+
1050
+ ### 8.8 配置扩展
1051
+
1052
+ ```json
1053
+ {
1054
+ "workflow": {
1055
+ "enabled": true,
1056
+ "autoProceedThreshold": 0.7,
1057
+ "persistencePath": ".codemap/workflow",
1058
+ "phases": {
1059
+ "reference": { "minConfidence": 0.3 },
1060
+ "impact": { "minConfidence": 0.4 },
1061
+ "risk": { "minConfidence": 0 }
1062
+ }
1063
+ }
1064
+ }
1065
+ ```