autosnippet 3.3.7 → 3.3.8
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/README.md +1 -0
- package/dashboard/dist/assets/icons-BMNb0V6L.js +1 -0
- package/dashboard/dist/assets/index-DHJ1Dj7u.css +1 -0
- package/dashboard/dist/assets/index-DV8biUkH.js +112 -0
- package/dashboard/dist/index.html +3 -3
- package/dist/bin/cli.js +7 -4
- package/dist/lib/agent/core/ChatAgentPrompts.js +57 -21
- package/dist/lib/agent/core/LoopContext.d.ts +1 -0
- package/dist/lib/agent/core/ToolExecutionPipeline.js +13 -0
- package/dist/lib/agent/memory/ActiveContext.d.ts +0 -2
- package/dist/lib/agent/memory/ActiveContext.js +0 -2
- package/dist/lib/agent/memory/MemoryEmbeddingStore.d.ts +49 -0
- package/dist/lib/agent/memory/MemoryEmbeddingStore.js +159 -0
- package/dist/lib/agent/memory/MemoryRetriever.d.ts +2 -0
- package/dist/lib/agent/memory/MemoryRetriever.js +25 -11
- package/dist/lib/agent/memory/MemoryStore.d.ts +8 -41
- package/dist/lib/agent/memory/MemoryStore.js +196 -261
- package/dist/lib/agent/memory/PersistentMemory.d.ts +2 -0
- package/dist/lib/agent/memory/PersistentMemory.js +4 -5
- package/dist/lib/agent/memory/SessionStore.d.ts +0 -2
- package/dist/lib/agent/memory/SessionStore.js +0 -2
- package/dist/lib/agent/tools/ast-graph.js +21 -19
- package/dist/lib/agent/tools/infrastructure.js +3 -2
- package/dist/lib/agent/tools/project-access.d.ts +2 -2
- package/dist/lib/agent/tools/project-access.js +5 -4
- package/dist/lib/bootstrap.js +2 -1
- package/dist/lib/cli/AiScanService.js +4 -17
- package/dist/lib/cli/KnowledgeSyncService.d.ts +7 -37
- package/dist/lib/cli/KnowledgeSyncService.js +23 -51
- package/dist/lib/core/ast/ProjectGraph.js +5 -27
- package/dist/lib/core/discovery/CustomConfigDiscoverer.d.ts +0 -2
- package/dist/lib/core/discovery/CustomConfigDiscoverer.js +0 -2
- package/dist/lib/domain/dimension/DimensionRegistry.d.ts +0 -2
- package/dist/lib/domain/dimension/DimensionRegistry.js +0 -2
- package/dist/lib/domain/dimension/DimensionSop.js +44 -33
- package/dist/lib/domain/dimension/UnifiedDimension.d.ts +0 -2
- package/dist/lib/domain/dimension/UnifiedDimension.js +0 -2
- package/dist/lib/domain/knowledge/Lifecycle.d.ts +26 -0
- package/dist/lib/domain/knowledge/Lifecycle.js +42 -0
- package/dist/lib/domain/knowledge/index.d.ts +2 -1
- package/dist/lib/domain/knowledge/index.js +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.d.ts +2 -1
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +102 -153
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +33 -16
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +41 -37
- package/dist/lib/external/mcp/handlers/bootstrap-external.js +1 -1
- package/dist/lib/external/mcp/handlers/dimension-complete-external.js +7 -3
- package/dist/lib/external/mcp/handlers/evolve-external.d.ts +1 -0
- package/dist/lib/external/mcp/handlers/evolve-external.js +13 -16
- package/dist/lib/external/mcp/handlers/guard.js +15 -24
- package/dist/lib/external/mcp/handlers/panorama.js +9 -9
- package/dist/lib/external/mcp/handlers/rescan-external.js +7 -6
- package/dist/lib/external/mcp/handlers/rescan-internal.js +9 -5
- package/dist/lib/external/mcp/handlers/search.js +3 -1
- package/dist/lib/external/mcp/handlers/skill.js +4 -4
- package/dist/lib/external/mcp/handlers/structure.js +8 -12
- package/dist/lib/external/mcp/handlers/system.js +10 -34
- package/dist/lib/http/routes/ai.js +11 -13
- package/dist/lib/http/routes/guardReport.js +3 -5
- package/dist/lib/http/routes/panorama.js +12 -12
- package/dist/lib/http/routes/recipes.js +59 -8
- package/dist/lib/http/routes/remote.js +3 -13
- package/dist/lib/http/routes/search.js +11 -8
- package/dist/lib/infrastructure/audit/AuditLogger.d.ts +20 -3
- package/dist/lib/infrastructure/audit/AuditStore.d.ts +28 -29
- package/dist/lib/infrastructure/audit/AuditStore.js +81 -88
- package/dist/lib/infrastructure/database/drizzle/schema.d.ts +180 -2
- package/dist/lib/infrastructure/database/drizzle/schema.js +23 -3
- package/dist/lib/injection/ServiceContainer.js +7 -4
- package/dist/lib/injection/ServiceMap.d.ts +20 -0
- package/dist/lib/injection/modules/AppModule.js +2 -1
- package/dist/lib/injection/modules/GuardModule.js +5 -5
- package/dist/lib/injection/modules/InfraModule.js +60 -0
- package/dist/lib/injection/modules/KnowledgeModule.js +86 -51
- package/dist/lib/injection/modules/PanoramaModule.js +16 -10
- package/dist/lib/injection/modules/VectorModule.js +3 -0
- package/dist/lib/repository/audit/AuditRepository.d.ts +107 -0
- package/dist/lib/repository/audit/AuditRepository.js +272 -0
- package/dist/lib/repository/base/RepositoryBase.d.ts +46 -0
- package/dist/lib/repository/base/RepositoryBase.js +32 -0
- package/dist/lib/repository/bootstrap/BootstrapRepository.d.ts +94 -0
- package/dist/lib/repository/bootstrap/BootstrapRepository.js +246 -0
- package/dist/lib/repository/code/CodeEntityRepository.d.ts +91 -0
- package/dist/lib/repository/code/CodeEntityRepository.js +361 -0
- package/dist/lib/repository/delivery/DeliveryRepoAdapter.d.ts +39 -0
- package/dist/lib/repository/delivery/DeliveryRepoAdapter.js +23 -0
- package/dist/lib/repository/evolution/LifecycleEventRepository.d.ts +51 -0
- package/dist/lib/repository/evolution/LifecycleEventRepository.js +119 -0
- package/dist/lib/repository/evolution/ProposalRepository.d.ts +9 -12
- package/dist/lib/repository/evolution/ProposalRepository.js +114 -57
- package/dist/lib/repository/guard/GuardViolationRepository.d.ts +104 -0
- package/dist/lib/repository/guard/GuardViolationRepository.js +217 -0
- package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.d.ts +129 -0
- package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.js +475 -0
- package/dist/lib/repository/knowledge/KnowledgeFileStore.d.ts +39 -0
- package/dist/lib/repository/knowledge/KnowledgeFileStore.js +12 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +295 -11
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +608 -13
- package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.d.ts +61 -0
- package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.js +156 -0
- package/dist/lib/repository/memory/MemoryRepository.d.ts +90 -0
- package/dist/lib/repository/memory/MemoryRepository.js +260 -0
- package/dist/lib/repository/search/SearchRepoAdapter.d.ts +92 -0
- package/dist/lib/repository/search/SearchRepoAdapter.js +124 -0
- package/dist/lib/repository/session/SessionRepository.d.ts +46 -0
- package/dist/lib/repository/session/SessionRepository.js +110 -0
- package/dist/lib/repository/sourceref/RecipeSourceRefRepository.d.ts +66 -0
- package/dist/lib/repository/sourceref/RecipeSourceRefRepository.js +182 -0
- package/dist/lib/repository/sync/SyncRepoAdapter.d.ts +58 -0
- package/dist/lib/repository/sync/SyncRepoAdapter.js +58 -0
- package/dist/lib/service/bootstrap/UiStartupTasks.js +5 -6
- package/dist/lib/service/bootstrap/bootstrap-event-types.d.ts +0 -1
- package/dist/lib/service/bootstrap/bootstrap-event-types.js +0 -1
- package/dist/lib/service/cleanup/CleanupService.js +8 -4
- package/dist/lib/service/delivery/CursorDeliveryPipeline.js +6 -8
- package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +4 -9
- package/dist/lib/service/evolution/ConsolidationAdvisor.js +34 -70
- package/dist/lib/service/evolution/ContentPatcher.d.ts +4 -12
- package/dist/lib/service/evolution/ContentPatcher.js +48 -19
- package/dist/lib/service/evolution/ContradictionDetector.d.ts +3 -7
- package/dist/lib/service/evolution/ContradictionDetector.js +17 -24
- package/dist/lib/service/evolution/DecayDetector.d.ts +10 -9
- package/dist/lib/service/evolution/DecayDetector.js +63 -57
- package/dist/lib/service/evolution/EnhancementSuggester.d.ts +3 -9
- package/dist/lib/service/evolution/EnhancementSuggester.js +42 -86
- package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +4 -4
- package/dist/lib/service/evolution/KnowledgeMetabolism.js +102 -71
- package/dist/lib/service/evolution/ProposalExecutor.d.ts +5 -12
- package/dist/lib/service/evolution/ProposalExecutor.js +64 -69
- package/dist/lib/service/evolution/RecipeLifecycleSupervisor.d.ts +9 -14
- package/dist/lib/service/evolution/RecipeLifecycleSupervisor.js +94 -155
- package/dist/lib/service/evolution/RecipeRelevanceAuditor.d.ts +4 -1
- package/dist/lib/service/evolution/RecipeRelevanceAuditor.js +50 -49
- package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +3 -7
- package/dist/lib/service/evolution/RedundancyAnalyzer.js +15 -22
- package/dist/lib/service/evolution/StagingManager.d.ts +6 -15
- package/dist/lib/service/evolution/StagingManager.js +37 -95
- package/dist/lib/service/evolution/createSupersedeProposal.d.ts +1 -1
- package/dist/lib/service/evolution/createSupersedeProposal.js +7 -8
- package/dist/lib/service/guard/CoverageAnalyzer.d.ts +3 -7
- package/dist/lib/service/guard/CoverageAnalyzer.js +9 -11
- package/dist/lib/service/guard/GuardCheckEngine.d.ts +3 -0
- package/dist/lib/service/guard/GuardCheckEngine.js +14 -22
- package/dist/lib/service/guard/ReverseGuard.d.ts +4 -7
- package/dist/lib/service/guard/ReverseGuard.js +21 -31
- package/dist/lib/service/guard/ViolationsStore.d.ts +15 -21
- package/dist/lib/service/guard/ViolationsStore.js +75 -69
- package/dist/lib/service/knowledge/CodeEntityGraph.d.ts +39 -63
- package/dist/lib/service/knowledge/CodeEntityGraph.js +418 -512
- package/dist/lib/service/knowledge/ConfidenceRouter.js +18 -9
- package/dist/lib/service/knowledge/KnowledgeFileWriter.d.ts +2 -1
- package/dist/lib/service/knowledge/KnowledgeGraphService.d.ts +18 -60
- package/dist/lib/service/knowledge/KnowledgeGraphService.js +58 -109
- package/dist/lib/service/knowledge/KnowledgeService.d.ts +15 -1
- package/dist/lib/service/knowledge/KnowledgeService.js +76 -38
- package/dist/lib/service/knowledge/RecipeProductionGateway.d.ts +0 -2
- package/dist/lib/service/knowledge/RecipeProductionGateway.js +0 -2
- package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +5 -13
- package/dist/lib/service/knowledge/SourceRefReconciler.js +58 -78
- package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +5 -3
- package/dist/lib/service/panorama/CouplingAnalyzer.js +102 -39
- package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +7 -4
- package/dist/lib/service/panorama/DimensionAnalyzer.js +72 -25
- package/dist/lib/service/panorama/LayerInferrer.js +1 -1
- package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +7 -6
- package/dist/lib/service/panorama/ModuleDiscoverer.js +174 -82
- package/dist/lib/service/panorama/PanoramaAggregator.d.ts +10 -3
- package/dist/lib/service/panorama/PanoramaAggregator.js +67 -79
- package/dist/lib/service/panorama/PanoramaScanner.d.ts +5 -1
- package/dist/lib/service/panorama/PanoramaScanner.js +32 -31
- package/dist/lib/service/panorama/PanoramaService.d.ts +11 -8
- package/dist/lib/service/panorama/PanoramaService.js +41 -66
- package/dist/lib/service/panorama/PanoramaTypes.d.ts +3 -0
- package/dist/lib/service/panorama/RoleRefiner.d.ts +8 -5
- package/dist/lib/service/panorama/RoleRefiner.js +52 -283
- package/dist/lib/service/panorama/TechStackProfiler.js +7 -119
- package/dist/lib/service/quality/QualityScorer.d.ts +45 -26
- package/dist/lib/service/quality/QualityScorer.js +157 -83
- package/dist/lib/service/search/SearchEngine.d.ts +1 -0
- package/dist/lib/service/search/SearchEngine.js +32 -37
- package/dist/lib/service/signal/HitRecorder.js +5 -5
- package/dist/lib/service/skills/RuleRecallStrategy.js +7 -3
- package/dist/lib/service/skills/SignalCollector.d.ts +5 -8
- package/dist/lib/service/skills/SignalCollector.js +28 -55
- package/dist/lib/service/skills/SkillAdvisor.d.ts +7 -13
- package/dist/lib/service/skills/SkillAdvisor.js +30 -79
- package/dist/lib/service/vector/SyncCoordinator.d.ts +3 -1
- package/dist/lib/service/vector/SyncCoordinator.js +25 -3
- package/dist/lib/service/vector/VectorService.d.ts +2 -0
- package/dist/lib/service/vector/VectorService.js +3 -0
- package/dist/lib/service/wiki/WikiGenerator.js +1 -1
- package/dist/lib/shared/LanguageProfiles.d.ts +109 -0
- package/dist/lib/shared/LanguageProfiles.js +939 -0
- package/dist/lib/shared/LanguageService.d.ts +6 -0
- package/dist/lib/shared/LanguageService.js +16 -0
- package/dist/lib/shared/constants.d.ts +19 -19
- package/dist/lib/shared/constants.js +10 -10
- package/dist/lib/shared/schemas/mcp-tools.d.ts +1 -1
- package/dist/lib/types/project-snapshot-builder.d.ts +0 -1
- package/dist/lib/types/project-snapshot-builder.js +0 -1
- package/dist/lib/types/project-snapshot.d.ts +0 -1
- package/dist/lib/types/project-snapshot.js +0 -1
- package/dist/lib/types/snapshot-views.d.ts +0 -2
- package/dist/lib/types/snapshot-views.js +0 -1
- package/package.json +2 -1
- package/dashboard/dist/assets/icons-FHns2ypa.js +0 -1
- package/dashboard/dist/assets/index-BRJv5Y3r.js +0 -135
- package/dashboard/dist/assets/index-DzoB7kxK.css +0 -1
- package/dist/lib/repository/base/BaseRepository.d.ts +0 -53
- package/dist/lib/repository/base/BaseRepository.js +0 -226
|
@@ -8,12 +8,16 @@
|
|
|
8
8
|
* 4. 提供增量 diff 计算
|
|
9
9
|
*
|
|
10
10
|
* 存储: SQLite bootstrap_snapshots + bootstrap_dim_files 表
|
|
11
|
+
* 所有操作使用 Drizzle 类型安全 API。
|
|
11
12
|
*
|
|
12
13
|
* @module pipeline/BootstrapSnapshot
|
|
13
14
|
*/
|
|
14
15
|
import { createHash, randomUUID } from 'node:crypto';
|
|
15
16
|
import { readFileSync } from 'node:fs';
|
|
16
17
|
import { relative } from 'node:path';
|
|
18
|
+
import { and, desc, eq, sql } from 'drizzle-orm';
|
|
19
|
+
import { getDrizzle } from '../../../../../infrastructure/database/drizzle/index.js';
|
|
20
|
+
import { bootstrapDimFiles, bootstrapSnapshots, } from '../../../../../infrastructure/database/drizzle/schema.js';
|
|
17
21
|
// ──────────────────────────────────────────────────────────────
|
|
18
22
|
// 常量
|
|
19
23
|
// ──────────────────────────────────────────────────────────────
|
|
@@ -25,21 +29,18 @@ const FULL_REBUILD_THRESHOLD = 0.5;
|
|
|
25
29
|
// BootstrapSnapshot 类
|
|
26
30
|
// ──────────────────────────────────────────────────────────────
|
|
27
31
|
export class BootstrapSnapshot {
|
|
28
|
-
#
|
|
32
|
+
#drizzle;
|
|
29
33
|
#logger;
|
|
30
|
-
|
|
31
|
-
/** @param db better-sqlite3 实例 */
|
|
34
|
+
/** @param db DatabaseConnection 或 better-sqlite3 实例 */
|
|
32
35
|
constructor(db, { logger } = {}) {
|
|
33
36
|
if (!db) {
|
|
34
37
|
throw new Error('BootstrapSnapshot requires a database instance');
|
|
35
38
|
}
|
|
36
|
-
this.#
|
|
37
|
-
typeof db?.
|
|
38
|
-
? db.
|
|
39
|
-
:
|
|
39
|
+
this.#drizzle =
|
|
40
|
+
typeof db?.getDrizzle === 'function'
|
|
41
|
+
? db.getDrizzle()
|
|
42
|
+
: getDrizzle();
|
|
40
43
|
this.#logger = logger || null;
|
|
41
|
-
this.#ensureTable();
|
|
42
|
-
this.#prepareStatements();
|
|
43
44
|
}
|
|
44
45
|
// ─── 快照保存 ─────────────────────────────────────────
|
|
45
46
|
/**
|
|
@@ -77,28 +78,30 @@ export class BootstrapSnapshot {
|
|
|
77
78
|
durationMs: stat.durationMs || 0,
|
|
78
79
|
};
|
|
79
80
|
}
|
|
80
|
-
//
|
|
81
|
-
|
|
81
|
+
// 事务保存(Drizzle 类型安全)
|
|
82
|
+
this.#drizzle.transaction((tx) => {
|
|
82
83
|
// 主记录
|
|
83
|
-
|
|
84
|
+
tx.insert(bootstrapSnapshots)
|
|
85
|
+
.values({
|
|
84
86
|
id,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
87
|
+
sessionId: sessionId || null,
|
|
88
|
+
projectRoot,
|
|
89
|
+
createdAt: now,
|
|
90
|
+
durationMs: meta.durationMs || 0,
|
|
91
|
+
fileCount: allFiles.length,
|
|
92
|
+
dimensionCount: Object.keys(dimensionStats || {}).length,
|
|
93
|
+
candidateCount: meta.candidateCount || 0,
|
|
94
|
+
primaryLang: meta.primaryLang || null,
|
|
95
|
+
fileHashes: JSON.stringify(fileHashes),
|
|
96
|
+
dimensionMeta: JSON.stringify(dimensionMeta),
|
|
97
|
+
episodicData: episodicData ? JSON.stringify(episodicData) : null,
|
|
98
|
+
isIncremental: isIncremental ? 1 : 0,
|
|
99
|
+
parentId: parentId,
|
|
100
|
+
changedFiles: JSON.stringify(changedFiles),
|
|
101
|
+
affectedDims: JSON.stringify(affectedDims),
|
|
100
102
|
status: 'complete',
|
|
101
|
-
})
|
|
103
|
+
})
|
|
104
|
+
.run();
|
|
102
105
|
// 维度-文件关联
|
|
103
106
|
for (const [dimId, stat] of Object.entries(dimensionStats || {})) {
|
|
104
107
|
const refFiles = stat.referencedFilesList || [];
|
|
@@ -108,18 +111,20 @@ export class BootstrapSnapshot {
|
|
|
108
111
|
? relative(projectRoot, filePath)
|
|
109
112
|
: filePath
|
|
110
113
|
: filePath;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
tx.insert(bootstrapDimFiles)
|
|
115
|
+
.values({
|
|
116
|
+
snapshotId: id,
|
|
117
|
+
dimId,
|
|
118
|
+
filePath: rel,
|
|
115
119
|
role: 'referenced',
|
|
116
|
-
})
|
|
120
|
+
})
|
|
121
|
+
.onConflictDoNothing()
|
|
122
|
+
.run();
|
|
117
123
|
}
|
|
118
124
|
}
|
|
119
125
|
// 容量控制: 保留最新 N 个
|
|
120
|
-
this.#enforceCapacity(projectRoot);
|
|
126
|
+
this.#enforceCapacity(projectRoot, tx);
|
|
121
127
|
});
|
|
122
|
-
saveTransaction();
|
|
123
128
|
this.#log(`Snapshot saved: ${id} (${allFiles.length} files, ${Object.keys(dimensionStats || {}).length} dims)`);
|
|
124
129
|
return id;
|
|
125
130
|
}
|
|
@@ -127,9 +132,13 @@ export class BootstrapSnapshot {
|
|
|
127
132
|
/** 清除项目的所有快照 — 用于手动重新冷启动时强制全量 */
|
|
128
133
|
clearProject(projectRoot) {
|
|
129
134
|
try {
|
|
130
|
-
const rows = this.#
|
|
135
|
+
const rows = this.#drizzle
|
|
136
|
+
.select({ id: bootstrapSnapshots.id })
|
|
137
|
+
.from(bootstrapSnapshots)
|
|
138
|
+
.where(eq(bootstrapSnapshots.projectRoot, projectRoot))
|
|
139
|
+
.all();
|
|
131
140
|
for (const row of rows) {
|
|
132
|
-
this.#
|
|
141
|
+
this.#drizzle.delete(bootstrapSnapshots).where(eq(bootstrapSnapshots.id, row.id)).run();
|
|
133
142
|
}
|
|
134
143
|
this.#log(`Cleared ${rows.length} snapshots for project`);
|
|
135
144
|
}
|
|
@@ -144,7 +153,13 @@ export class BootstrapSnapshot {
|
|
|
144
153
|
* @returns 快照数据
|
|
145
154
|
*/
|
|
146
155
|
getLatest(projectRoot) {
|
|
147
|
-
const row = this.#
|
|
156
|
+
const row = this.#drizzle
|
|
157
|
+
.select()
|
|
158
|
+
.from(bootstrapSnapshots)
|
|
159
|
+
.where(and(eq(bootstrapSnapshots.projectRoot, projectRoot), eq(bootstrapSnapshots.status, 'complete')))
|
|
160
|
+
.orderBy(desc(bootstrapSnapshots.createdAt))
|
|
161
|
+
.limit(1)
|
|
162
|
+
.get();
|
|
148
163
|
if (!row) {
|
|
149
164
|
return null;
|
|
150
165
|
}
|
|
@@ -152,7 +167,11 @@ export class BootstrapSnapshot {
|
|
|
152
167
|
}
|
|
153
168
|
/** 根据 ID 加载快照 */
|
|
154
169
|
getById(id) {
|
|
155
|
-
const row = this.#
|
|
170
|
+
const row = this.#drizzle
|
|
171
|
+
.select()
|
|
172
|
+
.from(bootstrapSnapshots)
|
|
173
|
+
.where(eq(bootstrapSnapshots.id, id))
|
|
174
|
+
.get();
|
|
156
175
|
if (!row) {
|
|
157
176
|
return null;
|
|
158
177
|
}
|
|
@@ -160,8 +179,13 @@ export class BootstrapSnapshot {
|
|
|
160
179
|
}
|
|
161
180
|
/** 获取项目的所有快照 (按时间降序) */
|
|
162
181
|
list(projectRoot, limit = 10) {
|
|
163
|
-
return this.#
|
|
164
|
-
.
|
|
182
|
+
return this.#drizzle
|
|
183
|
+
.select()
|
|
184
|
+
.from(bootstrapSnapshots)
|
|
185
|
+
.where(eq(bootstrapSnapshots.projectRoot, projectRoot))
|
|
186
|
+
.orderBy(desc(bootstrapSnapshots.createdAt))
|
|
187
|
+
.limit(limit)
|
|
188
|
+
.all()
|
|
165
189
|
.map((r) => this.#deserialize(r));
|
|
166
190
|
}
|
|
167
191
|
// ─── 增量 Diff 计算 ──────────────────────────────────
|
|
@@ -277,13 +301,20 @@ export class BootstrapSnapshot {
|
|
|
277
301
|
// ─── 维度-文件映射查询 ──────────────────────────────
|
|
278
302
|
/** 获取某个快照中每个维度引用的文件集合 */
|
|
279
303
|
#getDimFileMap(snapshotId) {
|
|
280
|
-
const rows = this.#
|
|
304
|
+
const rows = this.#drizzle
|
|
305
|
+
.select({
|
|
306
|
+
dimId: bootstrapDimFiles.dimId,
|
|
307
|
+
filePath: bootstrapDimFiles.filePath,
|
|
308
|
+
})
|
|
309
|
+
.from(bootstrapDimFiles)
|
|
310
|
+
.where(eq(bootstrapDimFiles.snapshotId, snapshotId))
|
|
311
|
+
.all();
|
|
281
312
|
const map = {};
|
|
282
313
|
for (const row of rows) {
|
|
283
|
-
if (!map[row.
|
|
284
|
-
map[row.
|
|
314
|
+
if (!map[row.dimId]) {
|
|
315
|
+
map[row.dimId] = new Set();
|
|
285
316
|
}
|
|
286
|
-
map[row.
|
|
317
|
+
map[row.dimId].add(row.filePath);
|
|
287
318
|
}
|
|
288
319
|
return map;
|
|
289
320
|
}
|
|
@@ -367,9 +398,17 @@ export class BootstrapSnapshot {
|
|
|
367
398
|
return '';
|
|
368
399
|
}
|
|
369
400
|
}
|
|
370
|
-
#enforceCapacity(projectRoot) {
|
|
401
|
+
#enforceCapacity(projectRoot, db = this.#drizzle) {
|
|
371
402
|
try {
|
|
372
|
-
|
|
403
|
+
db.delete(bootstrapSnapshots)
|
|
404
|
+
.where(sql `${bootstrapSnapshots.projectRoot} = ${projectRoot}
|
|
405
|
+
AND ${bootstrapSnapshots.id} NOT IN (
|
|
406
|
+
SELECT ${bootstrapSnapshots.id} FROM ${bootstrapSnapshots}
|
|
407
|
+
WHERE ${bootstrapSnapshots.projectRoot} = ${projectRoot}
|
|
408
|
+
ORDER BY ${bootstrapSnapshots.createdAt} DESC
|
|
409
|
+
LIMIT ${MAX_SNAPSHOTS}
|
|
410
|
+
)`)
|
|
411
|
+
.run();
|
|
373
412
|
}
|
|
374
413
|
catch (err) {
|
|
375
414
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -379,22 +418,22 @@ export class BootstrapSnapshot {
|
|
|
379
418
|
#deserialize(row) {
|
|
380
419
|
return {
|
|
381
420
|
id: row.id,
|
|
382
|
-
sessionId: row.
|
|
383
|
-
projectRoot: row.
|
|
384
|
-
createdAt: row.
|
|
385
|
-
durationMs: row.
|
|
386
|
-
fileCount: row.
|
|
387
|
-
dimensionCount: row.
|
|
388
|
-
candidateCount: row.
|
|
389
|
-
primaryLang: row.
|
|
390
|
-
fileHashes: this.#safeParseJSON(row.
|
|
391
|
-
dimensionMeta: this.#safeParseJSON(row.
|
|
392
|
-
episodicData: this.#safeParseJSON(row.
|
|
393
|
-
isIncremental: !!row.
|
|
394
|
-
parentId: row.
|
|
395
|
-
changedFiles: this.#safeParseJSON(row.
|
|
396
|
-
affectedDims: this.#safeParseJSON(row.
|
|
397
|
-
status: row.status,
|
|
421
|
+
sessionId: row.sessionId ?? null,
|
|
422
|
+
projectRoot: row.projectRoot,
|
|
423
|
+
createdAt: row.createdAt,
|
|
424
|
+
durationMs: row.durationMs ?? 0,
|
|
425
|
+
fileCount: row.fileCount ?? 0,
|
|
426
|
+
dimensionCount: row.dimensionCount ?? 0,
|
|
427
|
+
candidateCount: row.candidateCount ?? 0,
|
|
428
|
+
primaryLang: row.primaryLang ?? null,
|
|
429
|
+
fileHashes: this.#safeParseJSON(row.fileHashes, {}),
|
|
430
|
+
dimensionMeta: this.#safeParseJSON(row.dimensionMeta, {}),
|
|
431
|
+
episodicData: this.#safeParseJSON(row.episodicData, null),
|
|
432
|
+
isIncremental: !!row.isIncremental,
|
|
433
|
+
parentId: row.parentId ?? null,
|
|
434
|
+
changedFiles: this.#safeParseJSON(row.changedFiles, []),
|
|
435
|
+
affectedDims: this.#safeParseJSON(row.affectedDims, []),
|
|
436
|
+
status: row.status ?? 'complete',
|
|
398
437
|
};
|
|
399
438
|
}
|
|
400
439
|
#safeParseJSON(str, fallback) {
|
|
@@ -410,95 +449,5 @@ export class BootstrapSnapshot {
|
|
|
410
449
|
this.#logger[level](`[BootstrapSnapshot] ${msg}`);
|
|
411
450
|
}
|
|
412
451
|
}
|
|
413
|
-
// ─── 初始化 ───────────────────────────────────────────
|
|
414
|
-
#ensureTable() {
|
|
415
|
-
this.#db.exec(`
|
|
416
|
-
CREATE TABLE IF NOT EXISTS bootstrap_snapshots (
|
|
417
|
-
id TEXT PRIMARY KEY,
|
|
418
|
-
session_id TEXT,
|
|
419
|
-
project_root TEXT NOT NULL,
|
|
420
|
-
created_at TEXT NOT NULL,
|
|
421
|
-
duration_ms INTEGER DEFAULT 0,
|
|
422
|
-
file_count INTEGER DEFAULT 0,
|
|
423
|
-
dimension_count INTEGER DEFAULT 0,
|
|
424
|
-
candidate_count INTEGER DEFAULT 0,
|
|
425
|
-
primary_lang TEXT,
|
|
426
|
-
file_hashes TEXT NOT NULL DEFAULT '{}',
|
|
427
|
-
dimension_meta TEXT NOT NULL DEFAULT '{}',
|
|
428
|
-
episodic_data TEXT,
|
|
429
|
-
is_incremental INTEGER DEFAULT 0,
|
|
430
|
-
parent_id TEXT,
|
|
431
|
-
changed_files TEXT DEFAULT '[]',
|
|
432
|
-
affected_dims TEXT DEFAULT '[]',
|
|
433
|
-
status TEXT DEFAULT 'complete'
|
|
434
|
-
);
|
|
435
|
-
|
|
436
|
-
CREATE TABLE IF NOT EXISTS bootstrap_dim_files (
|
|
437
|
-
snapshot_id TEXT NOT NULL,
|
|
438
|
-
dim_id TEXT NOT NULL,
|
|
439
|
-
file_path TEXT NOT NULL,
|
|
440
|
-
role TEXT DEFAULT 'referenced',
|
|
441
|
-
PRIMARY KEY (snapshot_id, dim_id, file_path),
|
|
442
|
-
FOREIGN KEY (snapshot_id) REFERENCES bootstrap_snapshots(id) ON DELETE CASCADE
|
|
443
|
-
);
|
|
444
|
-
|
|
445
|
-
CREATE INDEX IF NOT EXISTS idx_snapshots_project
|
|
446
|
-
ON bootstrap_snapshots(project_root, created_at DESC);
|
|
447
|
-
CREATE INDEX IF NOT EXISTS idx_dim_files_file
|
|
448
|
-
ON bootstrap_dim_files(file_path);
|
|
449
|
-
`);
|
|
450
|
-
}
|
|
451
|
-
#prepareStatements() {
|
|
452
|
-
this.#stmts = {
|
|
453
|
-
insertSnapshot: this.#db.prepare(`
|
|
454
|
-
INSERT INTO bootstrap_snapshots
|
|
455
|
-
(id, session_id, project_root, created_at, duration_ms,
|
|
456
|
-
file_count, dimension_count, candidate_count, primary_lang,
|
|
457
|
-
file_hashes, dimension_meta, episodic_data,
|
|
458
|
-
is_incremental, parent_id, changed_files, affected_dims, status)
|
|
459
|
-
VALUES
|
|
460
|
-
(@id, @session_id, @project_root, @created_at, @duration_ms,
|
|
461
|
-
@file_count, @dimension_count, @candidate_count, @primary_lang,
|
|
462
|
-
@file_hashes, @dimension_meta, @episodic_data,
|
|
463
|
-
@is_incremental, @parent_id, @changed_files, @affected_dims, @status)
|
|
464
|
-
`),
|
|
465
|
-
insertDimFile: this.#db.prepare(`
|
|
466
|
-
INSERT OR IGNORE INTO bootstrap_dim_files (snapshot_id, dim_id, file_path, role)
|
|
467
|
-
VALUES (@snapshot_id, @dim_id, @file_path, @role)
|
|
468
|
-
`),
|
|
469
|
-
getLatest: this.#db.prepare(`
|
|
470
|
-
SELECT * FROM bootstrap_snapshots
|
|
471
|
-
WHERE project_root = ? AND status = 'complete'
|
|
472
|
-
ORDER BY created_at DESC
|
|
473
|
-
LIMIT 1
|
|
474
|
-
`),
|
|
475
|
-
getById: this.#db.prepare(`
|
|
476
|
-
SELECT * FROM bootstrap_snapshots WHERE id = ?
|
|
477
|
-
`),
|
|
478
|
-
listByProject: this.#db.prepare(`
|
|
479
|
-
SELECT * FROM bootstrap_snapshots
|
|
480
|
-
WHERE project_root = ?
|
|
481
|
-
ORDER BY created_at DESC
|
|
482
|
-
LIMIT ?
|
|
483
|
-
`),
|
|
484
|
-
getDimFiles: this.#db.prepare(`
|
|
485
|
-
SELECT dim_id, file_path FROM bootstrap_dim_files
|
|
486
|
-
WHERE snapshot_id = ?
|
|
487
|
-
`),
|
|
488
|
-
enforceCapacity: this.#db.prepare(`
|
|
489
|
-
DELETE FROM bootstrap_snapshots
|
|
490
|
-
WHERE project_root = ?
|
|
491
|
-
AND id NOT IN (
|
|
492
|
-
SELECT id FROM bootstrap_snapshots
|
|
493
|
-
WHERE project_root = ?
|
|
494
|
-
ORDER BY created_at DESC
|
|
495
|
-
LIMIT ?
|
|
496
|
-
)
|
|
497
|
-
`),
|
|
498
|
-
deleteById: this.#db.prepare(`
|
|
499
|
-
DELETE FROM bootstrap_snapshots WHERE id = ?
|
|
500
|
-
`),
|
|
501
|
-
};
|
|
502
|
-
}
|
|
503
452
|
}
|
|
504
453
|
export default BootstrapSnapshot;
|
|
@@ -20,6 +20,7 @@ import { ExplorationTracker } from '#agent/context/ExplorationTracker.js';
|
|
|
20
20
|
import { EpisodicConsolidator } from '#agent/domain/EpisodicConsolidator.js';
|
|
21
21
|
import { ANALYST_BUDGET } from '#agent/domain/insight-analyst.js';
|
|
22
22
|
import { MemoryCoordinator } from '#agent/memory/MemoryCoordinator.js';
|
|
23
|
+
import { MemoryEmbeddingStore } from '#agent/memory/MemoryEmbeddingStore.js';
|
|
23
24
|
import { PersistentMemory } from '#agent/memory/PersistentMemory.js';
|
|
24
25
|
import { SessionStore } from '#agent/memory/SessionStore.js';
|
|
25
26
|
import { PRESETS } from '#agent/presets.js';
|
|
@@ -159,7 +160,7 @@ export async function fillDimensionsV3(view, dimensions) {
|
|
|
159
160
|
timeoutMs: 15_000,
|
|
160
161
|
})) ?? null;
|
|
161
162
|
if (projectGraph) {
|
|
162
|
-
const overview = projectGraph.getOverview();
|
|
163
|
+
const overview = await projectGraph.getOverview();
|
|
163
164
|
logger.info(`[Insight-v3] ProjectGraph: ${overview.totalClasses} classes, ${overview.totalProtocols} protocols (${overview.buildTimeMs}ms)`);
|
|
164
165
|
}
|
|
165
166
|
}
|
|
@@ -233,7 +234,11 @@ export async function fillDimensionsV3(view, dimensions) {
|
|
|
233
234
|
catch {
|
|
234
235
|
// EmbedProvider 不可用时 fallback 到无向量模式
|
|
235
236
|
}
|
|
236
|
-
semanticMemory = new PersistentMemory(db, {
|
|
237
|
+
semanticMemory = new PersistentMemory(db, {
|
|
238
|
+
logger,
|
|
239
|
+
embeddingFn,
|
|
240
|
+
embeddingStore: new MemoryEmbeddingStore(projectRoot),
|
|
241
|
+
});
|
|
237
242
|
const smStats = semanticMemory.getStats();
|
|
238
243
|
if (smStats.total > 0) {
|
|
239
244
|
logger.info(`[Insight-v3] Loaded ${smStats.total} semantic memories from previous bootstrap ` +
|
|
@@ -248,10 +253,11 @@ export async function fillDimensionsV3(view, dimensions) {
|
|
|
248
253
|
let codeEntityGraphInst = null;
|
|
249
254
|
try {
|
|
250
255
|
const { CodeEntityGraph } = await import('#service/knowledge/CodeEntityGraph.js');
|
|
251
|
-
const
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
256
|
+
const entityRepo = ctx.container.get('codeEntityRepository');
|
|
257
|
+
const edgeRepo = ctx.container.get('knowledgeEdgeRepository');
|
|
258
|
+
if (entityRepo && edgeRepo) {
|
|
259
|
+
codeEntityGraphInst = new CodeEntityGraph(entityRepo, edgeRepo, { projectRoot, logger });
|
|
260
|
+
const topo = await codeEntityGraphInst.getTopology();
|
|
255
261
|
if (topo.totalEntities > 0) {
|
|
256
262
|
logger.info(`[Insight-v3] CodeEntityGraph: ${topo.totalEntities} entities, ${topo.totalEdges} edges`);
|
|
257
263
|
}
|
|
@@ -319,6 +325,7 @@ export async function fillDimensionsV3(view, dimensions) {
|
|
|
319
325
|
// ── 跨维度去重集合 (实例级持久化,等效旧 ChatAgent.#globalSubmittedTitles/Patterns) ──
|
|
320
326
|
const globalSubmittedTitles = new Set();
|
|
321
327
|
const globalSubmittedPatterns = new Set();
|
|
328
|
+
const globalSubmittedTriggers = new Set();
|
|
322
329
|
// ── Rescan 模式: 预种已有 recipe 标题到去重集合,防止重复创建 ──
|
|
323
330
|
const existingRecipesList = existingRecipes;
|
|
324
331
|
if (existingRecipesList && existingRecipesList.length > 0) {
|
|
@@ -327,8 +334,12 @@ export async function fillDimensionsV3(view, dimensions) {
|
|
|
327
334
|
if (r.title && r.status !== 'decaying') {
|
|
328
335
|
globalSubmittedTitles.add(r.title.toLowerCase().trim());
|
|
329
336
|
}
|
|
337
|
+
// ★ trigger 全部预种(含 decaying),防止 trigger 冲突
|
|
338
|
+
if (r.trigger) {
|
|
339
|
+
globalSubmittedTriggers.add(r.trigger.toLowerCase().trim());
|
|
340
|
+
}
|
|
330
341
|
}
|
|
331
|
-
logger.info(`[Insight-v3] Rescan mode: seeded ${globalSubmittedTitles.size}
|
|
342
|
+
logger.info(`[Insight-v3] Rescan mode: seeded ${globalSubmittedTitles.size} titles + ${globalSubmittedTriggers.size} triggers into dedup set`);
|
|
332
343
|
}
|
|
333
344
|
// 构建 rescanContext 供 Analyst/Producer prompt 使用(区分 healthy/decaying)
|
|
334
345
|
const rescanContext = existingRecipesList
|
|
@@ -597,6 +608,7 @@ export async function fillDimensionsV3(view, dimensions) {
|
|
|
597
608
|
sharedState: {
|
|
598
609
|
submittedTitles: globalSubmittedTitles,
|
|
599
610
|
submittedPatterns: globalSubmittedPatterns,
|
|
611
|
+
submittedTriggers: globalSubmittedTriggers,
|
|
600
612
|
_dimensionMeta: {
|
|
601
613
|
id: dimId,
|
|
602
614
|
outputType: dimConfig.outputType || 'candidate',
|
|
@@ -994,9 +1006,10 @@ export async function fillDimensionsV3(view, dimensions) {
|
|
|
994
1006
|
// ═══════════════════════════════════════════════════════════
|
|
995
1007
|
try {
|
|
996
1008
|
const { CodeEntityGraph } = await import('#service/knowledge/CodeEntityGraph.js');
|
|
997
|
-
const
|
|
998
|
-
|
|
999
|
-
|
|
1009
|
+
const entityRepo = ctx.container.get('codeEntityRepository');
|
|
1010
|
+
const edgeRepo = ctx.container.get('knowledgeEdgeRepository');
|
|
1011
|
+
if (entityRepo && edgeRepo) {
|
|
1012
|
+
const ceg = new CodeEntityGraph(entityRepo, edgeRepo, { projectRoot, logger });
|
|
1000
1013
|
// 收集所有维度产出的候选 (从 Producer toolCalls 中提取)
|
|
1001
1014
|
const allCandidates = [];
|
|
1002
1015
|
for (const dimData of Object.values(dimensionCandidates)) {
|
|
@@ -1015,7 +1028,7 @@ export async function fillDimensionsV3(view, dimensions) {
|
|
|
1015
1028
|
}
|
|
1016
1029
|
}
|
|
1017
1030
|
if (allCandidates.length > 0) {
|
|
1018
|
-
const relResult = ceg.populateFromCandidateRelations(allCandidates);
|
|
1031
|
+
const relResult = await ceg.populateFromCandidateRelations(allCandidates);
|
|
1019
1032
|
logger.info(`[Insight-v3] Code Entity Graph relations: ${relResult.edgesCreated} edges from ${allCandidates.length} candidates (${relResult.durationMs}ms)`);
|
|
1020
1033
|
}
|
|
1021
1034
|
}
|
|
@@ -1033,7 +1046,10 @@ export async function fillDimensionsV3(view, dimensions) {
|
|
|
1033
1046
|
try {
|
|
1034
1047
|
const db = ctx.container.get('database');
|
|
1035
1048
|
if (db) {
|
|
1036
|
-
const semanticMemory = new PersistentMemory(db, {
|
|
1049
|
+
const semanticMemory = new PersistentMemory(db, {
|
|
1050
|
+
logger,
|
|
1051
|
+
embeddingStore: new MemoryEmbeddingStore(projectRoot),
|
|
1052
|
+
});
|
|
1037
1053
|
const consolidator = new EpisodicConsolidator(semanticMemory, { logger });
|
|
1038
1054
|
consolidationResult = consolidator.consolidate(sessionStore, {
|
|
1039
1055
|
bootstrapSession: sessionId,
|
|
@@ -1152,10 +1168,11 @@ export async function fillDimensionsV3(view, dimensions) {
|
|
|
1152
1168
|
// Phase E: 附加 Code Entity Graph 拓扑到报告
|
|
1153
1169
|
try {
|
|
1154
1170
|
const { CodeEntityGraph } = await import('#service/knowledge/CodeEntityGraph.js');
|
|
1155
|
-
const
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
const
|
|
1171
|
+
const entityRepo = ctx.container.get('codeEntityRepository');
|
|
1172
|
+
const edgeRepo = ctx.container.get('knowledgeEdgeRepository');
|
|
1173
|
+
if (entityRepo && edgeRepo) {
|
|
1174
|
+
const ceg = new CodeEntityGraph(entityRepo, edgeRepo, { projectRoot, logger });
|
|
1175
|
+
const topo = await ceg.getTopology();
|
|
1159
1176
|
report.codeEntityGraph = {
|
|
1160
1177
|
entities: topo.entities,
|
|
1161
1178
|
edges: topo.edges,
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Phase 1 → 文件收集(DiscovererRegistry → 多语言项目类型检测)
|
|
10
10
|
* Phase 1.5 → AST 代码结构分析(tree-sitter + SFC 预处理)
|
|
11
11
|
* Phase 1.6 → Code Entity Graph(代码实体关系图谱)
|
|
12
|
-
* Phase
|
|
12
|
+
* Phase 2.2 → Panorama 全景汇总(RoleRefiner + CouplingAnalyzer + LayerInferrer)
|
|
13
13
|
* Phase 2 → 依赖关系 → knowledge_edges
|
|
14
14
|
* Phase 2.1 → Module 实体写入 Entity Graph
|
|
15
15
|
* Phase 3 → Guard 规则审计
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Phase 1 → 文件收集(DiscovererRegistry → 多语言项目类型检测)
|
|
10
10
|
* Phase 1.5 → AST 代码结构分析(tree-sitter + SFC 预处理)
|
|
11
11
|
* Phase 1.6 → Code Entity Graph(代码实体关系图谱)
|
|
12
|
-
* Phase
|
|
12
|
+
* Phase 2.2 → Panorama 全景汇总(RoleRefiner + CouplingAnalyzer + LayerInferrer)
|
|
13
13
|
* Phase 2 → 依赖关系 → knowledge_edges
|
|
14
14
|
* Phase 2.1 → Module 实体写入 Entity Graph
|
|
15
15
|
* Phase 3 → Guard 规则审计
|
|
@@ -218,12 +218,13 @@ export async function runPhase1_6_EntityGraph(astProjectSummary, projectRoot, co
|
|
|
218
218
|
if (astProjectSummary) {
|
|
219
219
|
try {
|
|
220
220
|
const { CodeEntityGraph } = await import('#service/knowledge/CodeEntityGraph.js');
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
ceg
|
|
221
|
+
const entityRepo = container.get('codeEntityRepository');
|
|
222
|
+
const edgeRepo = container.get('knowledgeEdgeRepository');
|
|
223
|
+
if (entityRepo && edgeRepo) {
|
|
224
|
+
const ceg = new CodeEntityGraph(entityRepo, edgeRepo, { projectRoot });
|
|
225
|
+
await ceg.clearProject();
|
|
225
226
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- ProjectAnalysisResult structurally compatible at runtime
|
|
226
|
-
codeEntityResult = ceg.populateFromAst(astProjectSummary);
|
|
227
|
+
codeEntityResult = await ceg.populateFromAst(astProjectSummary);
|
|
227
228
|
logger.info(`[Bootstrap] Entity Graph: ${codeEntityResult.entitiesUpserted} entities, ${codeEntityResult.edgesCreated} edges`);
|
|
228
229
|
}
|
|
229
230
|
}
|
|
@@ -279,14 +280,15 @@ export async function runPhase1_7_CallGraph(astProjectSummary, projectRoot, cont
|
|
|
279
280
|
minConfidence: 0.5,
|
|
280
281
|
});
|
|
281
282
|
// 写入 CodeEntityGraph
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
283
|
+
const entityRepo = container.get('codeEntityRepository');
|
|
284
|
+
const edgeRepo = container.get('knowledgeEdgeRepository');
|
|
285
|
+
if (entityRepo && edgeRepo && result && result.callEdges.length > 0) {
|
|
286
|
+
const ceg = new CodeEntityGraph(entityRepo, edgeRepo, { projectRoot });
|
|
285
287
|
// 增量模式: 先删除变更文件的旧边
|
|
286
288
|
if (isIncremental) {
|
|
287
|
-
ceg.clearCallGraphForFiles(changedFiles ?? null);
|
|
289
|
+
await ceg.clearCallGraphForFiles(changedFiles ?? null);
|
|
288
290
|
}
|
|
289
|
-
callGraphResult = ceg.populateCallGraph(result.callEdges, result.dataFlowEdges);
|
|
291
|
+
callGraphResult = await ceg.populateCallGraph(result.callEdges, result.dataFlowEdges);
|
|
290
292
|
const partialTag = result.stats.partial ? ' [partial]' : '';
|
|
291
293
|
const incrTag = isIncremental ? ' [incremental]' : '';
|
|
292
294
|
logger.info(`[Bootstrap] Call Graph${incrTag}${partialTag}: ${result.callEdges.length} call edges, ` +
|
|
@@ -321,7 +323,7 @@ export async function runPhase2_DependencyGraph(discoverer, container, logger, s
|
|
|
321
323
|
depGraphData = await discoverer.getDependencyGraph();
|
|
322
324
|
if (knowledgeGraphService) {
|
|
323
325
|
for (const edge of depGraphData.edges || []) {
|
|
324
|
-
const result = knowledgeGraphService.addEdge(edge.from, 'module', edge.to, 'module', 'depends_on', { weight: 1.0, source: `${discoverer.id}-${sourceTag}` });
|
|
326
|
+
const result = await knowledgeGraphService.addEdge(edge.from, 'module', edge.to, 'module', 'depends_on', { weight: 1.0, source: `${discoverer.id}-${sourceTag}` });
|
|
325
327
|
if (result?.success) {
|
|
326
328
|
depEdgesWritten++;
|
|
327
329
|
}
|
|
@@ -346,10 +348,11 @@ export async function runPhase2_1_ModuleEntities(depGraphData, projectRoot, cont
|
|
|
346
348
|
}
|
|
347
349
|
try {
|
|
348
350
|
const { CodeEntityGraph } = await import('#service/knowledge/CodeEntityGraph.js');
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const
|
|
351
|
+
const entityRepo = container.get('codeEntityRepository');
|
|
352
|
+
const edgeRepo = container.get('knowledgeEdgeRepository');
|
|
353
|
+
if (entityRepo && edgeRepo) {
|
|
354
|
+
const ceg = new CodeEntityGraph(entityRepo, edgeRepo, { projectRoot });
|
|
355
|
+
const result = await ceg.populateFromSpm(depGraphData);
|
|
353
356
|
logger.info(`[Bootstrap] Entity Graph modules: ${result.entitiesUpserted} entities`);
|
|
354
357
|
}
|
|
355
358
|
}
|
|
@@ -637,42 +640,43 @@ export async function runAllPhases(projectRoot, ctx, options = {}) {
|
|
|
637
640
|
if (report) {
|
|
638
641
|
report.phases.callGraph = { result: phase1_7.callGraphResult, ms: Date.now() - p17Start };
|
|
639
642
|
}
|
|
640
|
-
// ── Phase
|
|
643
|
+
// ── Phase 2: 依赖图 ──
|
|
644
|
+
const p2Start = Date.now();
|
|
645
|
+
const phase2 = await runPhase2_DependencyGraph(discoverer, ctx.container, ctx.logger, options.sourceTag || 'bootstrap');
|
|
646
|
+
warnings.push(...phase2.warnings);
|
|
647
|
+
if (report) {
|
|
648
|
+
report.phases.depGraph = {
|
|
649
|
+
edgesWritten: phase2.depEdgesWritten || 0,
|
|
650
|
+
ms: Date.now() - p2Start,
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
// ── Phase 2.1: Module 实体 ──
|
|
654
|
+
await runPhase2_1_ModuleEntities(phase2.depGraphData, projectRoot, ctx.container, ctx.logger);
|
|
655
|
+
// ── Phase 2.2: Panorama 全景汇总 ──
|
|
656
|
+
// 必须在 Phase 2.1 之后:此时 code_entities 中已有 module 记录
|
|
641
657
|
let panoramaResult = null;
|
|
642
658
|
try {
|
|
643
|
-
const panoramaService = ctx.container
|
|
659
|
+
const panoramaService = ctx.container.get('panoramaService');
|
|
644
660
|
if (panoramaService &&
|
|
645
661
|
typeof panoramaService.invalidate === 'function') {
|
|
646
|
-
const
|
|
662
|
+
const pPanoStart = Date.now();
|
|
647
663
|
panoramaService.invalidate();
|
|
648
|
-
const result = panoramaService.getResult();
|
|
664
|
+
const result = await panoramaService.getResult();
|
|
649
665
|
panoramaResult = result;
|
|
650
|
-
ctx.logger.info(`[Bootstrap] Phase
|
|
666
|
+
ctx.logger.info(`[Bootstrap] Phase 2.2: Panorama computed in ${Date.now() - pPanoStart}ms`);
|
|
651
667
|
if (report) {
|
|
652
|
-
const overview = panoramaService.getOverview();
|
|
668
|
+
const overview = await panoramaService.getOverview();
|
|
653
669
|
report.phases.panorama = {
|
|
654
670
|
moduleCount: overview.moduleCount ?? 0,
|
|
655
671
|
layerCount: overview.layerCount ?? 0,
|
|
656
|
-
ms: Date.now() -
|
|
672
|
+
ms: Date.now() - pPanoStart,
|
|
657
673
|
};
|
|
658
674
|
}
|
|
659
675
|
}
|
|
660
676
|
}
|
|
661
677
|
catch (err) {
|
|
662
|
-
warnings.push(`Phase
|
|
678
|
+
warnings.push(`Phase 2.2 panorama failed (non-blocking): ${err instanceof Error ? err.message : String(err)}`);
|
|
663
679
|
}
|
|
664
|
-
// ── Phase 2: 依赖图 ──
|
|
665
|
-
const p2Start = Date.now();
|
|
666
|
-
const phase2 = await runPhase2_DependencyGraph(discoverer, ctx.container, ctx.logger, options.sourceTag || 'bootstrap');
|
|
667
|
-
warnings.push(...phase2.warnings);
|
|
668
|
-
if (report) {
|
|
669
|
-
report.phases.depGraph = {
|
|
670
|
-
edgesWritten: phase2.depEdgesWritten || 0,
|
|
671
|
-
ms: Date.now() - p2Start,
|
|
672
|
-
};
|
|
673
|
-
}
|
|
674
|
-
// ── Phase 2.1: Module 实体 ──
|
|
675
|
-
await runPhase2_1_ModuleEntities(phase2.depGraphData, projectRoot, ctx.container, ctx.logger);
|
|
676
680
|
// ── Phase 3: Guard 审计 ──
|
|
677
681
|
const p3Start = Date.now();
|
|
678
682
|
const phase3 = await runPhase3_GuardAudit(allFiles, ctx.container, ctx.logger, {
|
|
@@ -766,7 +770,7 @@ export async function runAllPhases(projectRoot, ctx, options = {}) {
|
|
|
766
770
|
warnings,
|
|
767
771
|
report, // NEW: Phase 级报告 (null if generateReport=false)
|
|
768
772
|
incrementalPlan, // NEW: 增量评估结果 (null if incremental=false)
|
|
769
|
-
panoramaResult, // Phase
|
|
773
|
+
panoramaResult, // Phase 2.2: 全景汇总 (null if panoramaService unavailable)
|
|
770
774
|
isEmpty: false,
|
|
771
775
|
};
|
|
772
776
|
}
|
|
@@ -115,7 +115,7 @@ export async function bootstrapExternal(ctx) {
|
|
|
115
115
|
session,
|
|
116
116
|
languageExtension: buildLanguageExtension(primaryLang), // §7.1
|
|
117
117
|
languageStats: langStats,
|
|
118
|
-
panoramaResult: snapshot.panorama, // §M1: Phase
|
|
118
|
+
panoramaResult: snapshot.panorama, // §M1: Phase 2.2 全景数据
|
|
119
119
|
localPackageModules, // 本地子包模块信息
|
|
120
120
|
});
|
|
121
121
|
// 附加 warnings
|