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.
- package/bin/cli.js +13 -5
- package/dashboard/dist/assets/index-BTAsOZv2.js +128 -0
- package/dashboard/dist/assets/index-C_72Ct98.css +1 -0
- package/dashboard/dist/index.html +2 -2
- package/lib/cli/AiScanService.js +26 -29
- package/lib/cli/SetupService.js +1 -1
- package/lib/core/AstAnalyzer.js +27 -5
- package/lib/core/analysis/CallEdgeResolver.js +402 -0
- package/lib/core/analysis/CallGraphAnalyzer.js +367 -0
- package/lib/core/analysis/CallSiteExtractor.js +629 -0
- package/lib/core/analysis/DataFlowInferrer.js +57 -0
- package/lib/core/analysis/ImportPathResolver.js +189 -0
- package/lib/core/analysis/ImportRecord.js +105 -0
- package/lib/core/analysis/SymbolTableBuilder.js +211 -0
- package/lib/core/ast/ProjectGraph.js +8 -0
- package/lib/core/ast/lang-dart.js +352 -5
- package/lib/core/ast/lang-go.js +212 -10
- package/lib/core/ast/lang-java.js +205 -1
- package/lib/core/ast/lang-kotlin.js +330 -1
- package/lib/core/ast/lang-python.js +31 -2
- package/lib/core/ast/lang-rust.js +284 -3
- package/lib/core/ast/lang-swift.js +180 -1
- package/lib/core/ast/lang-typescript.js +290 -1
- package/lib/core/discovery/index.js +2 -2
- package/lib/external/ai/AiProvider.js +66 -172
- package/lib/external/ai/providers/GoogleGeminiProvider.js +23 -1
- package/lib/external/mcp/McpServer.js +1 -0
- package/lib/external/mcp/handlers/bootstrap/BootstrapSession.js +1 -1
- package/lib/external/mcp/handlers/bootstrap/ExternalSubmissionTracker.js +3 -3
- package/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +22 -1
- package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +1 -1
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-configs.js +2 -1
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +8 -8
- package/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +1 -1
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +311 -162
- package/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +102 -7
- package/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.js +1 -1
- package/lib/external/mcp/handlers/bootstrap-external.js +9 -2
- package/lib/external/mcp/handlers/bootstrap-internal.js +19 -8
- package/lib/external/mcp/handlers/consolidated.js +9 -0
- package/lib/external/mcp/handlers/dimension-complete-external.js +6 -6
- package/lib/external/mcp/handlers/guard.js +3 -3
- package/lib/external/mcp/handlers/structure.js +62 -0
- package/lib/external/mcp/handlers/wiki-external.js +66 -3
- package/lib/external/mcp/tools.js +36 -1
- package/lib/http/HttpServer.js +1 -1
- package/lib/http/middleware/requestLogger.js +1 -0
- package/lib/http/routes/ai.js +240 -35
- package/lib/http/routes/candidates.js +2 -3
- package/lib/http/routes/extract.js +13 -11
- package/lib/http/routes/modules.js +2 -2
- package/lib/http/routes/recipes.js +9 -5
- package/lib/http/routes/remote.js +149 -270
- package/lib/http/routes/violations.js +0 -54
- package/lib/http/utils/sse-sessions.js +1 -1
- package/lib/infrastructure/logging/Logger.js +5 -4
- package/lib/infrastructure/monitoring/PerformanceMonitor.js +3 -2
- package/lib/injection/ServiceContainer.js +70 -28
- package/lib/platform/ScreenCaptureService.js +177 -0
- package/lib/platform/ios/index.js +2 -2
- package/lib/platform/ios/routes/spm.js +2 -2
- package/lib/platform/ios/spm/PackageSwiftParser.js +14 -3
- package/lib/platform/ios/spm/SpmDiscoverer.js +123 -17
- package/lib/platform/ios/spm/{SpmService.js → SpmHelper.js} +43 -675
- package/lib/platform/ios/xcode/XcodeWriteUtils.js +1 -1
- package/lib/service/agent/AgentEventBus.js +207 -0
- package/lib/service/agent/AgentFactory.js +490 -0
- package/lib/service/agent/AgentMessage.js +240 -0
- package/lib/service/agent/AgentRouter.js +228 -0
- package/lib/service/agent/AgentRuntime.js +1016 -0
- package/lib/service/agent/AgentState.js +217 -0
- package/lib/service/agent/IntentClassifier.js +331 -0
- package/lib/service/agent/LarkTransport.js +389 -0
- package/lib/service/agent/capabilities.js +408 -0
- package/lib/service/{chat → agent/context}/ContextWindow.js +37 -12
- package/lib/service/{chat → agent/context}/ExplorationTracker.js +77 -22
- package/lib/service/{chat → agent/core}/ChatAgentPrompts.js +14 -2
- package/lib/service/agent/core/LoopContext.js +170 -0
- package/lib/service/agent/core/MessageAdapter.js +223 -0
- package/lib/service/agent/core/ToolExecutionPipeline.js +376 -0
- package/lib/service/{chat → agent/domain}/ChatAgentTasks.js +19 -98
- package/lib/service/{chat → agent/domain}/EpisodicConsolidator.js +7 -7
- package/lib/service/{chat → agent/domain}/EvidenceCollector.js +4 -2
- package/lib/service/{chat/AnalystAgent.js → agent/domain/insight-analyst.js} +37 -172
- package/lib/service/{chat/HandoffProtocol.js → agent/domain/insight-gate.js} +91 -123
- package/lib/service/agent/domain/insight-producer.js +267 -0
- package/lib/service/agent/domain/scan-prompts.js +105 -0
- package/lib/service/agent/forced-summary.js +266 -0
- package/lib/service/agent/index.js +91 -0
- package/lib/service/{chat → agent}/memory/ActiveContext.js +3 -1
- package/lib/service/{chat → agent}/memory/MemoryCoordinator.js +7 -7
- package/lib/service/{chat/ProjectSemanticMemory.js → agent/memory/PersistentMemory.js} +359 -89
- package/lib/service/{chat → agent}/memory/SessionStore.js +5 -4
- package/lib/service/{chat → agent}/memory/index.js +1 -1
- package/lib/service/agent/policies.js +442 -0
- package/lib/service/agent/presets.js +303 -0
- package/lib/service/agent/strategies.js +717 -0
- package/lib/service/{chat → agent/tools}/ToolRegistry.js +3 -3
- package/lib/service/agent/tools/ai-analysis.js +75 -0
- package/lib/service/{chat → agent}/tools/ast-graph.js +229 -32
- package/lib/service/{chat → agent}/tools/composite.js +2 -1
- package/lib/service/{chat → agent}/tools/guard.js +1 -121
- package/lib/service/{chat → agent}/tools/index.js +33 -22
- package/lib/service/{chat → agent}/tools/infrastructure.js +6 -1
- package/lib/service/agent/tools/knowledge-graph.js +112 -0
- package/lib/service/agent/tools/scan-recipe.js +189 -0
- package/lib/service/agent/tools/system-interaction.js +476 -0
- package/lib/service/automation/DirectiveDetector.js +0 -1
- package/lib/service/automation/FileWatcher.js +0 -8
- package/lib/service/automation/handlers/CreateHandler.js +7 -3
- package/lib/service/automation/handlers/DraftHandler.js +7 -6
- package/lib/service/cursor/CursorDeliveryPipeline.js +167 -1
- package/lib/service/knowledge/CodeEntityGraph.js +327 -2
- package/lib/service/knowledge/KnowledgeService.js +5 -1
- package/lib/service/module/ModuleService.js +49 -73
- package/lib/service/skills/SignalCollector.js +26 -19
- package/lib/service/snippet/codecs/VSCodeCodec.js +1 -1
- package/lib/service/wiki/WikiGenerator.js +1 -1
- package/lib/shared/FieldSpec.js +1 -1
- package/lib/shared/PathGuard.js +1 -1
- package/lib/shared/StyleGuide.js +1 -1
- package/package.json +4 -1
- package/resources/native-ui/screenshot.swift +228 -0
- package/dashboard/dist/assets/index-BaGY7kJI.css +0 -1
- package/dashboard/dist/assets/index-DfHY_3ln.js +0 -128
- package/lib/core/discovery/SpmDiscoverer.js +0 -5
- package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +0 -749
- package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +0 -277
- package/lib/http/routes/spm.js +0 -5
- package/lib/infrastructure/external/XcodeAutomation.js +0 -15
- package/lib/service/chat/ChatAgent.js +0 -1602
- package/lib/service/chat/Memory.js +0 -161
- package/lib/service/chat/ProducerAgent.js +0 -431
- package/lib/service/chat/ReasoningTrace.js +0 -523
- package/lib/service/chat/TaskPipeline.js +0 -357
- package/lib/service/chat/WorkingMemory.js +0 -357
- package/lib/service/chat/memory/PersistentMemory.js +0 -450
- package/lib/service/chat/tools/ai-analysis.js +0 -267
- package/lib/service/chat/tools/knowledge-graph.js +0 -234
- package/lib/service/chat/tools.js +0 -18
- package/lib/service/snippet/PlaceholderConverter.js +0 -5
- package/lib/service/snippet/codecs/XcodeCodec.js +0 -5
- /package/lib/service/{chat → agent}/ConversationStore.js +0 -0
- /package/lib/service/{chat → agent}/tools/_shared.js +0 -0
- /package/lib/service/{chat → agent}/tools/lifecycle.js +0 -0
- /package/lib/service/{chat → agent}/tools/project-access.js +0 -0
- /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
|
-
* 核心架构:
|
|
7
|
+
* 核心架构: PipelineStrategy 驱动 (Analyze → QualityGate → Produce → RejectionGate)
|
|
8
8
|
*
|
|
9
|
-
* 1.
|
|
10
|
-
* 2.
|
|
11
|
-
* 3.
|
|
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 {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
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
|
-
`[
|
|
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
|
|
76
|
+
let agentFactory = null;
|
|
74
77
|
try {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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 (!
|
|
87
|
-
logger.info('[
|
|
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
|
-
`[
|
|
252
|
+
`[Insight-v3] ProjectGraph: ${overview.totalClasses} classes, ${overview.totalProtocols} protocols (${overview.buildTimeMs}ms)`
|
|
251
253
|
);
|
|
252
254
|
}
|
|
253
255
|
} catch (e) {
|
|
254
|
-
logger.warn(`[
|
|
256
|
+
logger.warn(`[Insight-v3] ProjectGraph build failed: ${e.message}`);
|
|
255
257
|
}
|
|
256
258
|
|
|
257
259
|
// ═══════════════════════════════════════════════════════════
|
|
258
260
|
// Step 1: 构建 Agents + 上下文
|
|
259
261
|
// ═══════════════════════════════════════════════════════════
|
|
260
|
-
|
|
261
|
-
const producerAgent = new ProducerAgent(chatAgent);
|
|
262
|
+
logger.info('[Insight-v7] Using unified AgentRuntime pipeline (no legacy Analyst/Producer wrappers)');
|
|
262
263
|
|
|
263
|
-
//
|
|
264
|
-
|
|
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
|
-
`[
|
|
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:
|
|
312
|
-
// 加载历史 bootstrap 记忆 → 注入
|
|
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
|
|
318
|
+
semanticMemory = new PersistentMemory(db, { logger });
|
|
318
319
|
const smStats = semanticMemory.getStats();
|
|
319
320
|
if (smStats.total > 0) {
|
|
320
321
|
logger.info(
|
|
321
|
-
`[
|
|
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(`[
|
|
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
|
-
`[
|
|
341
|
+
`[Insight-v3] CodeEntityGraph: ${topo.totalEntities} entities, ${topo.totalEdges} edges`
|
|
341
342
|
);
|
|
342
343
|
}
|
|
343
344
|
}
|
|
344
345
|
} catch (cegErr) {
|
|
345
|
-
logger.warn(`[
|
|
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
|
-
`[
|
|
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
|
-
`[
|
|
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(`[
|
|
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(`[
|
|
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
|
-
`[
|
|
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(`[
|
|
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(`[
|
|
534
|
+
logger.info(`[Insight-v3] ── Dimension "${dimId}" (${dimConfig.label}) ──`);
|
|
530
535
|
|
|
531
536
|
const dimStartTime = Date.now();
|
|
532
537
|
|
|
533
538
|
try {
|
|
534
|
-
//
|
|
539
|
+
// ═══ v3.0: 增强 PipelineStrategy 驱动 ═══
|
|
535
540
|
const analystScopeId = `${dimId}:analyst`;
|
|
536
541
|
memoryCoordinator.createDimensionScope(analystScopeId);
|
|
537
542
|
|
|
538
|
-
|
|
539
|
-
const
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
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(`
|
|
636
|
+
setTimeout(() => reject(new Error(`Bootstrap runtime timeout for "${dimId}"`)), outerTimeoutMs),
|
|
552
637
|
),
|
|
553
638
|
]);
|
|
554
639
|
|
|
555
|
-
//
|
|
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
|
|
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
|
-
`[
|
|
574
|
-
|
|
575
|
-
|
|
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
|
-
// ──
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
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
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
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
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
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
|
-
`[
|
|
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
|
-
// ──
|
|
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
|
-
//
|
|
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:
|
|
646
|
-
subTopic:
|
|
647
|
-
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
|
-
|
|
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
|
-
|
|
663
|
-
source: 'internal-agent',
|
|
815
|
+
toolCallCount: runtimeToolCalls.length,
|
|
816
|
+
source: 'enhanced-pipeline-strategy',
|
|
664
817
|
});
|
|
665
818
|
|
|
666
|
-
|
|
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
|
-
|
|
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(`[
|
|
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
|
-
`[
|
|
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
|
-
`[
|
|
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(`[
|
|
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
|
-
`[
|
|
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
|
-
`[
|
|
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
|
-
`[
|
|
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(`[
|
|
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
|
-
`[
|
|
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(`[
|
|
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(`[
|
|
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
|
-
`[
|
|
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
|
-
`[
|
|
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
|
|
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
|
-
`[
|
|
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('[
|
|
1081
|
+
logger.warn('[Insight-v3] Database not available — skipping Semantic Memory consolidation');
|
|
933
1082
|
}
|
|
934
1083
|
} catch (consolidateErr) {
|
|
935
1084
|
logger.warn(
|
|
936
|
-
`[
|
|
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
|
-
`[
|
|
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(`[
|
|
1222
|
+
logger.info(`[Insight-v3] 📊 Bootstrap report saved to .autosnippet/bootstrap-report.json`);
|
|
1074
1223
|
} catch (reportErr) {
|
|
1075
|
-
logger.warn(`[
|
|
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(`[
|
|
1247
|
+
logger.info(`[Insight-v3] 📸 Snapshot saved: ${snapshotId}`);
|
|
1099
1248
|
}
|
|
1100
1249
|
} catch (snapErr) {
|
|
1101
|
-
logger.warn(`[
|
|
1250
|
+
logger.warn(`[Insight-v3] Snapshot save failed (non-blocking): ${snapErr.message}`);
|
|
1102
1251
|
}
|
|
1103
1252
|
|
|
1104
1253
|
// 释放文件缓存
|
|
1105
1254
|
allFiles = null;
|
|
1106
|
-
|
|
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
|
-
`[
|
|
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(`[
|
|
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
|
-
`[
|
|
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(`[
|
|
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?.({
|