autosnippet 3.3.7 → 3.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/README.md +1 -0
  2. package/dashboard/dist/assets/icons-BMNb0V6L.js +1 -0
  3. package/dashboard/dist/assets/index-DEU4tJtP.js +112 -0
  4. package/dashboard/dist/assets/index-DHJ1Dj7u.css +1 -0
  5. package/dashboard/dist/index.html +3 -3
  6. package/dist/bin/cli.js +7 -4
  7. package/dist/lib/agent/core/ChatAgentPrompts.js +57 -21
  8. package/dist/lib/agent/core/LoopContext.d.ts +1 -0
  9. package/dist/lib/agent/core/ToolExecutionPipeline.js +13 -0
  10. package/dist/lib/agent/memory/ActiveContext.d.ts +0 -2
  11. package/dist/lib/agent/memory/ActiveContext.js +0 -2
  12. package/dist/lib/agent/memory/MemoryEmbeddingStore.d.ts +49 -0
  13. package/dist/lib/agent/memory/MemoryEmbeddingStore.js +159 -0
  14. package/dist/lib/agent/memory/MemoryRetriever.d.ts +2 -0
  15. package/dist/lib/agent/memory/MemoryRetriever.js +25 -11
  16. package/dist/lib/agent/memory/MemoryStore.d.ts +8 -41
  17. package/dist/lib/agent/memory/MemoryStore.js +196 -261
  18. package/dist/lib/agent/memory/PersistentMemory.d.ts +2 -0
  19. package/dist/lib/agent/memory/PersistentMemory.js +4 -5
  20. package/dist/lib/agent/memory/SessionStore.d.ts +0 -2
  21. package/dist/lib/agent/memory/SessionStore.js +0 -2
  22. package/dist/lib/agent/tools/ast-graph.js +21 -19
  23. package/dist/lib/agent/tools/infrastructure.js +3 -2
  24. package/dist/lib/agent/tools/project-access.d.ts +2 -2
  25. package/dist/lib/agent/tools/project-access.js +5 -4
  26. package/dist/lib/bootstrap.js +8 -2
  27. package/dist/lib/cli/AiScanService.js +4 -17
  28. package/dist/lib/cli/KnowledgeSyncService.d.ts +7 -37
  29. package/dist/lib/cli/KnowledgeSyncService.js +23 -51
  30. package/dist/lib/cli/SetupService.js +5 -4
  31. package/dist/lib/core/ast/ProjectGraph.js +5 -27
  32. package/dist/lib/core/discovery/CustomConfigDiscoverer.d.ts +0 -2
  33. package/dist/lib/core/discovery/CustomConfigDiscoverer.js +0 -2
  34. package/dist/lib/domain/dimension/DimensionRegistry.d.ts +0 -2
  35. package/dist/lib/domain/dimension/DimensionRegistry.js +0 -2
  36. package/dist/lib/domain/dimension/DimensionSop.js +44 -33
  37. package/dist/lib/domain/dimension/UnifiedDimension.d.ts +0 -2
  38. package/dist/lib/domain/dimension/UnifiedDimension.js +0 -2
  39. package/dist/lib/domain/knowledge/Lifecycle.d.ts +26 -0
  40. package/dist/lib/domain/knowledge/Lifecycle.js +42 -0
  41. package/dist/lib/domain/knowledge/index.d.ts +2 -1
  42. package/dist/lib/domain/knowledge/index.js +1 -1
  43. package/dist/lib/external/mcp/McpServer.js +19 -2
  44. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.d.ts +2 -1
  45. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +102 -153
  46. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/mock-pipeline.js +10 -29
  47. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +33 -16
  48. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +1 -1
  49. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +41 -37
  50. package/dist/lib/external/mcp/handlers/bootstrap-external.js +1 -1
  51. package/dist/lib/external/mcp/handlers/dimension-complete-external.js +7 -3
  52. package/dist/lib/external/mcp/handlers/evolve-external.d.ts +1 -0
  53. package/dist/lib/external/mcp/handlers/evolve-external.js +13 -16
  54. package/dist/lib/external/mcp/handlers/guard.js +15 -24
  55. package/dist/lib/external/mcp/handlers/panorama.js +9 -9
  56. package/dist/lib/external/mcp/handlers/rescan-external.js +7 -6
  57. package/dist/lib/external/mcp/handlers/rescan-internal.js +9 -5
  58. package/dist/lib/external/mcp/handlers/search.js +3 -1
  59. package/dist/lib/external/mcp/handlers/skill.js +4 -4
  60. package/dist/lib/external/mcp/handlers/structure.js +8 -12
  61. package/dist/lib/external/mcp/handlers/system.js +10 -34
  62. package/dist/lib/http/routes/ai.js +11 -13
  63. package/dist/lib/http/routes/guardReport.js +3 -5
  64. package/dist/lib/http/routes/panorama.js +12 -12
  65. package/dist/lib/http/routes/recipes.js +59 -8
  66. package/dist/lib/http/routes/remote.js +3 -13
  67. package/dist/lib/http/routes/search.js +11 -8
  68. package/dist/lib/infrastructure/audit/AuditLogger.d.ts +20 -3
  69. package/dist/lib/infrastructure/audit/AuditStore.d.ts +28 -29
  70. package/dist/lib/infrastructure/audit/AuditStore.js +81 -88
  71. package/dist/lib/infrastructure/database/DatabaseConnection.js +7 -6
  72. package/dist/lib/infrastructure/database/drizzle/schema.d.ts +180 -2
  73. package/dist/lib/infrastructure/database/drizzle/schema.js +23 -3
  74. package/dist/lib/injection/ServiceContainer.js +7 -4
  75. package/dist/lib/injection/ServiceMap.d.ts +20 -0
  76. package/dist/lib/injection/modules/AppModule.js +2 -1
  77. package/dist/lib/injection/modules/GuardModule.js +5 -5
  78. package/dist/lib/injection/modules/InfraModule.js +60 -0
  79. package/dist/lib/injection/modules/KnowledgeModule.js +86 -51
  80. package/dist/lib/injection/modules/PanoramaModule.js +16 -10
  81. package/dist/lib/injection/modules/VectorModule.js +3 -0
  82. package/dist/lib/repository/audit/AuditRepository.d.ts +107 -0
  83. package/dist/lib/repository/audit/AuditRepository.js +272 -0
  84. package/dist/lib/repository/base/RepositoryBase.d.ts +46 -0
  85. package/dist/lib/repository/base/RepositoryBase.js +32 -0
  86. package/dist/lib/repository/bootstrap/BootstrapRepository.d.ts +94 -0
  87. package/dist/lib/repository/bootstrap/BootstrapRepository.js +246 -0
  88. package/dist/lib/repository/code/CodeEntityRepository.d.ts +91 -0
  89. package/dist/lib/repository/code/CodeEntityRepository.js +361 -0
  90. package/dist/lib/repository/delivery/DeliveryRepoAdapter.d.ts +39 -0
  91. package/dist/lib/repository/delivery/DeliveryRepoAdapter.js +23 -0
  92. package/dist/lib/repository/evolution/LifecycleEventRepository.d.ts +51 -0
  93. package/dist/lib/repository/evolution/LifecycleEventRepository.js +119 -0
  94. package/dist/lib/repository/evolution/ProposalRepository.d.ts +9 -12
  95. package/dist/lib/repository/evolution/ProposalRepository.js +114 -57
  96. package/dist/lib/repository/guard/GuardViolationRepository.d.ts +104 -0
  97. package/dist/lib/repository/guard/GuardViolationRepository.js +217 -0
  98. package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.d.ts +129 -0
  99. package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.js +475 -0
  100. package/dist/lib/repository/knowledge/KnowledgeFileStore.d.ts +39 -0
  101. package/dist/lib/repository/knowledge/KnowledgeFileStore.js +12 -0
  102. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +295 -11
  103. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +608 -13
  104. package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.d.ts +61 -0
  105. package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.js +156 -0
  106. package/dist/lib/repository/memory/MemoryRepository.d.ts +90 -0
  107. package/dist/lib/repository/memory/MemoryRepository.js +260 -0
  108. package/dist/lib/repository/search/SearchRepoAdapter.d.ts +92 -0
  109. package/dist/lib/repository/search/SearchRepoAdapter.js +124 -0
  110. package/dist/lib/repository/session/SessionRepository.d.ts +46 -0
  111. package/dist/lib/repository/session/SessionRepository.js +110 -0
  112. package/dist/lib/repository/sourceref/RecipeSourceRefRepository.d.ts +66 -0
  113. package/dist/lib/repository/sourceref/RecipeSourceRefRepository.js +182 -0
  114. package/dist/lib/repository/sync/SyncRepoAdapter.d.ts +58 -0
  115. package/dist/lib/repository/sync/SyncRepoAdapter.js +58 -0
  116. package/dist/lib/service/bootstrap/UiStartupTasks.js +5 -6
  117. package/dist/lib/service/bootstrap/bootstrap-event-types.d.ts +0 -1
  118. package/dist/lib/service/bootstrap/bootstrap-event-types.js +0 -1
  119. package/dist/lib/service/cleanup/CleanupService.js +8 -4
  120. package/dist/lib/service/delivery/CursorDeliveryPipeline.js +21 -9
  121. package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +4 -9
  122. package/dist/lib/service/evolution/ConsolidationAdvisor.js +34 -70
  123. package/dist/lib/service/evolution/ContentPatcher.d.ts +4 -12
  124. package/dist/lib/service/evolution/ContentPatcher.js +48 -19
  125. package/dist/lib/service/evolution/ContradictionDetector.d.ts +3 -7
  126. package/dist/lib/service/evolution/ContradictionDetector.js +17 -24
  127. package/dist/lib/service/evolution/DecayDetector.d.ts +10 -9
  128. package/dist/lib/service/evolution/DecayDetector.js +63 -57
  129. package/dist/lib/service/evolution/EnhancementSuggester.d.ts +3 -9
  130. package/dist/lib/service/evolution/EnhancementSuggester.js +42 -86
  131. package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +4 -4
  132. package/dist/lib/service/evolution/KnowledgeMetabolism.js +102 -71
  133. package/dist/lib/service/evolution/ProposalExecutor.d.ts +5 -12
  134. package/dist/lib/service/evolution/ProposalExecutor.js +64 -69
  135. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.d.ts +9 -14
  136. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.js +94 -155
  137. package/dist/lib/service/evolution/RecipeRelevanceAuditor.d.ts +4 -1
  138. package/dist/lib/service/evolution/RecipeRelevanceAuditor.js +50 -49
  139. package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +3 -7
  140. package/dist/lib/service/evolution/RedundancyAnalyzer.js +15 -22
  141. package/dist/lib/service/evolution/StagingManager.d.ts +6 -15
  142. package/dist/lib/service/evolution/StagingManager.js +37 -95
  143. package/dist/lib/service/evolution/createSupersedeProposal.d.ts +1 -1
  144. package/dist/lib/service/evolution/createSupersedeProposal.js +7 -8
  145. package/dist/lib/service/guard/CoverageAnalyzer.d.ts +3 -7
  146. package/dist/lib/service/guard/CoverageAnalyzer.js +9 -11
  147. package/dist/lib/service/guard/GuardCheckEngine.d.ts +3 -0
  148. package/dist/lib/service/guard/GuardCheckEngine.js +14 -22
  149. package/dist/lib/service/guard/ReverseGuard.d.ts +4 -7
  150. package/dist/lib/service/guard/ReverseGuard.js +21 -31
  151. package/dist/lib/service/guard/ViolationsStore.d.ts +15 -21
  152. package/dist/lib/service/guard/ViolationsStore.js +75 -69
  153. package/dist/lib/service/knowledge/CodeEntityGraph.d.ts +39 -63
  154. package/dist/lib/service/knowledge/CodeEntityGraph.js +418 -512
  155. package/dist/lib/service/knowledge/ConfidenceRouter.js +18 -9
  156. package/dist/lib/service/knowledge/KnowledgeFileWriter.d.ts +2 -1
  157. package/dist/lib/service/knowledge/KnowledgeGraphService.d.ts +18 -60
  158. package/dist/lib/service/knowledge/KnowledgeGraphService.js +58 -109
  159. package/dist/lib/service/knowledge/KnowledgeService.d.ts +15 -1
  160. package/dist/lib/service/knowledge/KnowledgeService.js +76 -38
  161. package/dist/lib/service/knowledge/RecipeProductionGateway.d.ts +0 -2
  162. package/dist/lib/service/knowledge/RecipeProductionGateway.js +0 -2
  163. package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +5 -13
  164. package/dist/lib/service/knowledge/SourceRefReconciler.js +58 -78
  165. package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +5 -3
  166. package/dist/lib/service/panorama/CouplingAnalyzer.js +102 -39
  167. package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +7 -4
  168. package/dist/lib/service/panorama/DimensionAnalyzer.js +72 -25
  169. package/dist/lib/service/panorama/LayerInferrer.js +1 -1
  170. package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +7 -6
  171. package/dist/lib/service/panorama/ModuleDiscoverer.js +174 -82
  172. package/dist/lib/service/panorama/PanoramaAggregator.d.ts +10 -3
  173. package/dist/lib/service/panorama/PanoramaAggregator.js +67 -79
  174. package/dist/lib/service/panorama/PanoramaScanner.d.ts +5 -1
  175. package/dist/lib/service/panorama/PanoramaScanner.js +32 -31
  176. package/dist/lib/service/panorama/PanoramaService.d.ts +11 -8
  177. package/dist/lib/service/panorama/PanoramaService.js +41 -66
  178. package/dist/lib/service/panorama/PanoramaTypes.d.ts +3 -0
  179. package/dist/lib/service/panorama/RoleRefiner.d.ts +8 -5
  180. package/dist/lib/service/panorama/RoleRefiner.js +52 -283
  181. package/dist/lib/service/panorama/TechStackProfiler.js +7 -119
  182. package/dist/lib/service/quality/QualityScorer.d.ts +45 -26
  183. package/dist/lib/service/quality/QualityScorer.js +157 -83
  184. package/dist/lib/service/search/SearchEngine.d.ts +1 -0
  185. package/dist/lib/service/search/SearchEngine.js +32 -37
  186. package/dist/lib/service/signal/HitRecorder.js +5 -5
  187. package/dist/lib/service/skills/RuleRecallStrategy.js +7 -3
  188. package/dist/lib/service/skills/SignalCollector.d.ts +5 -8
  189. package/dist/lib/service/skills/SignalCollector.js +28 -55
  190. package/dist/lib/service/skills/SkillAdvisor.d.ts +7 -13
  191. package/dist/lib/service/skills/SkillAdvisor.js +30 -79
  192. package/dist/lib/service/vector/SyncCoordinator.d.ts +3 -1
  193. package/dist/lib/service/vector/SyncCoordinator.js +25 -3
  194. package/dist/lib/service/vector/VectorService.d.ts +2 -0
  195. package/dist/lib/service/vector/VectorService.js +3 -0
  196. package/dist/lib/service/wiki/WikiGenerator.js +1 -1
  197. package/dist/lib/shared/LanguageProfiles.d.ts +109 -0
  198. package/dist/lib/shared/LanguageProfiles.js +939 -0
  199. package/dist/lib/shared/LanguageService.d.ts +6 -0
  200. package/dist/lib/shared/LanguageService.js +16 -0
  201. package/dist/lib/shared/PathGuard.js +16 -10
  202. package/dist/lib/shared/constants.d.ts +19 -19
  203. package/dist/lib/shared/constants.js +10 -10
  204. package/dist/lib/shared/isOwnDevRepo.d.ts +29 -4
  205. package/dist/lib/shared/isOwnDevRepo.js +64 -4
  206. package/dist/lib/shared/schemas/mcp-tools.d.ts +1 -1
  207. package/dist/lib/types/project-snapshot-builder.d.ts +0 -1
  208. package/dist/lib/types/project-snapshot-builder.js +0 -1
  209. package/dist/lib/types/project-snapshot.d.ts +0 -1
  210. package/dist/lib/types/project-snapshot.js +0 -1
  211. package/dist/lib/types/snapshot-views.d.ts +0 -2
  212. package/dist/lib/types/snapshot-views.js +0 -1
  213. package/package.json +2 -1
  214. package/dashboard/dist/assets/icons-FHns2ypa.js +0 -1
  215. package/dashboard/dist/assets/index-BRJv5Y3r.js +0 -135
  216. package/dashboard/dist/assets/index-DzoB7kxK.css +0 -1
  217. package/dist/lib/repository/base/BaseRepository.d.ts +0 -53
  218. 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
- #db;
32
+ #drizzle;
29
33
  #logger;
30
- #stmts;
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.#db =
37
- typeof db?.getDb === 'function'
38
- ? db.getDb()
39
- : db;
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
- const saveTransaction = this.#db.transaction(() => {
81
+ // 事务保存(Drizzle 类型安全)
82
+ this.#drizzle.transaction((tx) => {
82
83
  // 主记录
83
- this.#stmts.insertSnapshot.run({
84
+ tx.insert(bootstrapSnapshots)
85
+ .values({
84
86
  id,
85
- session_id: sessionId || null,
86
- project_root: projectRoot,
87
- created_at: now,
88
- duration_ms: meta.durationMs || 0,
89
- file_count: allFiles.length,
90
- dimension_count: Object.keys(dimensionStats || {}).length,
91
- candidate_count: meta.candidateCount || 0,
92
- primary_lang: meta.primaryLang || null,
93
- file_hashes: JSON.stringify(fileHashes),
94
- dimension_meta: JSON.stringify(dimensionMeta),
95
- episodic_data: episodicData ? JSON.stringify(episodicData) : null,
96
- is_incremental: isIncremental ? 1 : 0,
97
- parent_id: parentId,
98
- changed_files: JSON.stringify(changedFiles),
99
- affected_dims: JSON.stringify(affectedDims),
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
- this.#stmts.insertDimFile.run({
112
- snapshot_id: id,
113
- dim_id: dimId,
114
- file_path: rel,
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.#stmts.listByProject.all(projectRoot, 9999);
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.#stmts.deleteById.run(row.id);
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.#stmts.getLatest.get(projectRoot);
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.#stmts.getById.get(id);
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.#stmts.listByProject
164
- .all(projectRoot, limit)
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.#stmts.getDimFiles.all(snapshotId);
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.dim_id]) {
284
- map[row.dim_id] = new Set();
314
+ if (!map[row.dimId]) {
315
+ map[row.dimId] = new Set();
285
316
  }
286
- map[row.dim_id].add(row.file_path);
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
- this.#stmts.enforceCapacity.run(projectRoot, projectRoot, MAX_SNAPSHOTS);
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.session_id ?? null,
383
- projectRoot: row.project_root,
384
- createdAt: row.created_at,
385
- durationMs: row.duration_ms,
386
- fileCount: row.file_count,
387
- dimensionCount: row.dimension_count,
388
- candidateCount: row.candidate_count,
389
- primaryLang: row.primary_lang ?? null,
390
- fileHashes: this.#safeParseJSON(row.file_hashes, {}),
391
- dimensionMeta: this.#safeParseJSON(row.dimension_meta, {}),
392
- episodicData: this.#safeParseJSON(row.episodic_data, null),
393
- isIncremental: !!row.is_incremental,
394
- parentId: row.parent_id ?? null,
395
- changedFiles: this.#safeParseJSON(row.changed_files, []),
396
- affectedDims: this.#safeParseJSON(row.affected_dims, []),
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;
@@ -374,8 +374,7 @@ export async function fillDimensionsMock(view, dimensions) {
374
374
  message: '🧪 Mock AI 模式 — 基于代码结构自动生成知识候选(非 AI 深度分析)',
375
375
  mockMode: true,
376
376
  });
377
- const knowledgeService = ctx.container.get('knowledgeService');
378
- let totalCreated = 0;
377
+ let totalGenerated = 0;
379
378
  for (const dim of dimensions) {
380
379
  const dimStartTime = Date.now();
381
380
  const dimLabel = dim.label ?? dim.id;
@@ -385,48 +384,30 @@ export async function fillDimensionsMock(view, dimensions) {
385
384
  mockMode: true,
386
385
  });
387
386
  logger.info(`[MockPipeline] ── Dimension "${dim.id}" (${dimLabel}) ──`);
388
- // 生成候选
387
+ // 生成候选(仅在内存中,不写入数据库)
389
388
  const candidates = generateDimensionCandidates(dim.id, dimLabel, allFiles, primaryLang, projectName, astStats, repFiles);
390
- const createdIds = [];
389
+ totalGenerated += candidates.length;
391
390
  for (const candidate of candidates) {
392
- try {
393
- const entry = await knowledgeService.create({
394
- ...candidate,
395
- source: 'mock-bootstrap',
396
- }, { userId: 'mock-ai' });
397
- createdIds.push(entry.id);
398
- totalCreated++;
399
- // 尝试自动评分(非关键路径)
400
- try {
401
- await knowledgeService.updateQuality?.(entry.id, { userId: 'mock-ai' });
402
- }
403
- catch {
404
- /* best effort */
405
- }
406
- logger.info(`[MockPipeline] ✅ Created: "${candidate.title}" → ${entry.id}`);
407
- }
408
- catch (err) {
409
- const msg = err instanceof Error ? err.message : String(err);
410
- logger.warn(`[MockPipeline] ⚠️ Failed to create "${candidate.title}": ${msg}`);
411
- }
391
+ logger.info(`[MockPipeline] 📝 Generated (not persisted): "${candidate.title}"`);
412
392
  }
413
393
  const durationMs = Date.now() - dimStartTime;
414
394
  emitter.emitDimensionComplete(dim.id, {
415
395
  type: 'candidate',
416
396
  extracted: candidates.length,
417
- created: createdIds.length,
397
+ created: 0,
418
398
  status: 'mock-pipeline-complete',
419
399
  degraded: false,
420
400
  durationMs,
421
401
  toolCallCount: 0,
422
402
  source: 'mock-pipeline',
423
403
  });
424
- logger.info(`[MockPipeline] ✅ "${dim.id}": ${createdIds.length}/${candidates.length} candidates, ${durationMs}ms`);
404
+ logger.info(`[MockPipeline] ✅ "${dim.id}": ${candidates.length} candidates generated (mock-only, not persisted), ${durationMs}ms`);
425
405
  }
426
406
  emitter.emitProgress('bootstrap:mock-complete', {
427
- message: `🧪 Mock Bootstrap 完成: ${totalCreated} 个候选知识已生成`,
428
- totalCreated,
407
+ message: `🧪 Mock Bootstrap 完成: ${totalGenerated} 个候选知识已生成(仅预览,未写入数据库)`,
408
+ totalCreated: 0,
409
+ totalGenerated,
429
410
  mockMode: true,
430
411
  });
431
- logger.info(`[MockPipeline] ═══ Mock bootstrap complete — ${totalCreated} candidates from ${dimensions.length} dimensions`);
412
+ logger.info(`[MockPipeline] ═══ Mock bootstrap complete — ${totalGenerated} candidates generated (not persisted) from ${dimensions.length} dimensions`);
432
413
  }
@@ -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, { logger, embeddingFn });
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 db = ctx.container.get('database');
252
- if (db) {
253
- codeEntityGraphInst = new CodeEntityGraph(db, { projectRoot, logger });
254
- const topo = codeEntityGraphInst.getTopology();
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} existing recipe titles into dedup set`);
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 db = ctx.container.get('database');
998
- if (db) {
999
- const ceg = new CodeEntityGraph(db, { projectRoot, logger });
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, { logger });
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 db = ctx.container.get('database');
1156
- if (db) {
1157
- const ceg = new CodeEntityGraph(db, { projectRoot, logger });
1158
- const topo = ceg.getTopology();
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 1.8 → Panorama 全景汇总(RoleRefiner + CouplingAnalyzer + LayerInferrer)
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 规则审计