autosnippet 3.3.6 → 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.
Files changed (275) hide show
  1. package/README.md +1 -0
  2. package/dashboard/dist/assets/icons-BMNb0V6L.js +1 -0
  3. package/dashboard/dist/assets/index-DHJ1Dj7u.css +1 -0
  4. package/dashboard/dist/assets/index-DV8biUkH.js +112 -0
  5. package/dashboard/dist/index.html +3 -3
  6. package/dist/bin/cli.js +8 -4
  7. package/dist/lib/agent/AgentRuntime.d.ts +2 -2
  8. package/dist/lib/agent/AgentRuntime.js +26 -18
  9. package/dist/lib/agent/core/ChatAgentPrompts.js +57 -21
  10. package/dist/lib/agent/core/LoopContext.d.ts +1 -0
  11. package/dist/lib/agent/core/ToolExecutionPipeline.js +13 -0
  12. package/dist/lib/agent/domain/ChatAgentTasks.js +4 -0
  13. package/dist/lib/agent/forced-summary.js +7 -2
  14. package/dist/lib/agent/memory/ActiveContext.d.ts +0 -2
  15. package/dist/lib/agent/memory/ActiveContext.js +0 -2
  16. package/dist/lib/agent/memory/MemoryEmbeddingStore.d.ts +49 -0
  17. package/dist/lib/agent/memory/MemoryEmbeddingStore.js +159 -0
  18. package/dist/lib/agent/memory/MemoryRetriever.d.ts +2 -0
  19. package/dist/lib/agent/memory/MemoryRetriever.js +25 -11
  20. package/dist/lib/agent/memory/MemoryStore.d.ts +8 -41
  21. package/dist/lib/agent/memory/MemoryStore.js +196 -261
  22. package/dist/lib/agent/memory/PersistentMemory.d.ts +2 -0
  23. package/dist/lib/agent/memory/PersistentMemory.js +4 -5
  24. package/dist/lib/agent/memory/SessionStore.d.ts +0 -2
  25. package/dist/lib/agent/memory/SessionStore.js +0 -2
  26. package/dist/lib/agent/tools/ast-graph.js +21 -19
  27. package/dist/lib/agent/tools/infrastructure.js +3 -2
  28. package/dist/lib/agent/tools/project-access.d.ts +2 -2
  29. package/dist/lib/agent/tools/project-access.js +5 -4
  30. package/dist/lib/bootstrap.js +2 -1
  31. package/dist/lib/cli/AiScanService.js +8 -21
  32. package/dist/lib/cli/KnowledgeSyncService.d.ts +7 -37
  33. package/dist/lib/cli/KnowledgeSyncService.js +23 -51
  34. package/dist/lib/core/ast/ProjectGraph.js +5 -27
  35. package/dist/lib/core/discovery/ConfigWatcher.d.ts +64 -0
  36. package/dist/lib/core/discovery/ConfigWatcher.js +336 -0
  37. package/dist/lib/core/discovery/CustomConfigDiscoverer.d.ts +28 -0
  38. package/dist/lib/core/discovery/CustomConfigDiscoverer.js +1303 -0
  39. package/dist/lib/core/discovery/DiscovererPreference.d.ts +44 -0
  40. package/dist/lib/core/discovery/DiscovererPreference.js +141 -0
  41. package/dist/lib/core/discovery/DiscovererRegistry.d.ts +10 -1
  42. package/dist/lib/core/discovery/DiscovererRegistry.js +42 -2
  43. package/dist/lib/core/discovery/ProjectDiscoverer.d.ts +19 -0
  44. package/dist/lib/core/discovery/index.d.ts +2 -0
  45. package/dist/lib/core/discovery/index.js +4 -0
  46. package/dist/lib/core/discovery/parsers/CMakeParser.d.ts +32 -0
  47. package/dist/lib/core/discovery/parsers/CMakeParser.js +148 -0
  48. package/dist/lib/core/discovery/parsers/GradleDslParser.d.ts +43 -0
  49. package/dist/lib/core/discovery/parsers/GradleDslParser.js +171 -0
  50. package/dist/lib/core/discovery/parsers/JsonConfigParser.d.ts +45 -0
  51. package/dist/lib/core/discovery/parsers/JsonConfigParser.js +122 -0
  52. package/dist/lib/core/discovery/parsers/RubyDslParser.d.ts +49 -0
  53. package/dist/lib/core/discovery/parsers/RubyDslParser.js +282 -0
  54. package/dist/lib/core/discovery/parsers/StarlarkParser.d.ts +33 -0
  55. package/dist/lib/core/discovery/parsers/StarlarkParser.js +229 -0
  56. package/dist/lib/core/discovery/parsers/YamlConfigParser.d.ts +37 -0
  57. package/dist/lib/core/discovery/parsers/YamlConfigParser.js +212 -0
  58. package/dist/lib/domain/dimension/DimensionRegistry.d.ts +0 -2
  59. package/dist/lib/domain/dimension/DimensionRegistry.js +0 -2
  60. package/dist/lib/domain/dimension/DimensionSop.js +44 -33
  61. package/dist/lib/domain/dimension/UnifiedDimension.d.ts +0 -2
  62. package/dist/lib/domain/dimension/UnifiedDimension.js +0 -2
  63. package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +7 -1
  64. package/dist/lib/domain/knowledge/KnowledgeEntry.js +17 -3
  65. package/dist/lib/domain/knowledge/Lifecycle.d.ts +26 -0
  66. package/dist/lib/domain/knowledge/Lifecycle.js +42 -0
  67. package/dist/lib/domain/knowledge/index.d.ts +2 -1
  68. package/dist/lib/domain/knowledge/index.js +1 -1
  69. package/dist/lib/external/ai/AiProvider.d.ts +12 -0
  70. package/dist/lib/external/ai/AiProvider.js +24 -0
  71. package/dist/lib/external/ai/AiProviderManager.d.ts +101 -0
  72. package/dist/lib/external/ai/AiProviderManager.js +193 -0
  73. package/dist/lib/external/ai/providers/ClaudeProvider.js +11 -0
  74. package/dist/lib/external/ai/providers/GoogleGeminiProvider.js +18 -0
  75. package/dist/lib/external/ai/providers/MockProvider.d.ts +21 -3
  76. package/dist/lib/external/ai/providers/MockProvider.js +290 -14
  77. package/dist/lib/external/ai/providers/OpenAiProvider.js +16 -0
  78. package/dist/lib/external/lark/LarkTransport.d.ts +5 -1
  79. package/dist/lib/external/lark/LarkTransport.js +10 -2
  80. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.d.ts +2 -1
  81. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +102 -153
  82. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/mock-pipeline.d.ts +20 -0
  83. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/mock-pipeline.js +432 -0
  84. package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +49 -24
  85. package/dist/lib/external/mcp/handlers/bootstrap/refine.js +8 -0
  86. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +1 -1
  87. package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +41 -37
  88. package/dist/lib/external/mcp/handlers/bootstrap-external.d.ts +9 -0
  89. package/dist/lib/external/mcp/handlers/bootstrap-external.js +3 -1
  90. package/dist/lib/external/mcp/handlers/bootstrap-internal.js +2 -0
  91. package/dist/lib/external/mcp/handlers/consolidated.js +2 -1
  92. package/dist/lib/external/mcp/handlers/dimension-complete-external.js +9 -4
  93. package/dist/lib/external/mcp/handlers/evolve-external.d.ts +1 -0
  94. package/dist/lib/external/mcp/handlers/evolve-external.js +18 -18
  95. package/dist/lib/external/mcp/handlers/guard.js +15 -24
  96. package/dist/lib/external/mcp/handlers/knowledge.js +5 -4
  97. package/dist/lib/external/mcp/handlers/panorama.js +9 -9
  98. package/dist/lib/external/mcp/handlers/rescan-external.js +7 -6
  99. package/dist/lib/external/mcp/handlers/rescan-internal.js +9 -5
  100. package/dist/lib/external/mcp/handlers/search.js +3 -1
  101. package/dist/lib/external/mcp/handlers/skill.js +4 -4
  102. package/dist/lib/external/mcp/handlers/structure.js +8 -12
  103. package/dist/lib/external/mcp/handlers/system.js +10 -34
  104. package/dist/lib/http/routes/ai.js +109 -30
  105. package/dist/lib/http/routes/candidates.js +11 -4
  106. package/dist/lib/http/routes/commands.js +10 -1
  107. package/dist/lib/http/routes/guardReport.js +3 -5
  108. package/dist/lib/http/routes/health.js +11 -0
  109. package/dist/lib/http/routes/modules.js +27 -0
  110. package/dist/lib/http/routes/panorama.js +12 -12
  111. package/dist/lib/http/routes/recipes.js +66 -8
  112. package/dist/lib/http/routes/remote.js +3 -13
  113. package/dist/lib/http/routes/search.js +11 -8
  114. package/dist/lib/http/utils/routeHelpers.js +2 -1
  115. package/dist/lib/infrastructure/audit/AuditLogger.d.ts +20 -3
  116. package/dist/lib/infrastructure/audit/AuditStore.d.ts +28 -29
  117. package/dist/lib/infrastructure/audit/AuditStore.js +81 -88
  118. package/dist/lib/infrastructure/database/drizzle/schema.d.ts +180 -2
  119. package/dist/lib/infrastructure/database/drizzle/schema.js +23 -3
  120. package/dist/lib/injection/ServiceContainer.d.ts +6 -5
  121. package/dist/lib/injection/ServiceContainer.js +18 -31
  122. package/dist/lib/injection/ServiceMap.d.ts +22 -0
  123. package/dist/lib/injection/modules/AiModule.d.ts +6 -9
  124. package/dist/lib/injection/modules/AiModule.js +82 -39
  125. package/dist/lib/injection/modules/AppModule.js +2 -1
  126. package/dist/lib/injection/modules/GuardModule.js +5 -5
  127. package/dist/lib/injection/modules/InfraModule.js +60 -0
  128. package/dist/lib/injection/modules/KnowledgeModule.js +86 -51
  129. package/dist/lib/injection/modules/PanoramaModule.js +16 -10
  130. package/dist/lib/injection/modules/VectorModule.js +3 -0
  131. package/dist/lib/repository/audit/AuditRepository.d.ts +107 -0
  132. package/dist/lib/repository/audit/AuditRepository.js +272 -0
  133. package/dist/lib/repository/base/RepositoryBase.d.ts +46 -0
  134. package/dist/lib/repository/base/RepositoryBase.js +32 -0
  135. package/dist/lib/repository/bootstrap/BootstrapRepository.d.ts +94 -0
  136. package/dist/lib/repository/bootstrap/BootstrapRepository.js +246 -0
  137. package/dist/lib/repository/code/CodeEntityRepository.d.ts +91 -0
  138. package/dist/lib/repository/code/CodeEntityRepository.js +361 -0
  139. package/dist/lib/repository/delivery/DeliveryRepoAdapter.d.ts +39 -0
  140. package/dist/lib/repository/delivery/DeliveryRepoAdapter.js +23 -0
  141. package/dist/lib/repository/evolution/LifecycleEventRepository.d.ts +51 -0
  142. package/dist/lib/repository/evolution/LifecycleEventRepository.js +119 -0
  143. package/dist/lib/repository/evolution/ProposalRepository.d.ts +9 -12
  144. package/dist/lib/repository/evolution/ProposalRepository.js +114 -57
  145. package/dist/lib/repository/guard/GuardViolationRepository.d.ts +104 -0
  146. package/dist/lib/repository/guard/GuardViolationRepository.js +217 -0
  147. package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.d.ts +129 -0
  148. package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.js +475 -0
  149. package/dist/lib/repository/knowledge/KnowledgeFileStore.d.ts +39 -0
  150. package/dist/lib/repository/knowledge/KnowledgeFileStore.js +12 -0
  151. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +295 -11
  152. package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +608 -13
  153. package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.d.ts +61 -0
  154. package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.js +156 -0
  155. package/dist/lib/repository/memory/MemoryRepository.d.ts +90 -0
  156. package/dist/lib/repository/memory/MemoryRepository.js +260 -0
  157. package/dist/lib/repository/search/SearchRepoAdapter.d.ts +92 -0
  158. package/dist/lib/repository/search/SearchRepoAdapter.js +124 -0
  159. package/dist/lib/repository/session/SessionRepository.d.ts +46 -0
  160. package/dist/lib/repository/session/SessionRepository.js +110 -0
  161. package/dist/lib/repository/sourceref/RecipeSourceRefRepository.d.ts +66 -0
  162. package/dist/lib/repository/sourceref/RecipeSourceRefRepository.js +182 -0
  163. package/dist/lib/repository/sync/SyncRepoAdapter.d.ts +58 -0
  164. package/dist/lib/repository/sync/SyncRepoAdapter.js +58 -0
  165. package/dist/lib/service/bootstrap/UiStartupTasks.js +5 -6
  166. package/dist/lib/service/bootstrap/bootstrap-event-types.d.ts +0 -1
  167. package/dist/lib/service/bootstrap/bootstrap-event-types.js +0 -1
  168. package/dist/lib/service/cleanup/CleanupService.d.ts +54 -7
  169. package/dist/lib/service/cleanup/CleanupService.js +291 -40
  170. package/dist/lib/service/delivery/CursorDeliveryPipeline.js +6 -8
  171. package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +4 -9
  172. package/dist/lib/service/evolution/ConsolidationAdvisor.js +34 -70
  173. package/dist/lib/service/evolution/ContentPatcher.d.ts +4 -12
  174. package/dist/lib/service/evolution/ContentPatcher.js +48 -19
  175. package/dist/lib/service/evolution/ContradictionDetector.d.ts +3 -7
  176. package/dist/lib/service/evolution/ContradictionDetector.js +17 -24
  177. package/dist/lib/service/evolution/DecayDetector.d.ts +10 -9
  178. package/dist/lib/service/evolution/DecayDetector.js +63 -57
  179. package/dist/lib/service/evolution/EnhancementSuggester.d.ts +3 -9
  180. package/dist/lib/service/evolution/EnhancementSuggester.js +42 -86
  181. package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +4 -4
  182. package/dist/lib/service/evolution/KnowledgeMetabolism.js +102 -71
  183. package/dist/lib/service/evolution/ProposalExecutor.d.ts +5 -12
  184. package/dist/lib/service/evolution/ProposalExecutor.js +64 -69
  185. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.d.ts +9 -14
  186. package/dist/lib/service/evolution/RecipeLifecycleSupervisor.js +94 -155
  187. package/dist/lib/service/evolution/RecipeRelevanceAuditor.d.ts +4 -1
  188. package/dist/lib/service/evolution/RecipeRelevanceAuditor.js +50 -49
  189. package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +3 -7
  190. package/dist/lib/service/evolution/RedundancyAnalyzer.js +15 -22
  191. package/dist/lib/service/evolution/StagingManager.d.ts +6 -15
  192. package/dist/lib/service/evolution/StagingManager.js +37 -95
  193. package/dist/lib/service/evolution/createSupersedeProposal.d.ts +1 -1
  194. package/dist/lib/service/evolution/createSupersedeProposal.js +7 -8
  195. package/dist/lib/service/guard/CoverageAnalyzer.d.ts +3 -7
  196. package/dist/lib/service/guard/CoverageAnalyzer.js +9 -11
  197. package/dist/lib/service/guard/GuardCheckEngine.d.ts +3 -0
  198. package/dist/lib/service/guard/GuardCheckEngine.js +14 -22
  199. package/dist/lib/service/guard/ReverseGuard.d.ts +4 -7
  200. package/dist/lib/service/guard/ReverseGuard.js +21 -31
  201. package/dist/lib/service/guard/ViolationsStore.d.ts +15 -21
  202. package/dist/lib/service/guard/ViolationsStore.js +75 -69
  203. package/dist/lib/service/knowledge/CodeEntityGraph.d.ts +45 -63
  204. package/dist/lib/service/knowledge/CodeEntityGraph.js +418 -496
  205. package/dist/lib/service/knowledge/ConfidenceRouter.js +18 -9
  206. package/dist/lib/service/knowledge/KnowledgeFileWriter.d.ts +2 -1
  207. package/dist/lib/service/knowledge/KnowledgeGraphService.d.ts +18 -60
  208. package/dist/lib/service/knowledge/KnowledgeGraphService.js +58 -109
  209. package/dist/lib/service/knowledge/KnowledgeService.d.ts +15 -1
  210. package/dist/lib/service/knowledge/KnowledgeService.js +97 -46
  211. package/dist/lib/service/knowledge/RecipeProductionGateway.d.ts +0 -2
  212. package/dist/lib/service/knowledge/RecipeProductionGateway.js +0 -2
  213. package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +5 -13
  214. package/dist/lib/service/knowledge/SourceRefReconciler.js +58 -78
  215. package/dist/lib/service/module/ModuleService.js +10 -19
  216. package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +14 -3
  217. package/dist/lib/service/panorama/CouplingAnalyzer.js +137 -32
  218. package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +7 -4
  219. package/dist/lib/service/panorama/DimensionAnalyzer.js +94 -33
  220. package/dist/lib/service/panorama/LayerInferrer.d.ts +16 -1
  221. package/dist/lib/service/panorama/LayerInferrer.js +118 -1
  222. package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +14 -4
  223. package/dist/lib/service/panorama/ModuleDiscoverer.js +209 -61
  224. package/dist/lib/service/panorama/PanoramaAggregator.d.ts +15 -4
  225. package/dist/lib/service/panorama/PanoramaAggregator.js +128 -62
  226. package/dist/lib/service/panorama/PanoramaScanner.d.ts +5 -1
  227. package/dist/lib/service/panorama/PanoramaScanner.js +60 -31
  228. package/dist/lib/service/panorama/PanoramaService.d.ts +11 -8
  229. package/dist/lib/service/panorama/PanoramaService.js +49 -69
  230. package/dist/lib/service/panorama/PanoramaTypes.d.ts +41 -0
  231. package/dist/lib/service/panorama/RoleRefiner.d.ts +10 -5
  232. package/dist/lib/service/panorama/RoleRefiner.js +92 -282
  233. package/dist/lib/service/panorama/TechStackProfiler.d.ts +13 -0
  234. package/dist/lib/service/panorama/TechStackProfiler.js +79 -0
  235. package/dist/lib/service/quality/QualityScorer.d.ts +45 -26
  236. package/dist/lib/service/quality/QualityScorer.js +157 -83
  237. package/dist/lib/service/search/SearchEngine.d.ts +1 -0
  238. package/dist/lib/service/search/SearchEngine.js +32 -37
  239. package/dist/lib/service/signal/HitRecorder.js +5 -5
  240. package/dist/lib/service/skills/RuleRecallStrategy.js +7 -3
  241. package/dist/lib/service/skills/SignalCollector.d.ts +6 -8
  242. package/dist/lib/service/skills/SignalCollector.js +34 -60
  243. package/dist/lib/service/skills/SkillAdvisor.d.ts +7 -13
  244. package/dist/lib/service/skills/SkillAdvisor.js +30 -79
  245. package/dist/lib/service/vector/ContextualEnricher.d.ts +1 -0
  246. package/dist/lib/service/vector/ContextualEnricher.js +4 -0
  247. package/dist/lib/service/vector/SyncCoordinator.d.ts +3 -1
  248. package/dist/lib/service/vector/SyncCoordinator.js +25 -3
  249. package/dist/lib/service/vector/VectorService.d.ts +2 -0
  250. package/dist/lib/service/vector/VectorService.js +3 -0
  251. package/dist/lib/service/wiki/WikiGenerator.js +1 -1
  252. package/dist/lib/shared/LanguageProfiles.d.ts +109 -0
  253. package/dist/lib/shared/LanguageProfiles.js +939 -0
  254. package/dist/lib/shared/LanguageService.d.ts +6 -0
  255. package/dist/lib/shared/LanguageService.js +19 -0
  256. package/dist/lib/shared/constants.d.ts +19 -19
  257. package/dist/lib/shared/constants.js +10 -10
  258. package/dist/lib/shared/developer-identity.d.ts +18 -0
  259. package/dist/lib/shared/developer-identity.js +62 -0
  260. package/dist/lib/shared/schemas/http-requests.d.ts +8 -17
  261. package/dist/lib/shared/schemas/http-requests.js +9 -6
  262. package/dist/lib/shared/schemas/mcp-tools.d.ts +1 -1
  263. package/dist/lib/types/knowledge-wire.d.ts +1 -0
  264. package/dist/lib/types/project-snapshot-builder.d.ts +0 -1
  265. package/dist/lib/types/project-snapshot-builder.js +0 -1
  266. package/dist/lib/types/project-snapshot.d.ts +0 -1
  267. package/dist/lib/types/project-snapshot.js +0 -1
  268. package/dist/lib/types/snapshot-views.d.ts +0 -2
  269. package/dist/lib/types/snapshot-views.js +0 -1
  270. package/package.json +2 -1
  271. package/dashboard/dist/assets/icons-D1aVZYFW.js +0 -1
  272. package/dashboard/dist/assets/index-CxHOu8Hd.css +0 -1
  273. package/dashboard/dist/assets/index-DDdAOpYT.js +0 -128
  274. package/dist/lib/repository/base/BaseRepository.d.ts +0 -53
  275. package/dist/lib/repository/base/BaseRepository.js +0 -226
@@ -20,27 +20,24 @@ const SILENT_LOGGER = {
20
20
  export class PanoramaScanner {
21
21
  #projectRoot;
22
22
  #container;
23
+ #entityRepo;
24
+ #edgeRepo;
23
25
  #logger;
24
26
  #hasScanned = false;
25
27
  constructor(opts) {
26
28
  this.#projectRoot = opts.projectRoot;
27
29
  this.#container = opts.container;
30
+ this.#entityRepo = opts.entityRepo;
31
+ this.#edgeRepo = opts.edgeRepo;
28
32
  this.#logger = opts.logger ?? SILENT_LOGGER;
29
33
  }
30
34
  /**
31
35
  * 检测 DB 中是否已有该项目的 code_entities 数据
32
36
  */
33
- hasData() {
37
+ async hasData() {
34
38
  try {
35
- const db = this.#container.get('database');
36
- const rawDb = db?.getDb ? db.getDb() : db;
37
- if (!rawDb?.prepare) {
38
- return false;
39
- }
40
- const row = rawDb
41
- .prepare(`SELECT COUNT(*) as cnt FROM code_entities WHERE project_root = ?`)
42
- .get(this.#projectRoot);
43
- return (row?.cnt ?? 0) > 0;
39
+ const cnt = await this.#entityRepo.getEntityCount(this.#projectRoot);
40
+ return cnt > 0;
44
41
  }
45
42
  catch {
46
43
  return false;
@@ -51,7 +48,7 @@ export class PanoramaScanner {
51
48
  * 幂等:扫描过一次后不再重复(重启进程或手动 reset 可重新触发)。
52
49
  */
53
50
  async ensureData() {
54
- if (this.#hasScanned || this.hasData()) {
51
+ if (this.#hasScanned || (await this.hasData())) {
55
52
  return null;
56
53
  }
57
54
  return this.scan();
@@ -103,11 +100,39 @@ export class PanoramaScanner {
103
100
  modules = phase2.depGraphData.nodes?.length ?? 0;
104
101
  }
105
102
  }
103
+ // Phase 2-extra: CustomConfig 增强
104
+ // 当主 discoverer 不是 customConfig 时,尝试 CustomConfigDiscoverer
105
+ // 以获取更丰富的模块视图(混编项目常见:jvm/node/dart 获胜但模块数偏少)
106
+ if (phase1.discoverer && phase1.discoverer.id !== 'customConfig') {
107
+ try {
108
+ const { CustomConfigDiscoverer } = await import('../../core/discovery/CustomConfigDiscoverer.js');
109
+ const ccDiscoverer = new CustomConfigDiscoverer();
110
+ const ccDetect = await ccDiscoverer.detect(this.#projectRoot);
111
+ if (ccDetect.match && ccDetect.confidence >= 0.7) {
112
+ await ccDiscoverer.load(this.#projectRoot);
113
+ const ccTargets = await ccDiscoverer.listTargets();
114
+ // 仅当 CustomConfig 发现更多模块时才采纳
115
+ if (ccTargets.length > modules) {
116
+ this.#logger.info(`[PanoramaScanner] CustomConfig enrichment: ${ccTargets.length} modules ` +
117
+ `(primary discoverer '${phase1.discoverer.id}' found ${modules})`);
118
+ const ccPhase2 = await runPhase2_DependencyGraph(ccDiscoverer, this.#container, this.#logger, 'custom-enrichment');
119
+ edges += ccPhase2.depEdgesWritten;
120
+ if (ccPhase2.depGraphData) {
121
+ await runPhase2_1_ModuleEntities(ccPhase2.depGraphData, this.#projectRoot, this.#container, this.#logger);
122
+ modules = Math.max(modules, ccPhase2.depGraphData.nodes?.length ?? 0);
123
+ }
124
+ }
125
+ }
126
+ }
127
+ catch {
128
+ // CustomConfig 增强失败不阻塞主流程
129
+ }
130
+ }
106
131
  // Phase 2.2: 目录推断兜底
107
132
  // 当 Phase 2.1 未产出 module 实体时(无 Package.swift / build.gradle 等),
108
133
  // 从已有 code_entities 按顶层目录分组写入 module 实体
109
134
  if (modules === 0 && entities > 0) {
110
- modules = this.#inferModulesFromDirectories();
135
+ modules = await this.#inferModulesFromDirectories();
111
136
  }
112
137
  }
113
138
  catch (err) {
@@ -129,25 +154,17 @@ export class PanoramaScanner {
129
154
  * 从 code_entities 中按顶层目录分组写入 module 实体 + is_part_of 边。
130
155
  * 仅在 Phase 2.1 未产出 module 时调用。
131
156
  */
132
- #inferModulesFromDirectories() {
157
+ async #inferModulesFromDirectories() {
133
158
  try {
134
- const db = this.#container.get('database');
135
- const rawDb = db?.getDb ? db.getDb() : db;
136
- if (!rawDb?.prepare) {
137
- return 0;
138
- }
139
159
  // 查询所有非 module 实体的文件路径
140
- const rows = rawDb
141
- .prepare(`SELECT DISTINCT entity_id, file_path FROM code_entities
142
- WHERE project_root = ? AND file_path IS NOT NULL AND entity_type != 'module'`)
143
- .all(this.#projectRoot);
160
+ const rows = await this.#entityRepo.findDistinctEntityIdsWithFilePath(this.#projectRoot);
144
161
  if (rows.length === 0) {
145
162
  return 0;
146
163
  }
147
164
  // 按顶层目录分组
148
165
  const groups = new Map();
149
166
  for (const row of rows) {
150
- const filePath = row.file_path;
167
+ const filePath = row.filePath;
151
168
  if (!filePath) {
152
169
  continue;
153
170
  }
@@ -161,22 +178,34 @@ export class PanoramaScanner {
161
178
  if (!groups.has(firstDir)) {
162
179
  groups.set(firstDir, []);
163
180
  }
164
- groups.get(firstDir).push(row.entity_id);
181
+ groups.get(firstDir).push(row.entityId);
165
182
  }
166
183
  if (groups.size === 0) {
167
184
  return 0;
168
185
  }
169
- // 写入 module 实体 + is_part_of 边
170
- const insertEntity = rawDb.prepare(`INSERT OR IGNORE INTO code_entities (entity_id, name, entity_type, file_path, project_root)
171
- VALUES (?, ?, 'module', NULL, ?)`);
172
- const insertEdge = rawDb.prepare(`INSERT OR IGNORE INTO knowledge_edges (from_id, from_type, to_id, to_type, relation, weight)
173
- VALUES (?, 'entity', ?, 'module', 'is_part_of', 1.0)`);
186
+ // 写入 module 实体
187
+ const moduleEntities = [...groups.keys()].map((dirName) => ({
188
+ entityId: dirName,
189
+ name: dirName,
190
+ entityType: 'module',
191
+ projectRoot: this.#projectRoot,
192
+ }));
193
+ await this.#entityRepo.batchInsertIgnore(moduleEntities);
194
+ // 写入 is_part_of 边
195
+ const edges = [];
174
196
  for (const [dirName, entityIds] of groups) {
175
- insertEntity.run(dirName, dirName, this.#projectRoot);
176
197
  for (const entityId of entityIds) {
177
- insertEdge.run(entityId, dirName);
198
+ edges.push({
199
+ fromId: entityId,
200
+ fromType: 'entity',
201
+ toId: dirName,
202
+ toType: 'module',
203
+ relation: 'is_part_of',
204
+ weight: 1.0,
205
+ });
178
206
  }
179
207
  }
208
+ await this.#edgeRepo.bulkInsertIgnore(edges);
180
209
  this.#logger.info(`[PanoramaScanner] Directory fallback: inferred ${groups.size} modules from top-level dirs`);
181
210
  return groups.size;
182
211
  }
@@ -13,13 +13,16 @@
13
13
  * @module PanoramaService
14
14
  */
15
15
  import type { SignalBus } from '../../infrastructure/signal/SignalBus.js';
16
- import { ModuleDiscoverer } from './ModuleDiscoverer.js';
16
+ import type { KnowledgeEdgeRepositoryImpl } from '../../repository/knowledge/KnowledgeEdgeRepository.js';
17
+ import type { KnowledgeRepositoryImpl } from '../../repository/knowledge/KnowledgeRepository.impl.js';
18
+ import type { ModuleDiscoverer } from './ModuleDiscoverer.js';
17
19
  import type { PanoramaAggregator } from './PanoramaAggregator.js';
18
20
  import type { PanoramaScanner } from './PanoramaScanner.js';
19
- import type { CeDbLike, HealthRadar, KnowledgeGap, PanoramaModule, PanoramaResult } from './PanoramaTypes.js';
21
+ import type { HealthRadar, KnowledgeGap, PanoramaModule, PanoramaResult } from './PanoramaTypes.js';
20
22
  export interface PanoramaServiceOptions {
21
23
  aggregator: PanoramaAggregator;
22
- db: CeDbLike;
24
+ edgeRepo: KnowledgeEdgeRepositoryImpl;
25
+ knowledgeRepo: KnowledgeRepositoryImpl;
23
26
  projectRoot: string;
24
27
  scanner?: PanoramaScanner;
25
28
  moduleDiscoverer?: ModuleDiscoverer;
@@ -92,23 +95,23 @@ export declare class PanoramaService {
92
95
  /**
93
96
  * 获取项目全景概览
94
97
  */
95
- getOverview(): PanoramaOverview;
98
+ getOverview(): Promise<PanoramaOverview>;
96
99
  /**
97
100
  * 获取单模块详情 (enriched with file groups, recipes, and summary)
98
101
  */
99
- getModule(moduleName: string): PanoramaModuleDetail | null;
102
+ getModule(moduleName: string): Promise<PanoramaModuleDetail | null>;
100
103
  /**
101
104
  * 获取知识空白区
102
105
  */
103
- getGaps(): KnowledgeGap[];
106
+ getGaps(): Promise<KnowledgeGap[]>;
104
107
  /**
105
108
  * 获取全景健康度
106
109
  */
107
- getHealth(): PanoramaHealth;
110
+ getHealth(): Promise<PanoramaHealth>;
108
111
  /**
109
112
  * 获取完整 PanoramaResult(内部使用或 Bootstrap 注入)
110
113
  */
111
- getResult(): PanoramaResult;
114
+ getResult(): Promise<PanoramaResult>;
112
115
  /**
113
116
  * 确保全景数据已就绪(无数据时自动扫描)
114
117
  * MCP handler / HTTP route 应在返回数据前调用此方法
@@ -12,13 +12,14 @@
12
12
  *
13
13
  * @module PanoramaService
14
14
  */
15
- import { ModuleDiscoverer } from './ModuleDiscoverer.js';
15
+ import { COUNTABLE_LIFECYCLES } from '../../domain/knowledge/Lifecycle.js';
16
16
  /* ═══ Constants ═══════════════════════════════════════════ */
17
17
  const STALE_THRESHOLD_MS = 24 * 60 * 60 * 1000; // 24h
18
18
  /* ═══ PanoramaService Class ═══════════════════════════════ */
19
19
  export class PanoramaService {
20
20
  #aggregator;
21
- #db;
21
+ #edgeRepo;
22
+ #knowledgeRepo;
22
23
  #projectRoot;
23
24
  #scanner;
24
25
  #moduleDiscoverer;
@@ -28,11 +29,15 @@ export class PanoramaService {
28
29
  #lastOverview = null;
29
30
  constructor(opts) {
30
31
  this.#aggregator = opts.aggregator;
31
- this.#db = opts.db;
32
+ this.#edgeRepo = opts.edgeRepo;
33
+ this.#knowledgeRepo = opts.knowledgeRepo;
32
34
  this.#projectRoot = opts.projectRoot;
33
35
  this.#scanner = opts.scanner ?? null;
34
36
  this.#moduleDiscoverer =
35
- opts.moduleDiscoverer ?? new ModuleDiscoverer(opts.db, opts.projectRoot);
37
+ opts.moduleDiscoverer ??
38
+ (() => {
39
+ throw new Error('moduleDiscoverer is required');
40
+ })();
36
41
  this.#signalBus = opts.signalBus ?? null;
37
42
  // Phase 2: 订阅信号标记缓存失效
38
43
  if (this.#signalBus) {
@@ -45,8 +50,8 @@ export class PanoramaService {
45
50
  /**
46
51
  * 获取项目全景概览
47
52
  */
48
- getOverview() {
49
- const result = this.#getOrCompute();
53
+ async getOverview() {
54
+ const result = await this.#getOrCompute();
50
55
  const isStale = Date.now() - result.computedAt > STALE_THRESHOLD_MS;
51
56
  let totalFiles = 0;
52
57
  for (const [, mod] of result.modules) {
@@ -98,8 +103,8 @@ export class PanoramaService {
98
103
  /**
99
104
  * 获取单模块详情 (enriched with file groups, recipes, and summary)
100
105
  */
101
- getModule(moduleName) {
102
- const result = this.#getOrCompute();
106
+ async getModule(moduleName) {
107
+ const result = await this.#getOrCompute();
103
108
  const mod = result.modules.get(moduleName);
104
109
  if (!mod) {
105
110
  return null;
@@ -109,33 +114,27 @@ export class PanoramaService {
109
114
  // File groups: group by immediate subdirectory within the module
110
115
  const fileGroups = PanoramaService.#groupFilesBySubdir(mod.files);
111
116
  // Matched recipes from DB
112
- const recipes = this.#findModuleRecipes(moduleName, mod);
117
+ const recipes = await this.#findModuleRecipes(moduleName, mod);
113
118
  // Uncovered file count estimate
114
119
  const coveredFileCount = Math.min(recipes.length * 2, mod.fileCount); // rough heuristic
115
120
  const uncoveredFileCount = Math.max(0, mod.fileCount - coveredFileCount);
116
- // Neighbors from DB edges
121
+ // Neighbors from edge repo
117
122
  const neighbors = [];
118
- const outNeighbors = this.#db
119
- .prepare(`SELECT DISTINCT to_id, weight FROM knowledge_edges
120
- WHERE from_id = ? AND from_type = 'module' AND relation = 'depends_on'`)
121
- .all(moduleName);
122
- for (const n of outNeighbors) {
123
- neighbors.push({
124
- name: n.to_id,
125
- direction: 'out',
126
- weight: Number(n.weight ?? 1),
127
- });
123
+ const outEdges = await this.#edgeRepo.findOutgoingByRelation(moduleName, 'depends_on');
124
+ const seenOut = new Set();
125
+ for (const e of outEdges) {
126
+ if (!seenOut.has(e.toId)) {
127
+ seenOut.add(e.toId);
128
+ neighbors.push({ name: e.toId, direction: 'out', weight: e.weight });
129
+ }
128
130
  }
129
- const inNeighbors = this.#db
130
- .prepare(`SELECT DISTINCT from_id, weight FROM knowledge_edges
131
- WHERE to_id = ? AND to_type = 'module' AND relation = 'depends_on'`)
132
- .all(moduleName);
133
- for (const n of inNeighbors) {
134
- neighbors.push({
135
- name: n.from_id,
136
- direction: 'in',
137
- weight: Number(n.weight ?? 1),
138
- });
131
+ const inEdges = await this.#edgeRepo.findIncomingByRelation(moduleName, 'depends_on');
132
+ const seenIn = new Set();
133
+ for (const e of inEdges) {
134
+ if (!seenIn.has(e.fromId)) {
135
+ seenIn.add(e.fromId);
136
+ neighbors.push({ name: e.fromId, direction: 'in', weight: e.weight });
137
+ }
139
138
  }
140
139
  // Generate summary
141
140
  const summary = PanoramaService.#generateModuleSummary(mod, layerName, fileGroups, recipes, neighbors);
@@ -187,17 +186,19 @@ export class PanoramaService {
187
186
  let prefix = paths[0];
188
187
  for (const p of paths) {
189
188
  while (!p.startsWith(prefix)) {
190
- const lastSlash = prefix.lastIndexOf('/');
189
+ // Strip trailing slash before searching for last separator
190
+ const trimmed = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;
191
+ const lastSlash = trimmed.lastIndexOf('/');
191
192
  if (lastSlash < 0) {
192
193
  return '';
193
194
  }
194
- prefix = prefix.slice(0, lastSlash + 1);
195
+ prefix = trimmed.slice(0, lastSlash + 1);
195
196
  }
196
197
  }
197
198
  return prefix;
198
199
  }
199
200
  /** Find recipes related to this module by category, trigger, or title match */
200
- #findModuleRecipes(moduleName, mod) {
201
+ async #findModuleRecipes(moduleName, mod) {
201
202
  try {
202
203
  // Map refined role to typical recipe categories
203
204
  const roleCategories = {
@@ -211,31 +212,7 @@ export class PanoramaService {
211
212
  feature: ['Feature'],
212
213
  };
213
214
  const categories = roleCategories[mod.refinedRole] ?? [];
214
- // Build a LIKE query that matches module name or related categories
215
- const conditions = [];
216
- const params = [];
217
- // Match by module name in title or trigger
218
- conditions.push('(title LIKE ? OR trigger LIKE ?)');
219
- params.push(`%${moduleName}%`, `%${moduleName}%`);
220
- // Match by category
221
- for (const cat of categories) {
222
- conditions.push('category = ?');
223
- params.push(cat);
224
- }
225
- const whereClause = conditions.join(' OR ');
226
- const rows = this.#db
227
- .prepare(`SELECT id, title, trigger, kind FROM knowledge_entries
228
- WHERE lifecycle IN ('active', 'staging', 'pending')
229
- AND (${whereClause})
230
- ORDER BY lifecycle ASC
231
- LIMIT 20`)
232
- .all(...params);
233
- return rows.map((r) => ({
234
- id: String(r.id ?? ''),
235
- title: String(r.title ?? ''),
236
- trigger: String(r.trigger ?? ''),
237
- kind: String(r.kind ?? ''),
238
- }));
215
+ return await this.#knowledgeRepo.findModuleRecipes(COUNTABLE_LIFECYCLES, moduleName, categories, 20);
239
216
  }
240
217
  catch {
241
218
  return [];
@@ -278,15 +255,15 @@ export class PanoramaService {
278
255
  /**
279
256
  * 获取知识空白区
280
257
  */
281
- getGaps() {
282
- const result = this.#getOrCompute();
258
+ async getGaps() {
259
+ const result = await this.#getOrCompute();
283
260
  return result.gaps;
284
261
  }
285
262
  /**
286
263
  * 获取全景健康度
287
264
  */
288
- getHealth() {
289
- const result = this.#getOrCompute();
265
+ async getHealth() {
266
+ const result = await this.#getOrCompute();
290
267
  let totalCoupling = 0;
291
268
  let count = 0;
292
269
  for (const [, mod] of result.modules) {
@@ -316,8 +293,8 @@ export class PanoramaService {
316
293
  /**
317
294
  * 获取完整 PanoramaResult(内部使用或 Bootstrap 注入)
318
295
  */
319
- getResult() {
320
- return this.#getOrCompute();
296
+ async getResult() {
297
+ return await this.#getOrCompute();
321
298
  }
322
299
  /**
323
300
  * 确保全景数据已就绪(无数据时自动扫描)
@@ -328,8 +305,10 @@ export class PanoramaService {
328
305
  return;
329
306
  }
330
307
  if (!this.#scanPromise) {
331
- this.#scanPromise = this.#scanner.ensureData().then(() => {
332
- this.#cache = null; // 扫描后清除缓存以触发重新计算
308
+ this.#scanPromise = this.#scanner.ensureData().then((scanResult) => {
309
+ if (scanResult) {
310
+ this.#cache = null; // 扫描后清除缓存以触发重新计算
311
+ }
333
312
  });
334
313
  }
335
314
  await this.#scanPromise;
@@ -352,12 +331,13 @@ export class PanoramaService {
352
331
  }
353
332
  }
354
333
  /* ─── Cache + Compute ───────────────────────────── */
355
- #getOrCompute() {
334
+ async #getOrCompute() {
356
335
  if (this.#cache) {
357
336
  return this.#cache;
358
337
  }
359
- const candidates = this.#moduleDiscoverer.discover();
360
- this.#cache = this.#aggregator.compute(candidates);
338
+ const candidates = await this.#moduleDiscoverer.discover();
339
+ const configLayers = await this.#moduleDiscoverer.readConfigLayers();
340
+ this.#cache = await this.#aggregator.compute(candidates, { configLayers });
361
341
  return this.#cache;
362
342
  }
363
343
  }
@@ -33,6 +33,40 @@ export interface PanoramaModule {
33
33
  fileCount: number;
34
34
  recipeCount: number;
35
35
  coverageRatio: number;
36
+ /** 模块类型: local(有源码) / external(第三方) / host(宿主应用) */
37
+ kind?: 'local' | 'external' | 'host';
38
+ }
39
+ export interface ExternalDepProfile {
40
+ name: string;
41
+ /** 被多少本地模块依赖 */
42
+ fanIn: number;
43
+ /** 依赖此外部库的本地模块列表 */
44
+ dependedBy: string[];
45
+ /** 所属层级 */
46
+ layer?: string;
47
+ /** 声明版本 */
48
+ version?: string;
49
+ /** 技术栈分类标签 */
50
+ category?: string;
51
+ }
52
+ export interface TechStackProfile {
53
+ /** 按类别分组的外部依赖 */
54
+ categories: Array<{
55
+ name: string;
56
+ deps: Array<{
57
+ name: string;
58
+ fanIn: number;
59
+ version?: string;
60
+ }>;
61
+ }>;
62
+ /** 关键外部依赖(fan-in ≥ 3 的热点) */
63
+ hotspots: Array<{
64
+ name: string;
65
+ fanIn: number;
66
+ dependedBy: string[];
67
+ }>;
68
+ /** 外部依赖总数 */
69
+ totalExternalDeps: number;
36
70
  }
37
71
  export interface LayerLevel {
38
72
  level: number;
@@ -49,6 +83,8 @@ export interface LayerViolation {
49
83
  export interface LayerHierarchy {
50
84
  levels: LayerLevel[];
51
85
  violations: LayerViolation[];
86
+ /** 是否基于配置文件(如 Boxfile)声明的层级推断(而非纯拓扑) */
87
+ configBased?: boolean;
52
88
  }
53
89
  export interface CyclicDependency {
54
90
  cycle: string[];
@@ -120,6 +156,7 @@ export interface CallFlowSummary {
120
156
  dataProducers: string[];
121
157
  dataConsumers: string[];
122
158
  }
159
+ export type { ModuleRole } from '#shared/LanguageProfiles.js';
123
160
  export interface PanoramaResult {
124
161
  modules: Map<string, PanoramaModule>;
125
162
  layers: LayerHierarchy;
@@ -130,5 +167,9 @@ export interface PanoramaResult {
130
167
  callFlowSummary: CallFlowSummary;
131
168
  /** 项目级活跃 recipe 总数(不限模块匹配) */
132
169
  projectRecipeCount: number;
170
+ /** 外部依赖概况 */
171
+ externalDeps: ExternalDepProfile[];
172
+ /** 技术栈画像 */
173
+ techStack: TechStackProfile | null;
133
174
  computedAt: number;
134
175
  }
@@ -13,8 +13,11 @@
13
13
  *
14
14
  * @module RoleRefiner
15
15
  */
16
- import type { CeDbLike } from './PanoramaTypes.js';
17
- export type ModuleRole = 'core' | 'service' | 'ui' | 'networking' | 'storage' | 'test' | 'app' | 'routing' | 'utility' | 'model' | 'auth' | 'config' | 'feature';
16
+ import type { BootstrapRepositoryImpl } from '../../repository/bootstrap/BootstrapRepository.js';
17
+ import type { CodeEntityRepositoryImpl } from '../../repository/code/CodeEntityRepository.js';
18
+ import type { KnowledgeEdgeRepositoryImpl } from '../../repository/knowledge/KnowledgeEdgeRepository.js';
19
+ import type { ModuleRole } from './PanoramaTypes.js';
20
+ export type { ModuleRole } from './PanoramaTypes.js';
18
21
  export interface RoleSignal {
19
22
  role: ModuleRole;
20
23
  confidence: number;
@@ -33,16 +36,18 @@ export interface ModuleCandidate {
33
36
  name: string;
34
37
  inferredRole: ModuleRole;
35
38
  files: string[];
39
+ /** 来自配置文件的层级名称(如 Boxfile 中的 layer 声明) */
40
+ configLayer?: string;
36
41
  }
37
42
  export declare class RoleRefiner {
38
43
  #private;
39
- constructor(db: CeDbLike, projectRoot: string);
44
+ constructor(bootstrapRepo: BootstrapRepositoryImpl, entityRepo: CodeEntityRepositoryImpl, edgeRepo: KnowledgeEdgeRepositoryImpl, projectRoot: string);
40
45
  /**
41
46
  * 精化单个模块的角色
42
47
  */
43
- refineRole(module: ModuleCandidate): RefinedRole;
48
+ refineRole(module: ModuleCandidate): Promise<RefinedRole>;
44
49
  /**
45
50
  * 批量精化所有模块
46
51
  */
47
- refineAll(modules: ModuleCandidate[]): Map<string, RefinedRole>;
52
+ refineAll(modules: ModuleCandidate[]): Promise<Map<string, RefinedRole>>;
48
53
  }