autosnippet 3.2.7 → 3.2.9

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 (147) hide show
  1. package/bin/cli.js +13 -5
  2. package/dashboard/dist/assets/index-BTAsOZv2.js +128 -0
  3. package/dashboard/dist/assets/index-C_72Ct98.css +1 -0
  4. package/dashboard/dist/index.html +2 -2
  5. package/lib/cli/AiScanService.js +26 -29
  6. package/lib/cli/SetupService.js +1 -1
  7. package/lib/core/AstAnalyzer.js +27 -5
  8. package/lib/core/analysis/CallEdgeResolver.js +402 -0
  9. package/lib/core/analysis/CallGraphAnalyzer.js +367 -0
  10. package/lib/core/analysis/CallSiteExtractor.js +629 -0
  11. package/lib/core/analysis/DataFlowInferrer.js +57 -0
  12. package/lib/core/analysis/ImportPathResolver.js +189 -0
  13. package/lib/core/analysis/ImportRecord.js +105 -0
  14. package/lib/core/analysis/SymbolTableBuilder.js +211 -0
  15. package/lib/core/ast/ProjectGraph.js +8 -0
  16. package/lib/core/ast/lang-dart.js +352 -5
  17. package/lib/core/ast/lang-go.js +212 -10
  18. package/lib/core/ast/lang-java.js +205 -1
  19. package/lib/core/ast/lang-kotlin.js +330 -1
  20. package/lib/core/ast/lang-python.js +31 -2
  21. package/lib/core/ast/lang-rust.js +284 -3
  22. package/lib/core/ast/lang-swift.js +180 -1
  23. package/lib/core/ast/lang-typescript.js +290 -1
  24. package/lib/core/discovery/index.js +2 -2
  25. package/lib/external/ai/AiProvider.js +66 -172
  26. package/lib/external/ai/providers/GoogleGeminiProvider.js +23 -1
  27. package/lib/external/mcp/McpServer.js +1 -0
  28. package/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +1 -1
  29. package/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.js +3 -3
  30. package/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +22 -1
  31. package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +1 -1
  32. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +2 -1
  33. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +8 -8
  34. package/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +1 -1
  35. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +311 -162
  36. package/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +102 -7
  37. package/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.js +1 -1
  38. package/lib/external/mcp/handlers/bootstrap-external.js +9 -2
  39. package/lib/external/mcp/handlers/bootstrap-internal.js +19 -8
  40. package/lib/external/mcp/handlers/consolidated.js +9 -0
  41. package/lib/external/mcp/handlers/dimension-complete-external.js +6 -6
  42. package/lib/external/mcp/handlers/guard.js +3 -3
  43. package/lib/external/mcp/handlers/structure.js +62 -0
  44. package/lib/external/mcp/handlers/wiki-external.js +66 -3
  45. package/lib/external/mcp/tools.js +36 -1
  46. package/lib/http/HttpServer.js +1 -1
  47. package/lib/http/middleware/requestLogger.js +1 -0
  48. package/lib/http/routes/ai.js +240 -35
  49. package/lib/http/routes/candidates.js +2 -3
  50. package/lib/http/routes/extract.js +13 -11
  51. package/lib/http/routes/modules.js +2 -2
  52. package/lib/http/routes/recipes.js +9 -5
  53. package/lib/http/routes/remote.js +149 -270
  54. package/lib/http/routes/violations.js +0 -54
  55. package/lib/http/utils/sse-sessions.js +1 -1
  56. package/lib/infrastructure/logging/Logger.js +5 -4
  57. package/lib/infrastructure/monitoring/PerformanceMonitor.js +3 -2
  58. package/lib/injection/ServiceContainer.js +70 -28
  59. package/lib/platform/ScreenCaptureService.js +177 -0
  60. package/lib/platform/ios/index.js +2 -2
  61. package/lib/platform/ios/routes/spm.js +2 -2
  62. package/lib/platform/ios/spm/PackageSwiftParser.js +14 -3
  63. package/lib/platform/ios/spm/SpmDiscoverer.js +123 -17
  64. package/lib/platform/ios/spm/{SpmService.js → SpmHelper.js} +43 -675
  65. package/lib/platform/ios/xcode/XcodeWriteUtils.js +1 -1
  66. package/lib/service/agent/AgentEventBus.js +207 -0
  67. package/lib/service/agent/AgentFactory.js +490 -0
  68. package/lib/service/agent/AgentMessage.js +240 -0
  69. package/lib/service/agent/AgentRouter.js +228 -0
  70. package/lib/service/agent/AgentRuntime.js +1016 -0
  71. package/lib/service/agent/AgentState.js +217 -0
  72. package/lib/service/agent/IntentClassifier.js +331 -0
  73. package/lib/service/agent/LarkTransport.js +389 -0
  74. package/lib/service/agent/capabilities.js +408 -0
  75. package/lib/service/{chat → agent/context}/ContextWindow.js +37 -12
  76. package/lib/service/{chat → agent/context}/ExplorationTracker.js +77 -22
  77. package/lib/service/{chat → agent/core}/ChatAgentPrompts.js +14 -2
  78. package/lib/service/agent/core/LoopContext.js +170 -0
  79. package/lib/service/agent/core/MessageAdapter.js +223 -0
  80. package/lib/service/agent/core/ToolExecutionPipeline.js +376 -0
  81. package/lib/service/{chat → agent/domain}/ChatAgentTasks.js +19 -98
  82. package/lib/service/{chat → agent/domain}/EpisodicConsolidator.js +7 -7
  83. package/lib/service/{chat → agent/domain}/EvidenceCollector.js +4 -2
  84. package/lib/service/{chat/AnalystAgent.js → agent/domain/insight-analyst.js} +37 -172
  85. package/lib/service/{chat/HandoffProtocol.js → agent/domain/insight-gate.js} +91 -123
  86. package/lib/service/agent/domain/insight-producer.js +267 -0
  87. package/lib/service/agent/domain/scan-prompts.js +105 -0
  88. package/lib/service/agent/forced-summary.js +266 -0
  89. package/lib/service/agent/index.js +91 -0
  90. package/lib/service/{chat → agent}/memory/ActiveContext.js +3 -1
  91. package/lib/service/{chat → agent}/memory/MemoryCoordinator.js +7 -7
  92. package/lib/service/{chat/ProjectSemanticMemory.js → agent/memory/PersistentMemory.js} +359 -89
  93. package/lib/service/{chat → agent}/memory/SessionStore.js +5 -4
  94. package/lib/service/{chat → agent}/memory/index.js +1 -1
  95. package/lib/service/agent/policies.js +442 -0
  96. package/lib/service/agent/presets.js +303 -0
  97. package/lib/service/agent/strategies.js +717 -0
  98. package/lib/service/{chat → agent/tools}/ToolRegistry.js +3 -3
  99. package/lib/service/agent/tools/ai-analysis.js +75 -0
  100. package/lib/service/{chat → agent}/tools/ast-graph.js +229 -32
  101. package/lib/service/{chat → agent}/tools/composite.js +2 -1
  102. package/lib/service/{chat → agent}/tools/guard.js +1 -121
  103. package/lib/service/{chat → agent}/tools/index.js +33 -22
  104. package/lib/service/{chat → agent}/tools/infrastructure.js +6 -1
  105. package/lib/service/agent/tools/knowledge-graph.js +112 -0
  106. package/lib/service/agent/tools/scan-recipe.js +189 -0
  107. package/lib/service/agent/tools/system-interaction.js +476 -0
  108. package/lib/service/automation/DirectiveDetector.js +0 -1
  109. package/lib/service/automation/FileWatcher.js +0 -8
  110. package/lib/service/automation/handlers/CreateHandler.js +7 -3
  111. package/lib/service/automation/handlers/DraftHandler.js +7 -6
  112. package/lib/service/cursor/CursorDeliveryPipeline.js +167 -1
  113. package/lib/service/knowledge/CodeEntityGraph.js +327 -2
  114. package/lib/service/knowledge/KnowledgeService.js +5 -1
  115. package/lib/service/module/ModuleService.js +49 -73
  116. package/lib/service/skills/SignalCollector.js +26 -19
  117. package/lib/service/snippet/codecs/VSCodeCodec.js +1 -1
  118. package/lib/service/wiki/WikiGenerator.js +1 -1
  119. package/lib/shared/FieldSpec.js +1 -1
  120. package/lib/shared/PathGuard.js +1 -1
  121. package/lib/shared/StyleGuide.js +1 -1
  122. package/package.json +4 -1
  123. package/resources/native-ui/screenshot.swift +228 -0
  124. package/dashboard/dist/assets/index-BaGY7kJI.css +0 -1
  125. package/dashboard/dist/assets/index-DfHY_3ln.js +0 -128
  126. package/lib/core/discovery/SpmDiscoverer.js +0 -5
  127. package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +0 -749
  128. package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +0 -277
  129. package/lib/http/routes/spm.js +0 -5
  130. package/lib/infrastructure/external/XcodeAutomation.js +0 -15
  131. package/lib/service/chat/ChatAgent.js +0 -1602
  132. package/lib/service/chat/Memory.js +0 -161
  133. package/lib/service/chat/ProducerAgent.js +0 -431
  134. package/lib/service/chat/ReasoningTrace.js +0 -523
  135. package/lib/service/chat/TaskPipeline.js +0 -357
  136. package/lib/service/chat/WorkingMemory.js +0 -357
  137. package/lib/service/chat/memory/PersistentMemory.js +0 -450
  138. package/lib/service/chat/tools/ai-analysis.js +0 -267
  139. package/lib/service/chat/tools/knowledge-graph.js +0 -234
  140. package/lib/service/chat/tools.js +0 -18
  141. package/lib/service/snippet/PlaceholderConverter.js +0 -5
  142. package/lib/service/snippet/codecs/XcodeCodec.js +0 -5
  143. /package/lib/service/{chat → agent}/ConversationStore.js +0 -0
  144. /package/lib/service/{chat → agent}/tools/_shared.js +0 -0
  145. /package/lib/service/{chat → agent}/tools/lifecycle.js +0 -0
  146. /package/lib/service/{chat → agent}/tools/project-access.js +0 -0
  147. /package/lib/service/{chat → agent}/tools/query.js +0 -0
@@ -4,11 +4,11 @@
4
4
  * ⚠️ 本文件是「内部 Agent」专用 — 由 bootstrap.js Phase 5 调用。
5
5
  * 外部 Agent (Cursor/Copilot) 不经过此管线,它们自行分析代码。
6
6
  *
7
- * 核心架构: AnalystGateProducer (双 Agent 模式)
7
+ * 核心架构: PipelineStrategy 驱动 (Analyze QualityGateProduce RejectionGate)
8
8
  *
9
- * 1. Analyst Agent 自由探索代码 (AST 工具 + 文件搜索)
10
- * 2. HandoffProtocol 质量门控
11
- * 3. Producer Agent 格式化输出 (submit_knowledge)
9
+ * 1. Analyze 阶段: 自由探索代码 (AST 工具 + 文件搜索)
10
+ * 2. QualityGate: 质量门控 (insightGateEvaluator)
11
+ * 3. Produce 阶段: 格式化输出 (submit_knowledge)
12
12
  * 4. TierScheduler 分层并行执行
13
13
  *
14
14
  * @module pipeline/orchestrator
@@ -17,12 +17,15 @@
17
17
  import fs from 'node:fs/promises';
18
18
  import path from 'node:path';
19
19
  import Logger from '../../../../../infrastructure/logging/Logger.js';
20
- import { AnalystAgent } from '../../../../../service/chat/AnalystAgent.js';
21
- import { EpisodicConsolidator } from '../../../../../service/chat/EpisodicConsolidator.js';
22
- import { ProducerAgent } from '../../../../../service/chat/ProducerAgent.js';
23
- import { ProjectSemanticMemory } from '../../../../../service/chat/ProjectSemanticMemory.js';
24
- import { MemoryCoordinator } from '../../../../../service/chat/memory/MemoryCoordinator.js';
25
- import { SessionStore } from '../../../../../service/chat/memory/SessionStore.js';
20
+ import { EpisodicConsolidator } from '../../../../../service/agent/domain/EpisodicConsolidator.js';
21
+ import { PersistentMemory } from '../../../../../service/agent/memory/PersistentMemory.js';
22
+ import { MemoryCoordinator } from '../../../../../service/agent/memory/MemoryCoordinator.js';
23
+ import { SessionStore } from '../../../../../service/agent/memory/SessionStore.js';
24
+ import { AgentMessage } from '../../../../../service/agent/AgentMessage.js';
25
+ import { BudgetPolicy } from '../../../../../service/agent/policies.js';
26
+ import { PRESETS } from '../../../../../service/agent/presets.js';
27
+ import { ContextWindow } from '../../../../../service/agent/context/ContextWindow.js';
28
+ import { ExplorationTracker } from '../../../../../service/agent/context/ExplorationTracker.js';
26
29
  import { clearCheckpoints, loadCheckpoints, saveDimensionCheckpoint } from './checkpoint.js';
27
30
  import { buildTierReflection, DIMENSION_CONFIGS_V3, getFullDimensionConfig } from './dimension-configs.js';
28
31
  import { getDimensionFocusKeywords } from '../shared/dimension-sop.js';
@@ -61,30 +64,29 @@ export async function fillDimensionsV3(fillContext) {
61
64
  const isIncremental = incrementalPlan?.canIncremental && incrementalPlan?.mode === 'incremental';
62
65
  const emitter = new BootstrapEventEmitter(ctx.container);
63
66
  logger.info(
64
- `[Bootstrap-v3] ═══ fillDimensionsV3 entered — ${isIncremental ? 'INCREMENTAL' : 'FULL'} pipeline`
67
+ `[Insight-v3] ═══ fillDimensionsV3 entered — ${isIncremental ? 'INCREMENTAL' : 'FULL'} pipeline`
65
68
  );
66
69
 
67
70
  let allFiles = fillContext.allFiles;
68
71
  fillContext.allFiles = null;
69
72
 
70
73
  // ═══════════════════════════════════════════════════════════
71
- // Step 0: AI 可用性检查
74
+ // Step 0: AI 可用性检查 (v7.2: 使用 AgentFactory)
72
75
  // ═══════════════════════════════════════════════════════════
73
- let chatAgent = null;
76
+ let agentFactory = null;
74
77
  try {
75
- chatAgent = ctx.container.get('chatAgent');
76
- if (chatAgent && !chatAgent.hasRealAI) {
77
- chatAgent = null;
78
- }
79
- if (chatAgent) {
80
- chatAgent.resetGlobalSubmittedTitles();
78
+ agentFactory = ctx.container.get('agentFactory');
79
+ // 检查 AI Provider 是否可用
80
+ const aiProvider = ctx.container.singletons?.aiProvider;
81
+ if (!aiProvider || aiProvider.name === 'mock') {
82
+ agentFactory = null;
81
83
  }
82
84
  } catch {
83
85
  /* not available */
84
86
  }
85
87
 
86
- if (!chatAgent) {
87
- logger.info('[Bootstrap-v3] AI not available — entering rule-based fallback');
88
+ if (!agentFactory) {
89
+ logger.info('[Insight-v3] AI not available — entering rule-based fallback');
88
90
  emitter.emitProgress('bootstrap:ai-unavailable', {
89
91
  message: 'AI 不可用,将使用规则化降级提取基础知识。请配置 AI Provider 以获取完整分析。',
90
92
  });
@@ -247,21 +249,20 @@ export async function fillDimensionsV3(fillContext) {
247
249
  if (projectGraph) {
248
250
  const overview = projectGraph.getOverview();
249
251
  logger.info(
250
- `[Bootstrap-v3] ProjectGraph: ${overview.totalClasses} classes, ${overview.totalProtocols} protocols (${overview.buildTimeMs}ms)`
252
+ `[Insight-v3] ProjectGraph: ${overview.totalClasses} classes, ${overview.totalProtocols} protocols (${overview.buildTimeMs}ms)`
251
253
  );
252
254
  }
253
255
  } catch (e) {
254
- logger.warn(`[Bootstrap-v3] ProjectGraph build failed: ${e.message}`);
256
+ logger.warn(`[Insight-v3] ProjectGraph build failed: ${e.message}`);
255
257
  }
256
258
 
257
259
  // ═══════════════════════════════════════════════════════════
258
260
  // Step 1: 构建 Agents + 上下文
259
261
  // ═══════════════════════════════════════════════════════════
260
- const analystAgent = new AnalystAgent(chatAgent, projectGraph, { maxRetries: 1 });
261
- const producerAgent = new ProducerAgent(chatAgent);
262
+ logger.info('[Insight-v7] Using unified AgentRuntime pipeline (no legacy Analyst/Producer wrappers)');
262
263
 
263
- // 注入文件缓存
264
- chatAgent.setFileCache(allFiles);
264
+ // 注入文件缓存到容器 (v7.2: 通过容器传递)
265
+ ctx.container.singletons._fileCache = allFiles;
265
266
 
266
267
  // 项目信息
267
268
  const projectInfo = {
@@ -289,7 +290,7 @@ export async function fillDimensionsV3(fillContext) {
289
290
  sessionStore = incrementalPlan.restoredEpisodic;
290
291
  const restoredDims = sessionStore.getCompletedDimensions();
291
292
  logger.info(
292
- `[Bootstrap-v3] Restored SessionStore: ${restoredDims.length} dims [${restoredDims.join(', ')}]`
293
+ `[Insight-v3] Restored SessionStore: ${restoredDims.length} dims [${restoredDims.join(', ')}]`
293
294
  );
294
295
 
295
296
  // 同步恢复 DimensionContext 的 digests (兼容)
@@ -308,23 +309,23 @@ export async function fillDimensionsV3(fillContext) {
308
309
  });
309
310
  }
310
311
 
311
- // v4.1: ProjectSemanticMemory — 项目级永久语义记忆 (Tier 3)
312
- // 加载历史 bootstrap 记忆 → 注入 AnalystAgent prompt
312
+ // v4.1: PersistentMemory — 项目级永久语义记忆 (Tier 3)
313
+ // 加载历史 bootstrap 记忆 → 注入 Analyst promptBuilder
313
314
  let semanticMemory = null;
314
315
  try {
315
316
  const db = ctx.container.get('database');
316
317
  if (db) {
317
- semanticMemory = new ProjectSemanticMemory(db, { logger });
318
+ semanticMemory = new PersistentMemory(db, { logger });
318
319
  const smStats = semanticMemory.getStats();
319
320
  if (smStats.total > 0) {
320
321
  logger.info(
321
- `[Bootstrap-v3] Loaded ${smStats.total} semantic memories from previous bootstrap ` +
322
+ `[Insight-v3] Loaded ${smStats.total} semantic memories from previous bootstrap ` +
322
323
  `(fact: ${smStats.byType.fact || 0}, insight: ${smStats.byType.insight || 0}, preference: ${smStats.byType.preference || 0})`
323
324
  );
324
325
  }
325
326
  }
326
327
  } catch (smErr) {
327
- logger.warn(`[Bootstrap-v3] SemanticMemory init failed (non-blocking): ${smErr.message}`);
328
+ logger.warn(`[Insight-v3] SemanticMemory init failed (non-blocking): ${smErr.message}`);
328
329
  }
329
330
 
330
331
  // Phase E: CodeEntityGraph — 代码实体关系图谱 (供 Analyst prompt 注入)
@@ -337,12 +338,12 @@ export async function fillDimensionsV3(fillContext) {
337
338
  const topo = codeEntityGraphInst.getTopology();
338
339
  if (topo.totalEntities > 0) {
339
340
  logger.info(
340
- `[Bootstrap-v3] CodeEntityGraph: ${topo.totalEntities} entities, ${topo.totalEdges} edges`
341
+ `[Insight-v3] CodeEntityGraph: ${topo.totalEntities} entities, ${topo.totalEdges} edges`
341
342
  );
342
343
  }
343
344
  }
344
345
  } catch (cegErr) {
345
- logger.warn(`[Bootstrap-v3] CodeEntityGraph init failed (non-blocking): ${cegErr.message}`);
346
+ logger.warn(`[Insight-v3] CodeEntityGraph init failed (non-blocking): ${cegErr.message}`);
346
347
  }
347
348
 
348
349
  // v5.0: MemoryCoordinator — 统一记忆协调器 (会话级)
@@ -378,14 +379,14 @@ export async function fillDimensionsV3(fillContext) {
378
379
  }
379
380
  if (incrementalSkippedDims.length > 0) {
380
381
  logger.info(
381
- `[Bootstrap-v3] ⏩ Incremental skip: [${incrementalSkippedDims.join(', ')}] ` +
382
+ `[Insight-v3] ⏩ Incremental skip: [${incrementalSkippedDims.join(', ')}] ` +
382
383
  `(using historical results)`
383
384
  );
384
385
  }
385
386
  }
386
387
 
387
388
  logger.info(
388
- `[Bootstrap-v3] Active dimensions: [${activeDimIds.join(', ')}], concurrency=${enableParallel ? concurrency : 1}${isIncremental ? `, incremental skip: [${incrementalSkippedDims.join(', ')}]` : ''}`
389
+ `[Insight-v3] Active dimensions: [${activeDimIds.join(', ')}], concurrency=${enableParallel ? concurrency : 1}${isIncremental ? `, incremental skip: [${incrementalSkippedDims.join(', ')}]` : ''}`
389
390
  );
390
391
 
391
392
  // ── P3: 断点续传 — 加载有效 checkpoints ──
@@ -404,7 +405,7 @@ export async function fillDimensionsV3(fillContext) {
404
405
  ...checkpoint,
405
406
  });
406
407
  skippedDims.push(dimId);
407
- logger.info(`[Bootstrap-v3] ⏩ 跳过已完成维度 (checkpoint): "${dimId}"`);
408
+ logger.info(`[Insight-v3] ⏩ 跳过已完成维度 (checkpoint): "${dimId}"`);
408
409
  }
409
410
  }
410
411
 
@@ -412,6 +413,10 @@ export async function fillDimensionsV3(fillContext) {
412
413
  const dimensionCandidates = {};
413
414
  const dimensionStats = {}; // P4.2: 维度级统计
414
415
 
416
+ // ── 跨维度去重集合 (实例级持久化,等效旧 ChatAgent.#globalSubmittedTitles/Patterns) ──
417
+ const globalSubmittedTitles = new Set();
418
+ const globalSubmittedPatterns = new Set();
419
+
415
420
  /**
416
421
  * 执行单个维度: Analyst → Gate → Producer
417
422
  */
@@ -432,7 +437,7 @@ export async function fillDimensionsV3(fillContext) {
432
437
  restoredFromIncremental: true,
433
438
  };
434
439
  dimensionStats[dimId] = dimResult;
435
- logger.info(`[Bootstrap-v3] ⏩ "${dimId}" — incremental skip (historical result)`);
440
+ logger.info(`[Insight-v3] ⏩ "${dimId}" — incremental skip (historical result)`);
436
441
  return dimResult;
437
442
  }
438
443
 
@@ -472,7 +477,7 @@ export async function fillDimensionsV3(fillContext) {
472
477
  candidatesSummary: [],
473
478
  });
474
479
  logger.info(
475
- `[Bootstrap-v3] ✅ Checkpoint "${dimId}": analysisText restored (${cp.analysisText.length} chars) — Skill generation enabled`
480
+ `[Insight-v3] ✅ Checkpoint "${dimId}": analysisText restored (${cp.analysisText.length} chars) — Skill generation enabled`
476
481
  );
477
482
  }
478
483
 
@@ -521,110 +526,259 @@ export async function fillDimensionsV3(fillContext) {
521
526
 
522
527
  // Session 有效性检查
523
528
  if (taskManager && !taskManager.isSessionValid(sessionId)) {
524
- logger.warn(`[Bootstrap-v3] Session superseded — skipping "${dimId}"`);
529
+ logger.warn(`[Insight-v3] Session superseded — skipping "${dimId}"`);
525
530
  return { candidateCount: 0, error: 'session-superseded' };
526
531
  }
527
532
 
528
533
  emitter.emitDimensionStart(dimId);
529
- logger.info(`[Bootstrap-v3] ── Dimension "${dimId}" (${dimConfig.label}) ──`);
534
+ logger.info(`[Insight-v3] ── Dimension "${dimId}" (${dimConfig.label}) ──`);
530
535
 
531
536
  const dimStartTime = Date.now();
532
537
 
533
538
  try {
534
- // v5.0: 为每个维度创建独立的 ActiveContext 作用域
539
+ // ═══ v3.0: 增强 PipelineStrategy 驱动 ═══
535
540
  const analystScopeId = `${dimId}:analyst`;
536
541
  memoryCoordinator.createDimensionScope(analystScopeId);
537
542
 
538
- // ── Phase 1: Analyst ──
539
- const analysisReport = await Promise.race([
540
- analystAgent.analyze(dimConfig, projectInfo, {
541
- sessionId,
542
- dimensionContext: dimContext,
543
- // v5.0: 统一 MemoryCoordinator
544
- memoryCoordinator,
545
- // v4.1: Semantic Memory (历史 bootstrap 记忆)
546
- semanticMemory,
547
- // Phase E: Code Entity Graph 代码实体图谱
548
- codeEntityGraph: codeEntityGraphInst,
549
- }),
543
+ const v3OutputType = DIMENSION_CONFIGS_V3[dimId]?.outputType;
544
+ const needsCandidates = v3OutputType
545
+ ? v3OutputType !== 'skill'
546
+ : !dimConfig.skillWorthy || dimConfig.dualOutput;
547
+
548
+ // ── 获取 Preset 的标准 stages 配置作为基础 ──
549
+ const presetStages = PRESETS.insight.strategy.stages;
550
+
551
+ // ── 构建 per-dimension 的 stages ──
552
+ // NOTE: onToolCall 不再注入 ac.recordToolCall — ToolExecutionPipeline 的
553
+ // traceRecord 中间件已通过 loopCtx.trace 统一记录,避免同一 AC 上双重记录。
554
+ const analyzeStage = {
555
+ ...presetStages[0],
556
+ };
557
+
558
+ let stages;
559
+ if (needsCandidates) {
560
+ // 候选维度: Analyze→QualityGate→Produce→RejectionGate
561
+ const produceStage = {
562
+ ...presetStages[2],
563
+ promptBuilder: (ctx) => {
564
+ memoryCoordinator.allocateBudget('producer');
565
+ return presetStages[2].promptBuilder(ctx);
566
+ },
567
+ };
568
+ stages = [
569
+ analyzeStage,
570
+ presetStages[1], // quality_gate
571
+ produceStage,
572
+ presetStages[3], // rejection_gate
573
+ ];
574
+ } else {
575
+ // Skill-only 维度: 仅 Analyze
576
+ stages = [analyzeStage];
577
+ }
578
+
579
+ // ── 创建 Runtime (使用增强 PipelineStrategy) ──
580
+ const runtime = agentFactory.createRuntime('insight', {
581
+ lang: primaryLang || projectInfo.lang || null,
582
+ strategy: {
583
+ type: 'pipeline',
584
+ maxRetries: 1,
585
+ stages,
586
+ },
587
+ });
588
+ runtime.setFileCache(allFiles);
589
+
590
+ // ── 构建消息 + strategyContext ──
591
+ const message = AgentMessage.internal(`Bootstrap dimension: ${dimConfig.label}`, {
592
+ sessionId,
593
+ dimension: dimId,
594
+ phase: 'bootstrap',
595
+ });
596
+
597
+ const strategyContext = {
598
+ dimConfig,
599
+ projectInfo,
600
+ dimContext,
601
+ sessionStore,
602
+ semanticMemory,
603
+ codeEntityGraph: codeEntityGraphInst,
604
+ projectGraph: null, // ProjectGraph 在 orchestrator 级别可用时注入
605
+ dimId,
606
+ activeContext: memoryCoordinator.getActiveContext(analystScopeId),
607
+ outputType: dimConfig.outputType || 'analysis',
608
+ // ── 引擎增强参数 (PipelineStrategy → reactLoop 透传) ──
609
+ contextWindow: agentFactory.createContextWindow({ isSystem: true }),
610
+ tracker: ExplorationTracker.resolve(
611
+ { source: 'system', dimensionMeta: dimConfig },
612
+ { maxIterations: PRESETS.insight.strategy.stages[0].budget?.maxIterations || 24 },
613
+ ),
614
+ trace: memoryCoordinator.getActiveContext(analystScopeId),
615
+ memoryCoordinator,
616
+ sharedState: {
617
+ submittedTitles: globalSubmittedTitles,
618
+ submittedPatterns: globalSubmittedPatterns,
619
+ _dimensionMeta: {
620
+ id: dimId,
621
+ outputType: dimConfig.outputType || 'candidate',
622
+ allowedKnowledgeTypes: dimConfig.allowedKnowledgeTypes || [],
623
+ },
624
+ _projectLanguage: primaryLang || projectInfo.lang || null,
625
+ _dimensionScopeId: analystScopeId,
626
+ },
627
+ source: 'system',
628
+ };
629
+
630
+ // ── 执行 ──
631
+ // 外层超时 = 安全网 (各阶段已有独立超时: Analyst 300s + Producer 180s + 硬缓冲 60s)
632
+ const outerTimeoutMs = 600_000;
633
+ const runResult = await Promise.race([
634
+ runtime.execute(message, { strategyContext }),
550
635
  new Promise((_, reject) =>
551
- setTimeout(() => reject(new Error(`Analyst timeout for "${dimId}"`)), 300_000)
636
+ setTimeout(() => reject(new Error(`Bootstrap runtime timeout for "${dimId}"`)), outerTimeoutMs),
552
637
  ),
553
638
  ]);
554
639
 
555
- // v5.0: 通过 coordinator 蒸馏 ActiveContext → SessionStore
640
+ // ── 提取结果 ──
641
+ const analyzeResult = runResult?.phases?.analyze;
642
+ const gateResult = runResult?.phases?.quality_gate;
643
+ const produceResult = runResult?.phases?.produce;
644
+ const analysisText = (analyzeResult?.reply || runResult?.reply || '').trim();
645
+ const artifact = gateResult?.artifact || {
646
+ analysisText,
647
+ referencedFiles: [],
648
+ findings: [],
649
+ metadata: { toolCallCount: 0 },
650
+ };
651
+
652
+ const runtimeToolCalls = runResult?.toolCalls || [];
653
+ const combinedTokenUsage = runResult?.tokenUsage || { input: 0, output: 0 };
654
+
655
+ // 引用文件: 优先从 artifact 取, 回退从 toolCalls 提取
656
+ const referencedFiles = artifact.referencedFiles?.length > 0
657
+ ? artifact.referencedFiles
658
+ : [...new Set(runtimeToolCalls.flatMap((tc) => {
659
+ const a = tc?.args || tc?.params || {};
660
+ const files = [];
661
+ if (typeof a.filePath === 'string' && a.filePath.trim()) files.push(a.filePath.trim());
662
+ if (Array.isArray(a.filePaths)) {
663
+ for (const f of a.filePaths) {
664
+ if (typeof f === 'string' && f.trim()) files.push(f.trim());
665
+ }
666
+ }
667
+ return files;
668
+ }))];
669
+
670
+ const analysisReport = {
671
+ dimensionId: dimId,
672
+ analysisText: artifact.analysisText || analysisText,
673
+ findings: artifact.findings || [],
674
+ referencedFiles,
675
+ evidenceMap: artifact.evidenceMap || null,
676
+ negativeSignals: artifact.negativeSignals || [],
677
+ metadata: {
678
+ toolCallCount: runtimeToolCalls.length,
679
+ tokenUsage: combinedTokenUsage,
680
+ artifactVersion: artifact.metadata?.artifactVersion || 1,
681
+ },
682
+ };
683
+
684
+ // ── Producer 结果统计 ──
685
+ const submitCalls = runtimeToolCalls.filter(tc => {
686
+ const tool = tc?.tool || tc?.name;
687
+ return tool === 'submit_knowledge' || tool === 'submit_with_check';
688
+ });
689
+ const successCount = submitCalls.filter(tc => {
690
+ const res = tc?.result;
691
+ if (!res) return true;
692
+ if (typeof res === 'string') return !res.includes('rejected') && !res.includes('error');
693
+ return res.status !== 'rejected' && res.status !== 'error';
694
+ }).length;
695
+ const rejectedCount = submitCalls.length - successCount;
696
+
697
+ const producerResult = {
698
+ candidateCount: needsCandidates ? successCount : 0,
699
+ rejectedCount: needsCandidates ? rejectedCount : 0,
700
+ toolCalls: runtimeToolCalls,
701
+ reply: produceResult?.reply || analysisText,
702
+ tokenUsage: combinedTokenUsage,
703
+ };
704
+
705
+ candidateResults.created += producerResult.candidateCount;
706
+ dimensionCandidates[dimId] = { analysisReport, producerResult };
707
+
708
+ // ── Memory Update ──
556
709
  const ac = memoryCoordinator.getActiveContext(analystScopeId);
557
710
  const distilled = ac ? ac.distill() : { keyFindings: [], totalObservations: 0, toolCallSummary: [] };
558
711
  sessionStore.storeDimensionReport(dimId, {
559
712
  analysisText: analysisReport.analysisText,
560
- findings: analysisReport.findings || distilled.keyFindings,
713
+ findings: analysisReport.findings.length > 0 ? analysisReport.findings : distilled.keyFindings,
561
714
  referencedFiles: analysisReport.referencedFiles || [],
562
715
  candidatesSummary: [],
563
716
  workingMemoryDistilled: distilled,
564
717
  });
565
718
 
566
- // v4.2: 记录 Artifact 增强数据 (如果使用了 v2 pipeline)
567
- const isArtifact = !!analysisReport.evidenceMap;
568
- const evidenceMapSize = isArtifact ? analysisReport.evidenceMap.size : 0;
569
- const negativeSignalCount = isArtifact ? analysisReport.negativeSignals?.length || 0 : 0;
570
- const qualityScore = isArtifact ? analysisReport.qualityReport?.totalScore : null;
571
-
572
719
  logger.info(
573
- `[Bootstrap-v3] Analyst "${dimId}": ${analysisReport.analysisText.length} chars, ` +
574
- `${analysisReport.referencedFiles.length} files, ` +
575
- `${distilled.keyFindings.length} key findings, ` +
576
- `${distilled.totalObservations} observations` +
577
- (isArtifact
578
- ? `, evidence: ${evidenceMapSize} files, negative: ${negativeSignalCount}, quality: ${qualityScore}`
579
- : '') +
580
- ` (${Date.now() - dimStartTime}ms)`
720
+ `[Insight-v3] Dimension "${dimId}": analysis=${analysisReport.analysisText.length} chars, ` +
721
+ `files=${analysisReport.referencedFiles.length}, findings=${(analysisReport.findings || distilled.keyFindings).length}, ` +
722
+ `toolCalls=${runtimeToolCalls.length}, degraded=${runResult?.degraded || false} (${Date.now() - dimStartTime}ms)`,
581
723
  );
582
724
 
583
- // ── Phase 2: Producer (如果需要候选输出) ──
584
- let producerResult = { candidateCount: 0, toolCalls: [], reply: '' };
585
- // v3 优先使用 DIMENSION_CONFIGS_V3 的 outputType,回退到 baseDimension 的 skillWorthy/dualOutput
586
- const v3OutputType = DIMENSION_CONFIGS_V3[dimId]?.outputType;
587
- const needsCandidates = v3OutputType
588
- ? v3OutputType !== 'skill' // 'dual' 或 'candidate' 都产出候选
589
- : !dimConfig.skillWorthy || dimConfig.dualOutput;
590
-
591
- // 先保存 Analyst 结果,确保即使 Producer 失败也能生成 Skill
592
- dimensionCandidates[dimId] = {
593
- analysisReport,
594
- producerResult,
595
- };
725
+ // ── Token 用量持久化 (fire-and-forget) ──
726
+ try {
727
+ const tokenStore = ctx.container?.get?.('tokenUsageStore');
728
+ if (tokenStore) {
729
+ const aiProv = runtime.aiProvider;
730
+ tokenStore.record({
731
+ source: 'system',
732
+ dimension: dimId,
733
+ provider: aiProv?.name || null,
734
+ model: aiProv?.model || null,
735
+ inputTokens: combinedTokenUsage.input || 0,
736
+ outputTokens: combinedTokenUsage.output || 0,
737
+ durationMs: Date.now() - dimStartTime,
738
+ toolCalls: runtimeToolCalls.length,
739
+ sessionId: sessionId || null,
740
+ });
741
+ try {
742
+ const realtime = ctx.container?.get?.('realtimeService');
743
+ realtime?.broadcastTokenUsageUpdated?.();
744
+ } catch { /* optional */ }
745
+ }
746
+ } catch { /* token logging should never break execution */ }
596
747
 
597
- if (needsCandidates && analysisReport.analysisText.length >= 100) {
598
- try {
599
- // v5.0: Producer 创建独立作用域
600
- const producerScopeId = `${dimId}:producer`;
601
- memoryCoordinator.createDimensionScope(producerScopeId);
602
-
603
- producerResult = await Promise.race([
604
- producerAgent.produce(analysisReport, dimConfig, projectInfo, {
605
- sessionId,
606
- memoryCoordinator,
748
+ // ── v5.1: analysisText 过短补强 ──
749
+ if (needsCandidates && analysisReport.analysisText.length < 100) {
750
+ const findings = analysisReport.findings || [];
751
+ if (findings.length >= 3) {
752
+ const dimLabel = dimConfig.label || dimId;
753
+ const synthesized = [
754
+ `## ${dimLabel}`,
755
+ '',
756
+ analysisReport.analysisText.trim(),
757
+ '',
758
+ '### 关键发现',
759
+ '',
760
+ ...findings.slice(0, 10).map((f, i) => {
761
+ const text = typeof f === 'string' ? f : f.finding;
762
+ return `${i + 1}. ${text}`;
607
763
  }),
608
- new Promise((_, reject) =>
609
- setTimeout(() => reject(new Error(`Producer timeout for "${dimId}"`)), 180_000)
610
- ),
611
- ]);
612
-
613
- candidateResults.created += producerResult.candidateCount;
614
- // 更新 dimensionCandidates 以包含 Producer 结果
615
- dimensionCandidates[dimId].producerResult = producerResult;
764
+ ];
765
+ const memDistilled = distilled;
766
+ if (memDistilled?.toolCallSummary?.length > 0) {
767
+ synthesized.push('', '### 探索记录', '');
768
+ for (const s of memDistilled.toolCallSummary.slice(0, 10)) {
769
+ synthesized.push(`- ${s}`);
770
+ }
771
+ }
772
+ const originalLen = analysisReport.analysisText.length;
773
+ analysisReport.analysisText = synthesized.join('\n');
616
774
  logger.info(
617
- `[Bootstrap-v3] Producer "${dimId}": ${producerResult.candidateCount} candidates (${Date.now() - dimStartTime}ms total)`
618
- );
619
- } catch (producerErr) {
620
- logger.error(
621
- `[Bootstrap-v3] Producer "${dimId}" failed: ${producerErr.message} — Analyst result preserved for Skill generation`
775
+ `[Insight-v3] analysisText 补强 "${dimId}": ${originalLen} ${analysisReport.analysisText.length} chars ` +
776
+ `(from ${findings.length} findings)`,
622
777
  );
623
- candidateResults.errors.push({ dimId, error: `Producer: ${producerErr.message}` });
624
778
  }
625
779
  }
626
780
 
627
- // ── Phase 3: 记录 DimensionDigest ──
781
+ // ── DimensionDigest ──
628
782
  const digest = parseDimensionDigest(producerResult.reply) || {
629
783
  summary: `v3 分析: ${analysisReport.analysisText.substring(0, 200)}...`,
630
784
  candidateCount: producerResult.candidateCount,
@@ -633,21 +787,19 @@ export async function fillDimensionsV3(fillContext) {
633
787
  gaps: [],
634
788
  };
635
789
  dimContext.addDimensionDigest(dimId, digest);
636
-
637
- // v4.0: 同步 digest 到 SessionStore
638
790
  sessionStore.addDimensionDigest(dimId, digest);
639
791
 
640
- // 记录到 DimensionContext + EpisodicMemory
792
+ // 候选摘要记录到 DimensionContext + SessionStore
641
793
  for (const tc of producerResult.toolCalls || []) {
642
794
  const tool = tc.tool || tc.name;
643
795
  if (tool === 'submit_knowledge' || tool === 'submit_with_check') {
796
+ const args = tc.params || tc.args || {};
644
797
  const candidateSummary = {
645
- title: tc.params?.title || '',
646
- subTopic: tc.params?.category || '',
647
- summary: tc.params?.summary || '',
798
+ title: args.title || '',
799
+ subTopic: args.category || '',
800
+ summary: args.summary || '',
648
801
  };
649
802
  dimContext.addSubmittedCandidate(dimId, candidateSummary);
650
- // v4.0: 同步到 SessionStore
651
803
  sessionStore.addSubmittedCandidate(dimId, candidateSummary);
652
804
  }
653
805
  }
@@ -656,44 +808,41 @@ export async function fillDimensionsV3(fillContext) {
656
808
  type: needsCandidates ? 'candidate' : 'skill',
657
809
  extracted: producerResult.candidateCount,
658
810
  created: producerResult.candidateCount,
659
- status: 'v3-complete',
811
+ skillPending: dimConfig.skillWorthy && producerResult.candidateCount === 0,
812
+ status: 'v3-pipeline-complete',
813
+ degraded: runResult?.degraded || false,
660
814
  durationMs: Date.now() - dimStartTime,
661
- toolCallCount:
662
- (analysisReport.metadata?.toolCallCount || 0) + (producerResult.toolCalls?.length || 0),
663
- source: 'internal-agent',
815
+ toolCallCount: runtimeToolCalls.length,
816
+ source: 'enhanced-pipeline-strategy',
664
817
  });
665
818
 
666
- // P4.1: 聚合 token 用量
667
- const analystTokens = analysisReport.metadata?.tokenUsage || { input: 0, output: 0 };
668
- const producerTokens = producerResult.tokenUsage || { input: 0, output: 0 };
669
- const dimTokenUsage = {
670
- input: (analystTokens.input || 0) + (producerTokens.input || 0),
671
- output: (analystTokens.output || 0) + (producerTokens.output || 0),
672
- };
673
-
819
+ const dimTokenUsage = combinedTokenUsage;
674
820
  const dimResult = {
675
821
  candidateCount: producerResult.candidateCount,
676
822
  rejectedCount: producerResult.rejectedCount || 0,
677
823
  analysisChars: analysisReport.analysisText.length,
678
824
  referencedFiles: analysisReport.referencedFiles.length,
679
825
  durationMs: Date.now() - dimStartTime,
680
- toolCallCount:
681
- (analysisReport.metadata?.toolCallCount || 0) + (producerResult.toolCalls?.length || 0),
826
+ toolCallCount: runtimeToolCalls.length,
682
827
  tokenUsage: dimTokenUsage,
683
- // P3+: 保存 analysisText 供 checkpoint 恢复后 Skill 生成使用
684
828
  analysisText: analysisReport.analysisText,
685
829
  referencedFilesList: analysisReport.referencedFiles || [],
686
830
  };
687
831
 
688
- // P4.2: 记录维度统计
689
832
  dimensionStats[dimId] = dimResult;
690
833
 
691
- // P3: 保存 checkpoint
692
- await saveDimensionCheckpoint(projectRoot, sessionId, dimId, dimResult, digest);
834
+ // P3: 保存 checkpoint — 仅当有实质分析内容时(避免 degraded/空结果污染后续 run)
835
+ if (analysisReport.analysisText.length >= 50) {
836
+ await saveDimensionCheckpoint(projectRoot, sessionId, dimId, dimResult, digest);
837
+ } else {
838
+ logger.warn(
839
+ `[Insight-v3] ⚠ 跳过 checkpoint 保存: "${dimId}" analysisText 过短 (${analysisReport.analysisText.length} chars)`
840
+ );
841
+ }
693
842
 
694
843
  return dimResult;
695
844
  } catch (err) {
696
- logger.error(`[Bootstrap-v3] Dimension "${dimId}" failed: ${err.message}`);
845
+ logger.error(`[Insight-v3] Dimension "${dimId}" failed: ${err.message}`);
697
846
  candidateResults.errors.push({ dimId, error: err.message });
698
847
  emitter.emitDimensionComplete(dimId, { type: 'error', reason: err.message });
699
848
  return { candidateCount: 0, error: err.message };
@@ -723,7 +872,7 @@ export async function fillDimensionsV3(fillContext) {
723
872
  const tierStats = [...tierResults.values()];
724
873
  const totalCandidates = tierStats.reduce((s, r) => s + (r.candidateCount || 0), 0);
725
874
  logger.info(
726
- `[Bootstrap-v3] Tier ${tierIndex + 1} complete: ${tierResults.size} dimensions, ${totalCandidates} candidates`
875
+ `[Insight-v3] Tier ${tierIndex + 1} complete: ${tierResults.size} dimensions, ${totalCandidates} candidates`
727
876
  );
728
877
 
729
878
  // v4.0: Tier 级 Reflection — 综合本 Tier 所有维度的发现
@@ -731,29 +880,29 @@ export async function fillDimensionsV3(fillContext) {
731
880
  const reflection = buildTierReflection(tierIndex, tierResults, sessionStore);
732
881
  sessionStore.addTierReflection(tierIndex, reflection);
733
882
  logger.info(
734
- `[Bootstrap-v3] Tier ${tierIndex + 1} reflection: ` +
883
+ `[Insight-v3] Tier ${tierIndex + 1} reflection: ` +
735
884
  `${reflection.topFindings.length} top findings, ` +
736
885
  `${reflection.crossDimensionPatterns.length} patterns`
737
886
  );
738
887
  } catch (refErr) {
739
- logger.warn(`[Bootstrap-v3] Tier ${tierIndex + 1} reflection failed: ${refErr.message}`);
888
+ logger.warn(`[Insight-v3] Tier ${tierIndex + 1} reflection failed: ${refErr.message}`);
740
889
  }
741
890
  },
742
891
  });
743
892
 
744
893
  logger.info(
745
- `[Bootstrap-v3] All tiers complete: ${results.size} dimensions in ${Date.now() - t0}ms`
894
+ `[Insight-v3] All tiers complete: ${results.size} dimensions in ${Date.now() - t0}ms`
746
895
  );
747
896
  // v4.0: 记录 SessionStore 统计
748
897
  const emStats = sessionStore.getStats();
749
898
  logger.info(
750
- `[Bootstrap-v3] Memory stats: ${emStats.completedDimensions} dims, ` +
899
+ `[Insight-v3] Memory stats: ${emStats.completedDimensions} dims, ` +
751
900
  `${emStats.totalFindings} findings, ${emStats.referencedFiles} files, ` +
752
901
  `${emStats.crossReferences} cross-refs, ${emStats.tierReflections} reflections`
753
902
  );
754
903
  if (emStats.cacheStats) {
755
904
  logger.info(
756
- `[Bootstrap-v3] Cache stats: ${emStats.cacheStats.hitRate} hit rate, ` +
905
+ `[Insight-v3] Cache stats: ${emStats.cacheStats.hitRate} hit rate, ` +
757
906
  `${emStats.cacheStats.searchCacheSize} searches, ${emStats.cacheStats.fileCacheSize} files`
758
907
  );
759
908
  }
@@ -770,7 +919,7 @@ export async function fillDimensionsV3(fillContext) {
770
919
  await executeDimension(dimId);
771
920
  }
772
921
  }
773
- logger.info(`[Bootstrap-v3] Serial execution complete in ${Date.now() - t0}ms`);
922
+ logger.info(`[Insight-v3] Serial execution complete in ${Date.now() - t0}ms`);
774
923
  }
775
924
 
776
925
  // ═══════════════════════════════════════════════════════════
@@ -827,7 +976,7 @@ export async function fillDimensionsV3(fillContext) {
827
976
  }
828
977
  effectiveText = synthesized.join('\n');
829
978
  logger.info(
830
- `[Bootstrap-v3] Skill "${dim.id}": analysisText too short (${analysisText.trim().length} chars), ` +
979
+ `[Insight-v3] Skill "${dim.id}": analysisText too short (${analysisText.trim().length} chars), ` +
831
980
  `synthesized from ${keyFindings.length} findings → ${effectiveText.length} chars`
832
981
  );
833
982
  }
@@ -851,14 +1000,14 @@ export async function fillDimensionsV3(fillContext) {
851
1000
  emitter.emitDimensionFailed(dim.id, new Error(result.error));
852
1001
  }
853
1002
  } catch (err) {
854
- logger.warn(`[Bootstrap-v3] Skill generation failed for "${dim.id}": ${err.message}`);
1003
+ logger.warn(`[Insight-v3] Skill generation failed for "${dim.id}": ${err.message}`);
855
1004
  skillResults.failed++;
856
1005
  skillResults.errors.push({ dimId: dim.id, error: err.message });
857
1006
  emitter.emitDimensionFailed(dim.id, err);
858
1007
  }
859
1008
  }
860
1009
  } catch (e) {
861
- logger.warn(`[Bootstrap-v3] Skill generation module import failed: ${e.message}`);
1010
+ logger.warn(`[Insight-v3] Skill generation module import failed: ${e.message}`);
862
1011
  }
863
1012
 
864
1013
  // ═══════════════════════════════════════════════════════════
@@ -892,13 +1041,13 @@ export async function fillDimensionsV3(fillContext) {
892
1041
  if (allCandidates.length > 0) {
893
1042
  const relResult = ceg.populateFromCandidateRelations(allCandidates);
894
1043
  logger.info(
895
- `[Bootstrap-v3] Code Entity Graph relations: ${relResult.edgesCreated} edges from ${allCandidates.length} candidates (${relResult.durationMs}ms)`
1044
+ `[Insight-v3] Code Entity Graph relations: ${relResult.edgesCreated} edges from ${allCandidates.length} candidates (${relResult.durationMs}ms)`
896
1045
  );
897
1046
  }
898
1047
  }
899
1048
  } catch (cegErr) {
900
1049
  logger.warn(
901
- `[Bootstrap-v3] Code Entity Graph relations failed (non-blocking): ${cegErr.message}`
1050
+ `[Insight-v3] Code Entity Graph relations failed (non-blocking): ${cegErr.message}`
902
1051
  );
903
1052
  }
904
1053
 
@@ -912,7 +1061,7 @@ export async function fillDimensionsV3(fillContext) {
912
1061
  try {
913
1062
  const db = ctx.container.get('database');
914
1063
  if (db) {
915
- const semanticMemory = new ProjectSemanticMemory(db, { logger });
1064
+ const semanticMemory = new PersistentMemory(db, { logger });
916
1065
  const consolidator = new EpisodicConsolidator(semanticMemory, { logger });
917
1066
 
918
1067
  consolidationResult = consolidator.consolidate(sessionStore, {
@@ -922,18 +1071,18 @@ export async function fillDimensionsV3(fillContext) {
922
1071
 
923
1072
  const smStats = semanticMemory.getStats();
924
1073
  logger.info(
925
- `[Bootstrap-v3] Semantic Memory consolidation: ` +
1074
+ `[Insight-v3] Semantic Memory consolidation: ` +
926
1075
  `+${consolidationResult.total.added} ADD, ` +
927
1076
  `~${consolidationResult.total.updated} UPDATE, ` +
928
1077
  `⊕${consolidationResult.total.merged} MERGE | ` +
929
1078
  `Total: ${smStats.total} memories (avg importance: ${smStats.avgImportance})`
930
1079
  );
931
1080
  } else {
932
- logger.warn('[Bootstrap-v3] Database not available — skipping Semantic Memory consolidation');
1081
+ logger.warn('[Insight-v3] Database not available — skipping Semantic Memory consolidation');
933
1082
  }
934
1083
  } catch (consolidateErr) {
935
1084
  logger.warn(
936
- `[Bootstrap-v3] Semantic Memory consolidation failed (non-blocking): ${consolidateErr.message}`
1085
+ `[Insight-v3] Semantic Memory consolidation failed (non-blocking): ${consolidateErr.message}`
937
1086
  );
938
1087
  }
939
1088
 
@@ -957,7 +1106,7 @@ export async function fillDimensionsV3(fillContext) {
957
1106
 
958
1107
  logger.info(
959
1108
  [
960
- `[Bootstrap-v3] ═══ Pipeline complete ═══`,
1109
+ `[Insight-v3] ═══ Pipeline complete ═══`,
961
1110
  isIncremental
962
1111
  ? ` Mode: INCREMENTAL (${incrementalPlan.affectedDimensions.length} affected, ${incrementalSkippedDims.length} skipped)`
963
1112
  : '',
@@ -1070,9 +1219,9 @@ export async function fillDimensionsV3(fillContext) {
1070
1219
  path.join(reportDir, 'bootstrap-report.json'),
1071
1220
  JSON.stringify(report, null, 2)
1072
1221
  );
1073
- logger.info(`[Bootstrap-v3] 📊 Bootstrap report saved to .autosnippet/bootstrap-report.json`);
1222
+ logger.info(`[Insight-v3] 📊 Bootstrap report saved to .autosnippet/bootstrap-report.json`);
1074
1223
  } catch (reportErr) {
1075
- logger.warn(`[Bootstrap-v3] Bootstrap report generation failed: ${reportErr.message}`);
1224
+ logger.warn(`[Insight-v3] Bootstrap report generation failed: ${reportErr.message}`);
1076
1225
  }
1077
1226
 
1078
1227
  // P3: 成功完成后清理 checkpoints
@@ -1095,15 +1244,15 @@ export async function fillDimensionsV3(fillContext) {
1095
1244
  },
1096
1245
  plan: isIncremental ? incrementalPlan : null,
1097
1246
  });
1098
- logger.info(`[Bootstrap-v3] 📸 Snapshot saved: ${snapshotId}`);
1247
+ logger.info(`[Insight-v3] 📸 Snapshot saved: ${snapshotId}`);
1099
1248
  }
1100
1249
  } catch (snapErr) {
1101
- logger.warn(`[Bootstrap-v3] Snapshot save failed (non-blocking): ${snapErr.message}`);
1250
+ logger.warn(`[Insight-v3] Snapshot save failed (non-blocking): ${snapErr.message}`);
1102
1251
  }
1103
1252
 
1104
1253
  // 释放文件缓存
1105
1254
  allFiles = null;
1106
- chatAgent.setFileCache(null);
1255
+ ctx.container.singletons._fileCache = null;
1107
1256
 
1108
1257
  // ── Cursor Delivery: 生成 4 通道交付物料 ──
1109
1258
  try {
@@ -1113,7 +1262,7 @@ export async function fillDimensionsV3(fillContext) {
1113
1262
  const pipeline = container.get('cursorDeliveryPipeline');
1114
1263
  const deliveryResult = await pipeline.deliver();
1115
1264
  logger.info(
1116
- `[Bootstrap-v3] 🚀 Cursor Delivery complete — ` +
1265
+ `[Insight-v3] 🚀 Cursor Delivery complete — ` +
1117
1266
  `A: ${deliveryResult.channelA.rulesCount} rules, ` +
1118
1267
  `B: ${deliveryResult.channelB.topicCount} topics, ` +
1119
1268
  `C: ${deliveryResult.channelC.synced} skills, ` +
@@ -1122,7 +1271,7 @@ export async function fillDimensionsV3(fillContext) {
1122
1271
  );
1123
1272
  }
1124
1273
  } catch (deliveryErr) {
1125
- logger.warn(`[Bootstrap-v3] Cursor Delivery failed (non-blocking): ${deliveryErr.message}`);
1274
+ logger.warn(`[Insight-v3] Cursor Delivery failed (non-blocking): ${deliveryErr.message}`);
1126
1275
  }
1127
1276
 
1128
1277
  // ── Repo Wiki: 自动生成项目文档 Wiki ──
@@ -1199,7 +1348,7 @@ export async function fillDimensionsV3(fillContext) {
1199
1348
  const wikiResult = await wiki.generate();
1200
1349
  if (wikiResult.success) {
1201
1350
  logger.info(
1202
- `[Bootstrap-v3] 📖 Wiki generated — ${wikiResult.filesGenerated} files, ` +
1351
+ `[Insight-v3] 📖 Wiki generated — ${wikiResult.filesGenerated} files, ` +
1203
1352
  `AI: ${wikiResult.aiComposed || 0}, Synced: ${wikiResult.syncedDocs || 0}, ` +
1204
1353
  `Dedup removed: ${wikiResult.dedup?.removed?.length || 0}`
1205
1354
  );
@@ -1223,7 +1372,7 @@ export async function fillDimensionsV3(fillContext) {
1223
1372
  } catch { /* non-critical */ }
1224
1373
  }
1225
1374
  } catch (wikiErr) {
1226
- logger.warn(`[Bootstrap-v3] Wiki generation failed (non-blocking): ${wikiErr.message}`);
1375
+ logger.warn(`[Insight-v3] Wiki generation failed (non-blocking): ${wikiErr.message}`);
1227
1376
  try {
1228
1377
  const wikiRoute = await import('../../../../../http/routes/wiki.js');
1229
1378
  wikiRoute.patchWikiTask?.({