autosnippet 3.2.8 → 3.2.10
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 +6 -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 +23 -26
- package/lib/cli/SetupService.js +1 -1
- package/lib/cli/deploy/FileManifest.js +1 -1
- package/lib/core/AstAnalyzer.js +1 -1
- package/lib/core/discovery/index.js +2 -2
- package/lib/external/ai/AiProvider.js +66 -172
- package/lib/external/ai/providers/GoogleGeminiProvider.js +29 -5
- 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 +1 -1
- package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +1 -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 +291 -204
- package/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +7 -6
- package/lib/external/mcp/handlers/bootstrap/shared/dimension-sop.js +1 -1
- package/lib/external/mcp/handlers/bootstrap-internal.js +2 -2
- package/lib/external/mcp/handlers/dimension-complete-external.js +6 -6
- 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 +5 -5
- package/lib/http/routes/remote.js +134 -255
- 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 +64 -17
- package/lib/platform/ScreenCaptureService.js +177 -0
- package/lib/platform/ios/routes/spm.js +2 -2
- package/lib/service/agent/AgentEventBus.js +207 -0
- package/lib/service/agent/AgentFactory.js +535 -0
- package/lib/service/agent/AgentMessage.js +240 -0
- package/lib/service/agent/AgentRouter.js +228 -0
- package/lib/service/agent/AgentRuntime.js +1056 -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 +409 -0
- package/lib/service/{chat → agent/context}/ContextWindow.js +37 -12
- package/lib/service/{chat → agent/context}/ExplorationTracker.js +112 -33
- package/lib/service/{chat → agent/core}/ChatAgentPrompts.js +5 -3
- 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 +15 -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} +85 -135
- package/lib/service/agent/domain/insight-producer.js +270 -0
- package/lib/service/agent/domain/scan-prompts.js +444 -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 +29 -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 +1 -1
- package/lib/service/{chat → agent}/memory/index.js +1 -1
- package/lib/service/agent/policies.js +442 -0
- package/lib/service/agent/presets.js +305 -0
- package/lib/service/agent/strategies.js +756 -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/composite.js +2 -1
- package/lib/service/{chat → agent}/tools/guard.js +1 -121
- package/lib/service/{chat → agent}/tools/index.js +27 -21
- package/lib/service/{chat → agent}/tools/infrastructure.js +1 -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/module/ModuleService.js +40 -73
- package/lib/service/skills/SignalCollector.js +26 -19
- package/lib/service/snippet/codecs/VSCodeCodec.js +1 -1
- package/lib/shared/FieldSpec.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-D5jiDBQG.css +0 -1
- package/dashboard/dist/assets/index-e5OKj-Ni.js +0 -128
- package/lib/core/discovery/SpmDiscoverer.js +0 -5
- package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +0 -750
- 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 -359
- 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/ast-graph.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,16 @@
|
|
|
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 { ANALYST_BUDGET } from '../../../../../service/agent/domain/insight-analyst.js';
|
|
28
|
+
import { ContextWindow } from '../../../../../service/agent/context/ContextWindow.js';
|
|
29
|
+
import { ExplorationTracker } from '../../../../../service/agent/context/ExplorationTracker.js';
|
|
26
30
|
import { clearCheckpoints, loadCheckpoints, saveDimensionCheckpoint } from './checkpoint.js';
|
|
27
31
|
import { buildTierReflection, DIMENSION_CONFIGS_V3, getFullDimensionConfig } from './dimension-configs.js';
|
|
28
32
|
import { getDimensionFocusKeywords } from '../shared/dimension-sop.js';
|
|
@@ -61,30 +65,29 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
61
65
|
const isIncremental = incrementalPlan?.canIncremental && incrementalPlan?.mode === 'incremental';
|
|
62
66
|
const emitter = new BootstrapEventEmitter(ctx.container);
|
|
63
67
|
logger.info(
|
|
64
|
-
`[
|
|
68
|
+
`[Insight-v3] ═══ fillDimensionsV3 entered — ${isIncremental ? 'INCREMENTAL' : 'FULL'} pipeline`
|
|
65
69
|
);
|
|
66
70
|
|
|
67
71
|
let allFiles = fillContext.allFiles;
|
|
68
72
|
fillContext.allFiles = null;
|
|
69
73
|
|
|
70
74
|
// ═══════════════════════════════════════════════════════════
|
|
71
|
-
// Step 0: AI 可用性检查
|
|
75
|
+
// Step 0: AI 可用性检查 (v7.2: 使用 AgentFactory)
|
|
72
76
|
// ═══════════════════════════════════════════════════════════
|
|
73
|
-
let
|
|
77
|
+
let agentFactory = null;
|
|
74
78
|
try {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
chatAgent.resetGlobalSubmittedTitles();
|
|
79
|
+
agentFactory = ctx.container.get('agentFactory');
|
|
80
|
+
// 检查 AI Provider 是否可用
|
|
81
|
+
const aiProvider = ctx.container.singletons?.aiProvider;
|
|
82
|
+
if (!aiProvider || aiProvider.name === 'mock') {
|
|
83
|
+
agentFactory = null;
|
|
81
84
|
}
|
|
82
85
|
} catch {
|
|
83
86
|
/* not available */
|
|
84
87
|
}
|
|
85
88
|
|
|
86
|
-
if (!
|
|
87
|
-
logger.info('[
|
|
89
|
+
if (!agentFactory) {
|
|
90
|
+
logger.info('[Insight-v3] AI not available — entering rule-based fallback');
|
|
88
91
|
emitter.emitProgress('bootstrap:ai-unavailable', {
|
|
89
92
|
message: 'AI 不可用,将使用规则化降级提取基础知识。请配置 AI Provider 以获取完整分析。',
|
|
90
93
|
});
|
|
@@ -247,21 +250,20 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
247
250
|
if (projectGraph) {
|
|
248
251
|
const overview = projectGraph.getOverview();
|
|
249
252
|
logger.info(
|
|
250
|
-
`[
|
|
253
|
+
`[Insight-v3] ProjectGraph: ${overview.totalClasses} classes, ${overview.totalProtocols} protocols (${overview.buildTimeMs}ms)`
|
|
251
254
|
);
|
|
252
255
|
}
|
|
253
256
|
} catch (e) {
|
|
254
|
-
logger.warn(`[
|
|
257
|
+
logger.warn(`[Insight-v3] ProjectGraph build failed: ${e.message}`);
|
|
255
258
|
}
|
|
256
259
|
|
|
257
260
|
// ═══════════════════════════════════════════════════════════
|
|
258
261
|
// Step 1: 构建 Agents + 上下文
|
|
259
262
|
// ═══════════════════════════════════════════════════════════
|
|
260
|
-
|
|
261
|
-
const producerAgent = new ProducerAgent(chatAgent);
|
|
263
|
+
logger.info('[Insight-v7] Using unified AgentRuntime pipeline (no legacy Analyst/Producer wrappers)');
|
|
262
264
|
|
|
263
|
-
//
|
|
264
|
-
|
|
265
|
+
// 注入文件缓存到容器 (v7.2: 通过容器传递)
|
|
266
|
+
ctx.container.singletons._fileCache = allFiles;
|
|
265
267
|
|
|
266
268
|
// 项目信息
|
|
267
269
|
const projectInfo = {
|
|
@@ -289,7 +291,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
289
291
|
sessionStore = incrementalPlan.restoredEpisodic;
|
|
290
292
|
const restoredDims = sessionStore.getCompletedDimensions();
|
|
291
293
|
logger.info(
|
|
292
|
-
`[
|
|
294
|
+
`[Insight-v3] Restored SessionStore: ${restoredDims.length} dims [${restoredDims.join(', ')}]`
|
|
293
295
|
);
|
|
294
296
|
|
|
295
297
|
// 同步恢复 DimensionContext 的 digests (兼容)
|
|
@@ -308,23 +310,23 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
308
310
|
});
|
|
309
311
|
}
|
|
310
312
|
|
|
311
|
-
// v4.1:
|
|
312
|
-
// 加载历史 bootstrap 记忆 → 注入
|
|
313
|
+
// v4.1: PersistentMemory — 项目级永久语义记忆 (Tier 3)
|
|
314
|
+
// 加载历史 bootstrap 记忆 → 注入 Analyst promptBuilder
|
|
313
315
|
let semanticMemory = null;
|
|
314
316
|
try {
|
|
315
317
|
const db = ctx.container.get('database');
|
|
316
318
|
if (db) {
|
|
317
|
-
semanticMemory = new
|
|
319
|
+
semanticMemory = new PersistentMemory(db, { logger });
|
|
318
320
|
const smStats = semanticMemory.getStats();
|
|
319
321
|
if (smStats.total > 0) {
|
|
320
322
|
logger.info(
|
|
321
|
-
`[
|
|
323
|
+
`[Insight-v3] Loaded ${smStats.total} semantic memories from previous bootstrap ` +
|
|
322
324
|
`(fact: ${smStats.byType.fact || 0}, insight: ${smStats.byType.insight || 0}, preference: ${smStats.byType.preference || 0})`
|
|
323
325
|
);
|
|
324
326
|
}
|
|
325
327
|
}
|
|
326
328
|
} catch (smErr) {
|
|
327
|
-
logger.warn(`[
|
|
329
|
+
logger.warn(`[Insight-v3] SemanticMemory init failed (non-blocking): ${smErr.message}`);
|
|
328
330
|
}
|
|
329
331
|
|
|
330
332
|
// Phase E: CodeEntityGraph — 代码实体关系图谱 (供 Analyst prompt 注入)
|
|
@@ -337,12 +339,12 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
337
339
|
const topo = codeEntityGraphInst.getTopology();
|
|
338
340
|
if (topo.totalEntities > 0) {
|
|
339
341
|
logger.info(
|
|
340
|
-
`[
|
|
342
|
+
`[Insight-v3] CodeEntityGraph: ${topo.totalEntities} entities, ${topo.totalEdges} edges`
|
|
341
343
|
);
|
|
342
344
|
}
|
|
343
345
|
}
|
|
344
346
|
} catch (cegErr) {
|
|
345
|
-
logger.warn(`[
|
|
347
|
+
logger.warn(`[Insight-v3] CodeEntityGraph init failed (non-blocking): ${cegErr.message}`);
|
|
346
348
|
}
|
|
347
349
|
|
|
348
350
|
// v5.0: MemoryCoordinator — 统一记忆协调器 (会话级)
|
|
@@ -378,14 +380,14 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
378
380
|
}
|
|
379
381
|
if (incrementalSkippedDims.length > 0) {
|
|
380
382
|
logger.info(
|
|
381
|
-
`[
|
|
383
|
+
`[Insight-v3] ⏩ Incremental skip: [${incrementalSkippedDims.join(', ')}] ` +
|
|
382
384
|
`(using historical results)`
|
|
383
385
|
);
|
|
384
386
|
}
|
|
385
387
|
}
|
|
386
388
|
|
|
387
389
|
logger.info(
|
|
388
|
-
`[
|
|
390
|
+
`[Insight-v3] Active dimensions: [${activeDimIds.join(', ')}], concurrency=${enableParallel ? concurrency : 1}${isIncremental ? `, incremental skip: [${incrementalSkippedDims.join(', ')}]` : ''}`
|
|
389
391
|
);
|
|
390
392
|
|
|
391
393
|
// ── P3: 断点续传 — 加载有效 checkpoints ──
|
|
@@ -404,7 +406,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
404
406
|
...checkpoint,
|
|
405
407
|
});
|
|
406
408
|
skippedDims.push(dimId);
|
|
407
|
-
logger.info(`[
|
|
409
|
+
logger.info(`[Insight-v3] ⏩ 跳过已完成维度 (checkpoint): "${dimId}"`);
|
|
408
410
|
}
|
|
409
411
|
}
|
|
410
412
|
|
|
@@ -412,6 +414,10 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
412
414
|
const dimensionCandidates = {};
|
|
413
415
|
const dimensionStats = {}; // P4.2: 维度级统计
|
|
414
416
|
|
|
417
|
+
// ── 跨维度去重集合 (实例级持久化,等效旧 ChatAgent.#globalSubmittedTitles/Patterns) ──
|
|
418
|
+
const globalSubmittedTitles = new Set();
|
|
419
|
+
const globalSubmittedPatterns = new Set();
|
|
420
|
+
|
|
415
421
|
/**
|
|
416
422
|
* 执行单个维度: Analyst → Gate → Producer
|
|
417
423
|
*/
|
|
@@ -432,7 +438,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
432
438
|
restoredFromIncremental: true,
|
|
433
439
|
};
|
|
434
440
|
dimensionStats[dimId] = dimResult;
|
|
435
|
-
logger.info(`[
|
|
441
|
+
logger.info(`[Insight-v3] ⏩ "${dimId}" — incremental skip (historical result)`);
|
|
436
442
|
return dimResult;
|
|
437
443
|
}
|
|
438
444
|
|
|
@@ -472,7 +478,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
472
478
|
candidatesSummary: [],
|
|
473
479
|
});
|
|
474
480
|
logger.info(
|
|
475
|
-
`[
|
|
481
|
+
`[Insight-v3] ✅ Checkpoint "${dimId}": analysisText restored (${cp.analysisText.length} chars) — Skill generation enabled`
|
|
476
482
|
);
|
|
477
483
|
}
|
|
478
484
|
|
|
@@ -521,81 +527,229 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
521
527
|
|
|
522
528
|
// Session 有效性检查
|
|
523
529
|
if (taskManager && !taskManager.isSessionValid(sessionId)) {
|
|
524
|
-
logger.warn(`[
|
|
530
|
+
logger.warn(`[Insight-v3] Session superseded — skipping "${dimId}"`);
|
|
525
531
|
return { candidateCount: 0, error: 'session-superseded' };
|
|
526
532
|
}
|
|
527
533
|
|
|
528
534
|
emitter.emitDimensionStart(dimId);
|
|
529
|
-
logger.info(`[
|
|
535
|
+
logger.info(`[Insight-v3] ── Dimension "${dimId}" (${dimConfig.label}) ──`);
|
|
530
536
|
|
|
531
537
|
const dimStartTime = Date.now();
|
|
532
538
|
|
|
533
539
|
try {
|
|
534
|
-
//
|
|
540
|
+
// ═══ v3.0: 增强 PipelineStrategy 驱动 ═══
|
|
535
541
|
const analystScopeId = `${dimId}:analyst`;
|
|
536
542
|
memoryCoordinator.createDimensionScope(analystScopeId);
|
|
537
543
|
|
|
538
|
-
|
|
539
|
-
const
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
544
|
+
const v3OutputType = DIMENSION_CONFIGS_V3[dimId]?.outputType;
|
|
545
|
+
const needsCandidates = v3OutputType
|
|
546
|
+
? v3OutputType !== 'skill'
|
|
547
|
+
: !dimConfig.skillWorthy || dimConfig.dualOutput;
|
|
548
|
+
|
|
549
|
+
// ── 获取 Preset 的标准 stages 配置作为基础 ──
|
|
550
|
+
const presetStages = PRESETS.insight.strategy.stages;
|
|
551
|
+
|
|
552
|
+
// ── 构建 per-dimension 的 stages ──
|
|
553
|
+
// NOTE: onToolCall 不再注入 ac.recordToolCall — ToolExecutionPipeline 的
|
|
554
|
+
// traceRecord 中间件已通过 loopCtx.trace 统一记录,避免同一 AC 上双重记录。
|
|
555
|
+
const analyzeStage = {
|
|
556
|
+
...presetStages[0],
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
let stages;
|
|
560
|
+
if (needsCandidates) {
|
|
561
|
+
// 候选维度: Analyze→QualityGate→Produce→RejectionGate
|
|
562
|
+
const produceStage = {
|
|
563
|
+
...presetStages[2],
|
|
564
|
+
promptBuilder: (ctx) => {
|
|
565
|
+
memoryCoordinator.allocateBudget('producer');
|
|
566
|
+
return presetStages[2].promptBuilder(ctx);
|
|
567
|
+
},
|
|
568
|
+
};
|
|
569
|
+
stages = [
|
|
570
|
+
analyzeStage,
|
|
571
|
+
presetStages[1], // quality_gate
|
|
572
|
+
produceStage,
|
|
573
|
+
presetStages[3], // rejection_gate
|
|
574
|
+
];
|
|
575
|
+
} else {
|
|
576
|
+
// Skill-only 维度: 仅 Analyze
|
|
577
|
+
stages = [analyzeStage];
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// ── 创建 Runtime (使用增强 PipelineStrategy) ──
|
|
581
|
+
const runtime = agentFactory.createRuntime('insight', {
|
|
582
|
+
lang: primaryLang || projectInfo.lang || null,
|
|
583
|
+
strategy: {
|
|
584
|
+
type: 'pipeline',
|
|
585
|
+
maxRetries: 1,
|
|
586
|
+
stages,
|
|
587
|
+
},
|
|
588
|
+
});
|
|
589
|
+
runtime.setFileCache(allFiles);
|
|
590
|
+
|
|
591
|
+
// ── 构建消息 + strategyContext ──
|
|
592
|
+
const message = AgentMessage.internal(`Bootstrap dimension: ${dimConfig.label}`, {
|
|
593
|
+
sessionId,
|
|
594
|
+
dimension: dimId,
|
|
595
|
+
phase: 'bootstrap',
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
const strategyContext = {
|
|
599
|
+
dimConfig,
|
|
600
|
+
projectInfo,
|
|
601
|
+
dimContext,
|
|
602
|
+
sessionStore,
|
|
603
|
+
semanticMemory,
|
|
604
|
+
codeEntityGraph: codeEntityGraphInst,
|
|
605
|
+
projectGraph: null, // ProjectGraph 在 orchestrator 级别可用时注入
|
|
606
|
+
dimId,
|
|
607
|
+
activeContext: memoryCoordinator.getActiveContext(analystScopeId),
|
|
608
|
+
outputType: dimConfig.outputType || 'analysis',
|
|
609
|
+
// ── 引擎增强参数 (PipelineStrategy → reactLoop 透传) ──
|
|
610
|
+
contextWindow: agentFactory.createContextWindow({ isSystem: true }),
|
|
611
|
+
// B1 fix: 分析阶段使用 analyst 策略 (SCAN→EXPLORE→VERIFY→SUMMARIZE)
|
|
612
|
+
// 而非 bootstrap (EXPLORE→PRODUCE→SUMMARIZE),避免 PRODUCE nudge 浪费轮次
|
|
613
|
+
// B3 fix: 透传完整 ANALYST_BUDGET (searchBudget/maxSubmits/softSubmitLimit/idleRoundsToExit)
|
|
614
|
+
tracker: ExplorationTracker.resolve(
|
|
615
|
+
{ source: 'system', strategy: 'analyst' },
|
|
616
|
+
{ ...ANALYST_BUDGET },
|
|
617
|
+
),
|
|
618
|
+
trace: memoryCoordinator.getActiveContext(analystScopeId),
|
|
619
|
+
memoryCoordinator,
|
|
620
|
+
sharedState: {
|
|
621
|
+
submittedTitles: globalSubmittedTitles,
|
|
622
|
+
submittedPatterns: globalSubmittedPatterns,
|
|
623
|
+
_dimensionMeta: {
|
|
624
|
+
id: dimId,
|
|
625
|
+
outputType: dimConfig.outputType || 'candidate',
|
|
626
|
+
allowedKnowledgeTypes: dimConfig.allowedKnowledgeTypes || [],
|
|
627
|
+
},
|
|
628
|
+
_projectLanguage: primaryLang || projectInfo.lang || null,
|
|
629
|
+
_dimensionScopeId: analystScopeId,
|
|
630
|
+
},
|
|
631
|
+
source: 'system',
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
// ── 执行 ──
|
|
635
|
+
// 外层超时 = 安全网 (各阶段已有独立超时: Analyst 300s + Producer 180s + 硬缓冲 60s)
|
|
636
|
+
const outerTimeoutMs = 600_000;
|
|
637
|
+
const runResult = await Promise.race([
|
|
638
|
+
runtime.execute(message, { strategyContext }),
|
|
550
639
|
new Promise((_, reject) =>
|
|
551
|
-
setTimeout(() => reject(new Error(`
|
|
640
|
+
setTimeout(() => reject(new Error(`Bootstrap runtime timeout for "${dimId}"`)), outerTimeoutMs),
|
|
552
641
|
),
|
|
553
642
|
]);
|
|
554
643
|
|
|
555
|
-
//
|
|
644
|
+
// ── 提取结果 ──
|
|
645
|
+
const analyzeResult = runResult?.phases?.analyze;
|
|
646
|
+
const gateResult = runResult?.phases?.quality_gate;
|
|
647
|
+
const produceResult = runResult?.phases?.produce;
|
|
648
|
+
const analysisText = (analyzeResult?.reply || runResult?.reply || '').trim();
|
|
649
|
+
const artifact = gateResult?.artifact || {
|
|
650
|
+
analysisText,
|
|
651
|
+
referencedFiles: [],
|
|
652
|
+
findings: [],
|
|
653
|
+
metadata: { toolCallCount: 0 },
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
const runtimeToolCalls = runResult?.toolCalls || [];
|
|
657
|
+
const combinedTokenUsage = runResult?.tokenUsage || { input: 0, output: 0 };
|
|
658
|
+
|
|
659
|
+
// 引用文件: 优先从 artifact 取, 回退从 toolCalls 提取
|
|
660
|
+
const referencedFiles = artifact.referencedFiles?.length > 0
|
|
661
|
+
? artifact.referencedFiles
|
|
662
|
+
: [...new Set(runtimeToolCalls.flatMap((tc) => {
|
|
663
|
+
const a = tc?.args || tc?.params || {};
|
|
664
|
+
const files = [];
|
|
665
|
+
if (typeof a.filePath === 'string' && a.filePath.trim()) files.push(a.filePath.trim());
|
|
666
|
+
if (Array.isArray(a.filePaths)) {
|
|
667
|
+
for (const f of a.filePaths) {
|
|
668
|
+
if (typeof f === 'string' && f.trim()) files.push(f.trim());
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
return files;
|
|
672
|
+
}))];
|
|
673
|
+
|
|
674
|
+
const analysisReport = {
|
|
675
|
+
dimensionId: dimId,
|
|
676
|
+
analysisText: artifact.analysisText || analysisText,
|
|
677
|
+
findings: artifact.findings || [],
|
|
678
|
+
referencedFiles,
|
|
679
|
+
evidenceMap: artifact.evidenceMap || null,
|
|
680
|
+
negativeSignals: artifact.negativeSignals || [],
|
|
681
|
+
metadata: {
|
|
682
|
+
toolCallCount: runtimeToolCalls.length,
|
|
683
|
+
tokenUsage: combinedTokenUsage,
|
|
684
|
+
artifactVersion: artifact.metadata?.artifactVersion || 1,
|
|
685
|
+
},
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
// ── Producer 结果统计 ──
|
|
689
|
+
const submitCalls = runtimeToolCalls.filter(tc => {
|
|
690
|
+
const tool = tc?.tool || tc?.name;
|
|
691
|
+
return tool === 'submit_knowledge' || tool === 'submit_with_check';
|
|
692
|
+
});
|
|
693
|
+
const successCount = submitCalls.filter(tc => {
|
|
694
|
+
const res = tc?.result;
|
|
695
|
+
if (!res) return true;
|
|
696
|
+
if (typeof res === 'string') return !res.includes('rejected') && !res.includes('error');
|
|
697
|
+
return res.status !== 'rejected' && res.status !== 'error';
|
|
698
|
+
}).length;
|
|
699
|
+
const rejectedCount = submitCalls.length - successCount;
|
|
700
|
+
|
|
701
|
+
const producerResult = {
|
|
702
|
+
candidateCount: needsCandidates ? successCount : 0,
|
|
703
|
+
rejectedCount: needsCandidates ? rejectedCount : 0,
|
|
704
|
+
toolCalls: runtimeToolCalls,
|
|
705
|
+
reply: produceResult?.reply || analysisText,
|
|
706
|
+
tokenUsage: combinedTokenUsage,
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
candidateResults.created += producerResult.candidateCount;
|
|
710
|
+
dimensionCandidates[dimId] = { analysisReport, producerResult };
|
|
711
|
+
|
|
712
|
+
// ── Memory Update ──
|
|
556
713
|
const ac = memoryCoordinator.getActiveContext(analystScopeId);
|
|
557
714
|
const distilled = ac ? ac.distill() : { keyFindings: [], totalObservations: 0, toolCallSummary: [] };
|
|
558
715
|
sessionStore.storeDimensionReport(dimId, {
|
|
559
716
|
analysisText: analysisReport.analysisText,
|
|
560
|
-
findings: analysisReport.findings
|
|
717
|
+
findings: analysisReport.findings.length > 0 ? analysisReport.findings : distilled.keyFindings,
|
|
561
718
|
referencedFiles: analysisReport.referencedFiles || [],
|
|
562
719
|
candidatesSummary: [],
|
|
563
720
|
workingMemoryDistilled: distilled,
|
|
564
721
|
});
|
|
565
722
|
|
|
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
723
|
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)`
|
|
724
|
+
`[Insight-v3] Dimension "${dimId}": analysis=${analysisReport.analysisText.length} chars, ` +
|
|
725
|
+
`files=${analysisReport.referencedFiles.length}, findings=${(analysisReport.findings || distilled.keyFindings).length}, ` +
|
|
726
|
+
`toolCalls=${runtimeToolCalls.length}, degraded=${runResult?.degraded || false} (${Date.now() - dimStartTime}ms)`,
|
|
581
727
|
);
|
|
582
728
|
|
|
583
|
-
// ──
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
729
|
+
// ── Token 用量持久化 (fire-and-forget) ──
|
|
730
|
+
try {
|
|
731
|
+
const tokenStore = ctx.container?.get?.('tokenUsageStore');
|
|
732
|
+
if (tokenStore) {
|
|
733
|
+
const aiProv = runtime.aiProvider;
|
|
734
|
+
tokenStore.record({
|
|
735
|
+
source: 'system',
|
|
736
|
+
dimension: dimId,
|
|
737
|
+
provider: aiProv?.name || null,
|
|
738
|
+
model: aiProv?.model || null,
|
|
739
|
+
inputTokens: combinedTokenUsage.input || 0,
|
|
740
|
+
outputTokens: combinedTokenUsage.output || 0,
|
|
741
|
+
durationMs: Date.now() - dimStartTime,
|
|
742
|
+
toolCalls: runtimeToolCalls.length,
|
|
743
|
+
sessionId: sessionId || null,
|
|
744
|
+
});
|
|
745
|
+
try {
|
|
746
|
+
const realtime = ctx.container?.get?.('realtimeService');
|
|
747
|
+
realtime?.broadcastTokenUsageUpdated?.();
|
|
748
|
+
} catch { /* optional */ }
|
|
749
|
+
}
|
|
750
|
+
} catch { /* token logging should never break execution */ }
|
|
596
751
|
|
|
597
|
-
// v5.1:
|
|
598
|
-
// 但有足够的结构化发现时,从 findings 合成补充文本,避免 Producer 被 100 char 门控拦截
|
|
752
|
+
// ── v5.1: analysisText 过短补强 ──
|
|
599
753
|
if (needsCandidates && analysisReport.analysisText.length < 100) {
|
|
600
754
|
const findings = analysisReport.findings || [];
|
|
601
755
|
if (findings.length >= 3) {
|
|
@@ -612,9 +766,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
612
766
|
return `${i + 1}. ${text}`;
|
|
613
767
|
}),
|
|
614
768
|
];
|
|
615
|
-
|
|
616
|
-
const dimReport = sessionStore.getDimensionReport(dimId);
|
|
617
|
-
const memDistilled = dimReport?.workingMemoryDistilled;
|
|
769
|
+
const memDistilled = distilled;
|
|
618
770
|
if (memDistilled?.toolCallSummary?.length > 0) {
|
|
619
771
|
synthesized.push('', '### 探索记录', '');
|
|
620
772
|
for (const s of memDistilled.toolCallSummary.slice(0, 10)) {
|
|
@@ -624,71 +776,13 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
624
776
|
const originalLen = analysisReport.analysisText.length;
|
|
625
777
|
analysisReport.analysisText = synthesized.join('\n');
|
|
626
778
|
logger.info(
|
|
627
|
-
`[
|
|
628
|
-
|
|
629
|
-
);
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
if (needsCandidates && analysisReport.analysisText.length >= 100) {
|
|
634
|
-
try {
|
|
635
|
-
// v5.0: 为 Producer 创建独立作用域
|
|
636
|
-
const producerScopeId = `${dimId}:producer`;
|
|
637
|
-
memoryCoordinator.createDimensionScope(producerScopeId);
|
|
638
|
-
|
|
639
|
-
const producerPromise = producerAgent.produce(analysisReport, dimConfig, projectInfo, {
|
|
640
|
-
sessionId,
|
|
641
|
-
memoryCoordinator,
|
|
642
|
-
});
|
|
643
|
-
|
|
644
|
-
producerResult = await Promise.race([
|
|
645
|
-
producerPromise,
|
|
646
|
-
new Promise((_, reject) =>
|
|
647
|
-
setTimeout(() => reject(new Error(`Producer timeout for "${dimId}"`)), 180_000)
|
|
648
|
-
),
|
|
649
|
-
]);
|
|
650
|
-
|
|
651
|
-
candidateResults.created += producerResult.candidateCount;
|
|
652
|
-
// 更新 dimensionCandidates 以包含 Producer 结果
|
|
653
|
-
dimensionCandidates[dimId].producerResult = producerResult;
|
|
654
|
-
logger.info(
|
|
655
|
-
`[Bootstrap-v3] Producer "${dimId}": ${producerResult.candidateCount} candidates (${Date.now() - dimStartTime}ms total)`
|
|
656
|
-
);
|
|
657
|
-
} catch (producerErr) {
|
|
658
|
-
logger.error(
|
|
659
|
-
`[Bootstrap-v3] Producer "${dimId}" failed: ${producerErr.message} — Analyst result preserved for Skill generation`
|
|
779
|
+
`[Insight-v3] analysisText 补强 "${dimId}": ${originalLen} → ${analysisReport.analysisText.length} chars ` +
|
|
780
|
+
`(from ${findings.length} findings)`,
|
|
660
781
|
);
|
|
661
|
-
candidateResults.errors.push({ dimId, error: `Producer: ${producerErr.message}` });
|
|
662
|
-
|
|
663
|
-
// v5.1: 超时后异步监听实际结果,避免 ghost candidates 永远不被计数
|
|
664
|
-
if (producerErr.message.includes('timeout')) {
|
|
665
|
-
const dimIdRef = dimId;
|
|
666
|
-
// producerPromise 仍在后台执行 — 监听完成后更新统计
|
|
667
|
-
// biome-ignore lint: 故意 fire-and-forget
|
|
668
|
-
producerPromise
|
|
669
|
-
?.then((actualResult) => {
|
|
670
|
-
const count = actualResult?.candidateCount || 0;
|
|
671
|
-
if (count > 0) {
|
|
672
|
-
logger.info(
|
|
673
|
-
`[Bootstrap-v3] Producer "${dimIdRef}" completed post-timeout: ${count} candidates (ghost → reconciled)`
|
|
674
|
-
);
|
|
675
|
-
if (dimensionStats[dimIdRef]) {
|
|
676
|
-
dimensionStats[dimIdRef].candidateCount = count;
|
|
677
|
-
}
|
|
678
|
-
candidateResults.created += count;
|
|
679
|
-
dimensionCandidates[dimIdRef].producerResult = actualResult;
|
|
680
|
-
}
|
|
681
|
-
})
|
|
682
|
-
.catch((finalErr) => {
|
|
683
|
-
logger.warn(
|
|
684
|
-
`[Bootstrap-v3] Producer "${dimIdRef}" also failed post-timeout: ${finalErr.message}`
|
|
685
|
-
);
|
|
686
|
-
});
|
|
687
|
-
}
|
|
688
782
|
}
|
|
689
783
|
}
|
|
690
784
|
|
|
691
|
-
// ──
|
|
785
|
+
// ── DimensionDigest ──
|
|
692
786
|
const digest = parseDimensionDigest(producerResult.reply) || {
|
|
693
787
|
summary: `v3 分析: ${analysisReport.analysisText.substring(0, 200)}...`,
|
|
694
788
|
candidateCount: producerResult.candidateCount,
|
|
@@ -697,21 +791,19 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
697
791
|
gaps: [],
|
|
698
792
|
};
|
|
699
793
|
dimContext.addDimensionDigest(dimId, digest);
|
|
700
|
-
|
|
701
|
-
// v4.0: 同步 digest 到 SessionStore
|
|
702
794
|
sessionStore.addDimensionDigest(dimId, digest);
|
|
703
795
|
|
|
704
|
-
//
|
|
796
|
+
// 候选摘要记录到 DimensionContext + SessionStore
|
|
705
797
|
for (const tc of producerResult.toolCalls || []) {
|
|
706
798
|
const tool = tc.tool || tc.name;
|
|
707
799
|
if (tool === 'submit_knowledge' || tool === 'submit_with_check') {
|
|
800
|
+
const args = tc.params || tc.args || {};
|
|
708
801
|
const candidateSummary = {
|
|
709
|
-
title:
|
|
710
|
-
subTopic:
|
|
711
|
-
summary:
|
|
802
|
+
title: args.title || '',
|
|
803
|
+
subTopic: args.category || '',
|
|
804
|
+
summary: args.summary || '',
|
|
712
805
|
};
|
|
713
806
|
dimContext.addSubmittedCandidate(dimId, candidateSummary);
|
|
714
|
-
// v4.0: 同步到 SessionStore
|
|
715
807
|
sessionStore.addSubmittedCandidate(dimId, candidateSummary);
|
|
716
808
|
}
|
|
717
809
|
}
|
|
@@ -720,46 +812,41 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
720
812
|
type: needsCandidates ? 'candidate' : 'skill',
|
|
721
813
|
extracted: producerResult.candidateCount,
|
|
722
814
|
created: producerResult.candidateCount,
|
|
723
|
-
// v5.1: 标记 Skill 待生成,Dashboard 可据此避免显示 "无匹配内容"
|
|
724
815
|
skillPending: dimConfig.skillWorthy && producerResult.candidateCount === 0,
|
|
725
|
-
status: 'v3-complete',
|
|
816
|
+
status: 'v3-pipeline-complete',
|
|
817
|
+
degraded: runResult?.degraded || false,
|
|
726
818
|
durationMs: Date.now() - dimStartTime,
|
|
727
|
-
toolCallCount:
|
|
728
|
-
|
|
729
|
-
source: 'internal-agent',
|
|
819
|
+
toolCallCount: runtimeToolCalls.length,
|
|
820
|
+
source: 'enhanced-pipeline-strategy',
|
|
730
821
|
});
|
|
731
822
|
|
|
732
|
-
|
|
733
|
-
const analystTokens = analysisReport.metadata?.tokenUsage || { input: 0, output: 0 };
|
|
734
|
-
const producerTokens = producerResult.tokenUsage || { input: 0, output: 0 };
|
|
735
|
-
const dimTokenUsage = {
|
|
736
|
-
input: (analystTokens.input || 0) + (producerTokens.input || 0),
|
|
737
|
-
output: (analystTokens.output || 0) + (producerTokens.output || 0),
|
|
738
|
-
};
|
|
739
|
-
|
|
823
|
+
const dimTokenUsage = combinedTokenUsage;
|
|
740
824
|
const dimResult = {
|
|
741
825
|
candidateCount: producerResult.candidateCount,
|
|
742
826
|
rejectedCount: producerResult.rejectedCount || 0,
|
|
743
827
|
analysisChars: analysisReport.analysisText.length,
|
|
744
828
|
referencedFiles: analysisReport.referencedFiles.length,
|
|
745
829
|
durationMs: Date.now() - dimStartTime,
|
|
746
|
-
toolCallCount:
|
|
747
|
-
(analysisReport.metadata?.toolCallCount || 0) + (producerResult.toolCalls?.length || 0),
|
|
830
|
+
toolCallCount: runtimeToolCalls.length,
|
|
748
831
|
tokenUsage: dimTokenUsage,
|
|
749
|
-
// P3+: 保存 analysisText 供 checkpoint 恢复后 Skill 生成使用
|
|
750
832
|
analysisText: analysisReport.analysisText,
|
|
751
833
|
referencedFilesList: analysisReport.referencedFiles || [],
|
|
752
834
|
};
|
|
753
835
|
|
|
754
|
-
// P4.2: 记录维度统计
|
|
755
836
|
dimensionStats[dimId] = dimResult;
|
|
756
837
|
|
|
757
|
-
// P3: 保存 checkpoint
|
|
758
|
-
|
|
838
|
+
// P3: 保存 checkpoint — 仅当有实质分析内容时(避免 degraded/空结果污染后续 run)
|
|
839
|
+
if (analysisReport.analysisText.length >= 50) {
|
|
840
|
+
await saveDimensionCheckpoint(projectRoot, sessionId, dimId, dimResult, digest);
|
|
841
|
+
} else {
|
|
842
|
+
logger.warn(
|
|
843
|
+
`[Insight-v3] ⚠ 跳过 checkpoint 保存: "${dimId}" analysisText 过短 (${analysisReport.analysisText.length} chars)`
|
|
844
|
+
);
|
|
845
|
+
}
|
|
759
846
|
|
|
760
847
|
return dimResult;
|
|
761
848
|
} catch (err) {
|
|
762
|
-
logger.error(`[
|
|
849
|
+
logger.error(`[Insight-v3] Dimension "${dimId}" failed: ${err.message}`);
|
|
763
850
|
candidateResults.errors.push({ dimId, error: err.message });
|
|
764
851
|
emitter.emitDimensionComplete(dimId, { type: 'error', reason: err.message });
|
|
765
852
|
return { candidateCount: 0, error: err.message };
|
|
@@ -789,7 +876,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
789
876
|
const tierStats = [...tierResults.values()];
|
|
790
877
|
const totalCandidates = tierStats.reduce((s, r) => s + (r.candidateCount || 0), 0);
|
|
791
878
|
logger.info(
|
|
792
|
-
`[
|
|
879
|
+
`[Insight-v3] Tier ${tierIndex + 1} complete: ${tierResults.size} dimensions, ${totalCandidates} candidates`
|
|
793
880
|
);
|
|
794
881
|
|
|
795
882
|
// v4.0: Tier 级 Reflection — 综合本 Tier 所有维度的发现
|
|
@@ -797,29 +884,29 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
797
884
|
const reflection = buildTierReflection(tierIndex, tierResults, sessionStore);
|
|
798
885
|
sessionStore.addTierReflection(tierIndex, reflection);
|
|
799
886
|
logger.info(
|
|
800
|
-
`[
|
|
887
|
+
`[Insight-v3] Tier ${tierIndex + 1} reflection: ` +
|
|
801
888
|
`${reflection.topFindings.length} top findings, ` +
|
|
802
889
|
`${reflection.crossDimensionPatterns.length} patterns`
|
|
803
890
|
);
|
|
804
891
|
} catch (refErr) {
|
|
805
|
-
logger.warn(`[
|
|
892
|
+
logger.warn(`[Insight-v3] Tier ${tierIndex + 1} reflection failed: ${refErr.message}`);
|
|
806
893
|
}
|
|
807
894
|
},
|
|
808
895
|
});
|
|
809
896
|
|
|
810
897
|
logger.info(
|
|
811
|
-
`[
|
|
898
|
+
`[Insight-v3] All tiers complete: ${results.size} dimensions in ${Date.now() - t0}ms`
|
|
812
899
|
);
|
|
813
900
|
// v4.0: 记录 SessionStore 统计
|
|
814
901
|
const emStats = sessionStore.getStats();
|
|
815
902
|
logger.info(
|
|
816
|
-
`[
|
|
903
|
+
`[Insight-v3] Memory stats: ${emStats.completedDimensions} dims, ` +
|
|
817
904
|
`${emStats.totalFindings} findings, ${emStats.referencedFiles} files, ` +
|
|
818
905
|
`${emStats.crossReferences} cross-refs, ${emStats.tierReflections} reflections`
|
|
819
906
|
);
|
|
820
907
|
if (emStats.cacheStats) {
|
|
821
908
|
logger.info(
|
|
822
|
-
`[
|
|
909
|
+
`[Insight-v3] Cache stats: ${emStats.cacheStats.hitRate} hit rate, ` +
|
|
823
910
|
`${emStats.cacheStats.searchCacheSize} searches, ${emStats.cacheStats.fileCacheSize} files`
|
|
824
911
|
);
|
|
825
912
|
}
|
|
@@ -836,7 +923,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
836
923
|
await executeDimension(dimId);
|
|
837
924
|
}
|
|
838
925
|
}
|
|
839
|
-
logger.info(`[
|
|
926
|
+
logger.info(`[Insight-v3] Serial execution complete in ${Date.now() - t0}ms`);
|
|
840
927
|
}
|
|
841
928
|
|
|
842
929
|
// ═══════════════════════════════════════════════════════════
|
|
@@ -893,7 +980,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
893
980
|
}
|
|
894
981
|
effectiveText = synthesized.join('\n');
|
|
895
982
|
logger.info(
|
|
896
|
-
`[
|
|
983
|
+
`[Insight-v3] Skill "${dim.id}": analysisText too short (${analysisText.trim().length} chars), ` +
|
|
897
984
|
`synthesized from ${keyFindings.length} findings → ${effectiveText.length} chars`
|
|
898
985
|
);
|
|
899
986
|
}
|
|
@@ -917,14 +1004,14 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
917
1004
|
emitter.emitDimensionFailed(dim.id, new Error(result.error));
|
|
918
1005
|
}
|
|
919
1006
|
} catch (err) {
|
|
920
|
-
logger.warn(`[
|
|
1007
|
+
logger.warn(`[Insight-v3] Skill generation failed for "${dim.id}": ${err.message}`);
|
|
921
1008
|
skillResults.failed++;
|
|
922
1009
|
skillResults.errors.push({ dimId: dim.id, error: err.message });
|
|
923
1010
|
emitter.emitDimensionFailed(dim.id, err);
|
|
924
1011
|
}
|
|
925
1012
|
}
|
|
926
1013
|
} catch (e) {
|
|
927
|
-
logger.warn(`[
|
|
1014
|
+
logger.warn(`[Insight-v3] Skill generation module import failed: ${e.message}`);
|
|
928
1015
|
}
|
|
929
1016
|
|
|
930
1017
|
// ═══════════════════════════════════════════════════════════
|
|
@@ -958,13 +1045,13 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
958
1045
|
if (allCandidates.length > 0) {
|
|
959
1046
|
const relResult = ceg.populateFromCandidateRelations(allCandidates);
|
|
960
1047
|
logger.info(
|
|
961
|
-
`[
|
|
1048
|
+
`[Insight-v3] Code Entity Graph relations: ${relResult.edgesCreated} edges from ${allCandidates.length} candidates (${relResult.durationMs}ms)`
|
|
962
1049
|
);
|
|
963
1050
|
}
|
|
964
1051
|
}
|
|
965
1052
|
} catch (cegErr) {
|
|
966
1053
|
logger.warn(
|
|
967
|
-
`[
|
|
1054
|
+
`[Insight-v3] Code Entity Graph relations failed (non-blocking): ${cegErr.message}`
|
|
968
1055
|
);
|
|
969
1056
|
}
|
|
970
1057
|
|
|
@@ -978,7 +1065,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
978
1065
|
try {
|
|
979
1066
|
const db = ctx.container.get('database');
|
|
980
1067
|
if (db) {
|
|
981
|
-
const semanticMemory = new
|
|
1068
|
+
const semanticMemory = new PersistentMemory(db, { logger });
|
|
982
1069
|
const consolidator = new EpisodicConsolidator(semanticMemory, { logger });
|
|
983
1070
|
|
|
984
1071
|
consolidationResult = consolidator.consolidate(sessionStore, {
|
|
@@ -988,18 +1075,18 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
988
1075
|
|
|
989
1076
|
const smStats = semanticMemory.getStats();
|
|
990
1077
|
logger.info(
|
|
991
|
-
`[
|
|
1078
|
+
`[Insight-v3] Semantic Memory consolidation: ` +
|
|
992
1079
|
`+${consolidationResult.total.added} ADD, ` +
|
|
993
1080
|
`~${consolidationResult.total.updated} UPDATE, ` +
|
|
994
1081
|
`⊕${consolidationResult.total.merged} MERGE | ` +
|
|
995
1082
|
`Total: ${smStats.total} memories (avg importance: ${smStats.avgImportance})`
|
|
996
1083
|
);
|
|
997
1084
|
} else {
|
|
998
|
-
logger.warn('[
|
|
1085
|
+
logger.warn('[Insight-v3] Database not available — skipping Semantic Memory consolidation');
|
|
999
1086
|
}
|
|
1000
1087
|
} catch (consolidateErr) {
|
|
1001
1088
|
logger.warn(
|
|
1002
|
-
`[
|
|
1089
|
+
`[Insight-v3] Semantic Memory consolidation failed (non-blocking): ${consolidateErr.message}`
|
|
1003
1090
|
);
|
|
1004
1091
|
}
|
|
1005
1092
|
|
|
@@ -1023,7 +1110,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
1023
1110
|
|
|
1024
1111
|
logger.info(
|
|
1025
1112
|
[
|
|
1026
|
-
`[
|
|
1113
|
+
`[Insight-v3] ═══ Pipeline complete ═══`,
|
|
1027
1114
|
isIncremental
|
|
1028
1115
|
? ` Mode: INCREMENTAL (${incrementalPlan.affectedDimensions.length} affected, ${incrementalSkippedDims.length} skipped)`
|
|
1029
1116
|
: '',
|
|
@@ -1136,9 +1223,9 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
1136
1223
|
path.join(reportDir, 'bootstrap-report.json'),
|
|
1137
1224
|
JSON.stringify(report, null, 2)
|
|
1138
1225
|
);
|
|
1139
|
-
logger.info(`[
|
|
1226
|
+
logger.info(`[Insight-v3] 📊 Bootstrap report saved to .autosnippet/bootstrap-report.json`);
|
|
1140
1227
|
} catch (reportErr) {
|
|
1141
|
-
logger.warn(`[
|
|
1228
|
+
logger.warn(`[Insight-v3] Bootstrap report generation failed: ${reportErr.message}`);
|
|
1142
1229
|
}
|
|
1143
1230
|
|
|
1144
1231
|
// P3: 成功完成后清理 checkpoints
|
|
@@ -1161,15 +1248,15 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
1161
1248
|
},
|
|
1162
1249
|
plan: isIncremental ? incrementalPlan : null,
|
|
1163
1250
|
});
|
|
1164
|
-
logger.info(`[
|
|
1251
|
+
logger.info(`[Insight-v3] 📸 Snapshot saved: ${snapshotId}`);
|
|
1165
1252
|
}
|
|
1166
1253
|
} catch (snapErr) {
|
|
1167
|
-
logger.warn(`[
|
|
1254
|
+
logger.warn(`[Insight-v3] Snapshot save failed (non-blocking): ${snapErr.message}`);
|
|
1168
1255
|
}
|
|
1169
1256
|
|
|
1170
1257
|
// 释放文件缓存
|
|
1171
1258
|
allFiles = null;
|
|
1172
|
-
|
|
1259
|
+
ctx.container.singletons._fileCache = null;
|
|
1173
1260
|
|
|
1174
1261
|
// ── Cursor Delivery: 生成 4 通道交付物料 ──
|
|
1175
1262
|
try {
|
|
@@ -1179,7 +1266,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
1179
1266
|
const pipeline = container.get('cursorDeliveryPipeline');
|
|
1180
1267
|
const deliveryResult = await pipeline.deliver();
|
|
1181
1268
|
logger.info(
|
|
1182
|
-
`[
|
|
1269
|
+
`[Insight-v3] 🚀 Cursor Delivery complete — ` +
|
|
1183
1270
|
`A: ${deliveryResult.channelA.rulesCount} rules, ` +
|
|
1184
1271
|
`B: ${deliveryResult.channelB.topicCount} topics, ` +
|
|
1185
1272
|
`C: ${deliveryResult.channelC.synced} skills, ` +
|
|
@@ -1188,7 +1275,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
1188
1275
|
);
|
|
1189
1276
|
}
|
|
1190
1277
|
} catch (deliveryErr) {
|
|
1191
|
-
logger.warn(`[
|
|
1278
|
+
logger.warn(`[Insight-v3] Cursor Delivery failed (non-blocking): ${deliveryErr.message}`);
|
|
1192
1279
|
}
|
|
1193
1280
|
|
|
1194
1281
|
// ── Repo Wiki: 自动生成项目文档 Wiki ──
|
|
@@ -1265,7 +1352,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
1265
1352
|
const wikiResult = await wiki.generate();
|
|
1266
1353
|
if (wikiResult.success) {
|
|
1267
1354
|
logger.info(
|
|
1268
|
-
`[
|
|
1355
|
+
`[Insight-v3] 📖 Wiki generated — ${wikiResult.filesGenerated} files, ` +
|
|
1269
1356
|
`AI: ${wikiResult.aiComposed || 0}, Synced: ${wikiResult.syncedDocs || 0}, ` +
|
|
1270
1357
|
`Dedup removed: ${wikiResult.dedup?.removed?.length || 0}`
|
|
1271
1358
|
);
|
|
@@ -1289,7 +1376,7 @@ export async function fillDimensionsV3(fillContext) {
|
|
|
1289
1376
|
} catch { /* non-critical */ }
|
|
1290
1377
|
}
|
|
1291
1378
|
} catch (wikiErr) {
|
|
1292
|
-
logger.warn(`[
|
|
1379
|
+
logger.warn(`[Insight-v3] Wiki generation failed (non-blocking): ${wikiErr.message}`);
|
|
1293
1380
|
try {
|
|
1294
1381
|
const wikiRoute = await import('../../../../../http/routes/wiki.js');
|
|
1295
1382
|
wikiRoute.patchWikiTask?.({
|