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
@@ -15,6 +15,7 @@
15
15
  * 3. 独立价值 — 内容长度、具体性、是否有独立 coreCode
16
16
  */
17
17
  var _a;
18
+ import { COUNTABLE_LIFECYCLES } from '../../domain/knowledge/Lifecycle.js';
18
19
  import Logger from '../../infrastructure/logging/Logger.js';
19
20
  import { ContradictionDetector } from './ContradictionDetector.js';
20
21
  /* ────────────────────── Constants ────────────────────── */
@@ -29,10 +30,10 @@ const MAX_CANDIDATES_PER_ANALYSIS = 30;
29
30
  const WEIGHTS = { title: 0.2, clause: 0.3, code: 0.3, guard: 0.2 };
30
31
  /* ────────────────────── Class ────────────────────── */
31
32
  export class ConsolidationAdvisor {
32
- #db;
33
+ #knowledgeRepo;
33
34
  #logger = Logger.getInstance();
34
- constructor(db) {
35
- this.#db = db;
35
+ constructor(knowledgeRepo) {
36
+ this.#knowledgeRepo = knowledgeRepo;
36
37
  }
37
38
  /**
38
39
  * 分析候选知识与现有知识库的关系,返回融合建议。
@@ -40,11 +41,11 @@ export class ConsolidationAdvisor {
40
41
  * @param candidate - 待提交的候选数据
41
42
  * @returns ConsolidationAdvice — 建议 + 理由 + 上下文
42
43
  */
43
- analyze(candidate) {
44
+ async analyze(candidate) {
44
45
  // ── Step 1: 独立价值评估 ──
45
46
  const substanceScore = this.#assessSubstance(candidate);
46
47
  // ── Step 2: 加载同域 / 相关 Recipe ──
47
- const related = this.#loadRelatedRecipes(candidate);
48
+ const related = await this.#loadRelatedRecipes(candidate);
48
49
  // ── Step 3: insufficient — 独立价值不足,交给 Agent 与开发者决定 ──
49
50
  if (substanceScore < MIN_SUBSTANCE_SCORE) {
50
51
  if (related.length > 0) {
@@ -188,12 +189,12 @@ export class ConsolidationAdvisor {
188
189
  * @param candidates - 待提交的候选数组
189
190
  * @returns BatchConsolidationResult — 每条分析 + 批次内重叠
190
191
  */
191
- analyzeBatch(candidates) {
192
+ async analyzeBatch(candidates) {
192
193
  // 对每个候选独立分析(vs DB)
193
- const items = candidates.map((c, index) => ({
194
- index,
195
- advice: this.analyze(c),
196
- }));
194
+ const items = [];
195
+ for (let index = 0; index < candidates.length; index++) {
196
+ items.push({ index, advice: await this.analyze(candidates[index]) });
197
+ }
197
198
  // 检测批次内候选之间的相互重叠
198
199
  const internalOverlaps = [];
199
200
  for (let i = 0; i < candidates.length; i++) {
@@ -288,78 +289,41 @@ export class ConsolidationAdvisor {
288
289
  return msg;
289
290
  }
290
291
  /* ════════════════════ 相关 Recipe 加载 ════════════════════ */
291
- #loadRelatedRecipes(candidate) {
292
+ async #loadRelatedRecipes(candidate) {
292
293
  try {
293
- // 先按 category 精确匹配 + trigger 前缀匹配
294
294
  const category = candidate.category || '';
295
295
  const trigger = candidate.trigger || '';
296
296
  const triggerPrefix = trigger.startsWith('@')
297
297
  ? trigger.slice(0, Math.max(3, trigger.indexOf('-', 1) > 0 ? trigger.indexOf('-', 1) : trigger.length))
298
298
  : '';
299
- let rows;
299
+ const toSummary = (e) => ({
300
+ id: e.id,
301
+ title: e.title,
302
+ doClause: e.doClause || null,
303
+ dontClause: e.dontClause || null,
304
+ coreCode: e.coreCode || null,
305
+ category: e.category || null,
306
+ trigger: e.trigger || null,
307
+ whenClause: e.whenClause || null,
308
+ guardPattern: e.content?.pattern || null,
309
+ });
300
310
  if (category) {
301
- // category Recipe 是最有可能重叠的
302
- rows = this.#db
303
- .prepare(`SELECT id, title,
304
- doClause,
305
- dontClause,
306
- json_extract(content, '$.coreCode') AS coreCode,
307
- category, trigger, whenClause,
308
- json_extract(content, '$.pattern') AS guardPattern
309
- FROM knowledge_entries
310
- WHERE lifecycle IN ('active', 'staging', 'evolving', 'pending')
311
- AND category = ?
312
- ORDER BY lifecycle DESC
313
- LIMIT ?`)
314
- .all(category, MAX_CANDIDATES_PER_ANALYSIS);
315
- // 如果同 category 不够,再加载 trigger 相关的
316
- if (rows.length < 5 && triggerPrefix.length >= 3) {
317
- const extra = this.#db
318
- .prepare(`SELECT id, title,
319
- doClause,
320
- dontClause,
321
- json_extract(content, '$.coreCode') AS coreCode,
322
- category, trigger, whenClause,
323
- json_extract(content, '$.pattern') AS guardPattern
324
- FROM knowledge_entries
325
- WHERE lifecycle IN ('active', 'staging', 'evolving', 'pending')
326
- AND category != ?
327
- AND trigger LIKE ?
328
- LIMIT ?`)
329
- .all(category, `${triggerPrefix}%`, MAX_CANDIDATES_PER_ANALYSIS - rows.length);
330
- const existingIds = new Set(rows.map((r) => r.id));
311
+ const entries = await this.#knowledgeRepo.findAllByLifecyclesAndCategory(COUNTABLE_LIFECYCLES, category, MAX_CANDIDATES_PER_ANALYSIS);
312
+ const results = entries.map(toSummary);
313
+ if (results.length < 5 && triggerPrefix.length >= 3) {
314
+ const extra = await this.#knowledgeRepo.findByLifecyclesAndTriggerPrefix(COUNTABLE_LIFECYCLES, category, triggerPrefix, MAX_CANDIDATES_PER_ANALYSIS - results.length);
315
+ const existingIds = new Set(results.map((r) => r.id));
331
316
  for (const e of extra) {
332
- if (!existingIds.has(e.id)) {
333
- rows.push(e);
317
+ const s = toSummary(e);
318
+ if (!existingIds.has(s.id)) {
319
+ results.push(s);
334
320
  }
335
321
  }
336
322
  }
323
+ return results;
337
324
  }
338
- else {
339
- // category 时按 title 关键词粗筛
340
- rows = this.#db
341
- .prepare(`SELECT id, title,
342
- doClause,
343
- dontClause,
344
- json_extract(content, '$.coreCode') AS coreCode,
345
- category, trigger, whenClause,
346
- json_extract(content, '$.pattern') AS guardPattern
347
- FROM knowledge_entries
348
- WHERE lifecycle IN ('active', 'staging', 'evolving', 'pending')
349
- LIMIT ?`)
350
- .all(MAX_CANDIDATES_PER_ANALYSIS);
351
- }
352
- return rows.map((r) => ({
353
- id: r.id,
354
- title: r.title,
355
- doClause: r.doClause ?? null,
356
- dontClause: r.dontClause ?? null,
357
- coreCode: r.coreCode ?? null,
358
- category: r.category ?? null,
359
- trigger: r.trigger ?? null,
360
- whenClause: r.whenClause ?? null,
361
- guardPattern: r.guardPattern ?? null,
362
- }));
325
+ const entries = await this.#knowledgeRepo.findAllByLifecycles(COUNTABLE_LIFECYCLES);
326
+ return entries.slice(0, MAX_CANDIDATES_PER_ANALYSIS).map(toSummary);
363
327
  }
364
328
  catch (err) {
365
329
  this.#logger.warn(`ConsolidationAdvisor: failed to load recipes: ${err instanceof Error ? err.message : String(err)}`);
@@ -16,19 +16,12 @@
16
16
  *
17
17
  * @module service/evolution/ContentPatcher
18
18
  */
19
+ import type KnowledgeRepositoryImpl from '../../repository/knowledge/KnowledgeRepository.impl.js';
20
+ import type { RecipeSourceRefRepositoryImpl } from '../../repository/sourceref/RecipeSourceRefRepository.js';
19
21
  import type { ContentPatchResult } from '../../types/evolution.js';
20
- interface DatabaseLike {
21
- prepare(sql: string): {
22
- all(...params: unknown[]): Record<string, unknown>[];
23
- get(...params: unknown[]): Record<string, unknown> | undefined;
24
- run(...params: unknown[]): {
25
- changes: number;
26
- };
27
- };
28
- }
29
22
  export declare class ContentPatcher {
30
23
  #private;
31
- constructor(db: DatabaseLike);
24
+ constructor(knowledgeRepo: KnowledgeRepositoryImpl, sourceRefRepo: RecipeSourceRefRepositoryImpl);
32
25
  /**
33
26
  * 从 Proposal evidence 提取 suggestedChanges 并应用到 Recipe
34
27
  *
@@ -39,6 +32,5 @@ export declare class ContentPatcher {
39
32
  type: string;
40
33
  targetRecipeId: string;
41
34
  evidence: Record<string, unknown>[];
42
- }, patchSource?: 'agent-suggestion' | 'correction' | 'merge'): ContentPatchResult;
35
+ }, patchSource?: 'agent-suggestion' | 'correction' | 'merge'): Promise<ContentPatchResult>;
43
36
  }
44
- export {};
@@ -31,20 +31,22 @@ const PATCHABLE_FIELDS = new Set([
31
31
  ]);
32
32
  /* ────────────────────── Class ────────────────────── */
33
33
  export class ContentPatcher {
34
- #db;
34
+ #knowledgeRepo;
35
+ #sourceRefRepo;
35
36
  #logger = Logger.getInstance();
36
- constructor(db) {
37
- this.#db = db;
37
+ constructor(knowledgeRepo, sourceRefRepo) {
38
+ this.#knowledgeRepo = knowledgeRepo;
39
+ this.#sourceRefRepo = sourceRefRepo;
38
40
  }
39
41
  /**
40
42
  * 从 Proposal evidence 提取 suggestedChanges 并应用到 Recipe
41
43
  *
42
44
  * @returns ContentPatchResult — success: 是否成功应用了至少一个 patch
43
45
  */
44
- applyProposal(proposal, patchSource = 'agent-suggestion') {
46
+ async applyProposal(proposal, patchSource = 'agent-suggestion') {
45
47
  const recipeId = proposal.targetRecipeId;
46
48
  // 1. 获取 Recipe 当前内容
47
- const recipe = this.#getRecipe(recipeId);
49
+ const recipe = await this.#getRecipe(recipeId);
48
50
  if (!recipe) {
49
51
  return this.#skipResult(recipeId, patchSource, 'Recipe not found');
50
52
  }
@@ -66,7 +68,7 @@ export class ContentPatcher {
66
68
  return this.#skipResult(recipeId, patchSource, 'No valid fields to patch');
67
69
  }
68
70
  // 6. 持久化
69
- this.#persistRecipe(recipe);
71
+ await this.#persistRecipe(recipe);
70
72
  // 7. 创建 after 快照
71
73
  const afterSnapshot = this.#createSnapshot(recipe);
72
74
  this.#logger.info(`[ContentPatcher] Applied ${fieldsPatched.length} patches to recipe ${recipeId}: ${fieldsPatched.join(', ')}`);
@@ -257,20 +259,47 @@ export class ContentPatcher {
257
259
  };
258
260
  }
259
261
  /* ═══════════════════ DB ═══════════════════ */
260
- #getRecipe(recipeId) {
261
- const row = this.#db
262
- .prepare(`SELECT id, title, coreCode, doClause, dontClause, whenClause, content, sourceRefs, headers
263
- FROM knowledge_entries WHERE id = ?`)
264
- .get(recipeId);
265
- return row ?? null;
262
+ async #getRecipe(recipeId) {
263
+ const entry = await this.#knowledgeRepo.findById(recipeId);
264
+ if (!entry) {
265
+ return null;
266
+ }
267
+ // recipe_source_refs 表读取关联的源引用路径
268
+ const refs = this.#sourceRefRepo.findByRecipeId(entry.id);
269
+ const sourcePaths = refs.map((r) => r.sourcePath);
270
+ return {
271
+ id: entry.id,
272
+ title: entry.title,
273
+ coreCode: entry.coreCode || '',
274
+ doClause: entry.doClause || '',
275
+ dontClause: entry.dontClause || '',
276
+ whenClause: entry.whenClause || '',
277
+ content: JSON.stringify(entry.content || {}),
278
+ sourceRefs: JSON.stringify(sourcePaths),
279
+ headers: JSON.stringify(entry.headers || []),
280
+ };
266
281
  }
267
- #persistRecipe(recipe) {
268
- this.#db
269
- .prepare(`UPDATE knowledge_entries
270
- SET coreCode = ?, doClause = ?, dontClause = ?, whenClause = ?,
271
- content = ?, sourceRefs = ?, headers = ?, updatedAt = ?
272
- WHERE id = ?`)
273
- .run(recipe.coreCode, recipe.doClause, recipe.dontClause, recipe.whenClause, recipe.content, recipe.sourceRefs, recipe.headers, Date.now(), recipe.id);
282
+ async #persistRecipe(recipe) {
283
+ await this.#knowledgeRepo.update(recipe.id, {
284
+ coreCode: recipe.coreCode,
285
+ doClause: recipe.doClause,
286
+ dontClause: recipe.dontClause,
287
+ whenClause: recipe.whenClause,
288
+ content: safeJsonParse(recipe.content, {}),
289
+ headers: safeJsonParse(recipe.headers, []),
290
+ });
291
+ // 同步 sourceRefs 到 recipe_source_refs 表
292
+ const newPaths = safeJsonParse(recipe.sourceRefs, []);
293
+ const now = Math.floor(Date.now() / 1000);
294
+ this.#sourceRefRepo.deleteByRecipeId(recipe.id);
295
+ for (const sourcePath of newPaths) {
296
+ this.#sourceRefRepo.upsert({
297
+ recipeId: recipe.id,
298
+ sourcePath,
299
+ status: 'active',
300
+ verifiedAt: now,
301
+ });
302
+ }
274
303
  }
275
304
  /* ═══════════════════ Helpers ═══════════════════ */
276
305
  #skipResult(recipeId, patchSource, reason) {
@@ -13,11 +13,7 @@
13
13
  * 结果:硬矛盾 (confidence ≥ 0.8) / 软矛盾 (0.4-0.8)
14
14
  */
15
15
  import type { SignalBus } from '../../infrastructure/signal/SignalBus.js';
16
- interface DatabaseLike {
17
- prepare(sql: string): {
18
- all(...params: unknown[]): Record<string, unknown>[];
19
- };
20
- }
16
+ import type KnowledgeRepositoryImpl from '../../repository/knowledge/KnowledgeRepository.impl.js';
21
17
  export interface ContradictionResult {
22
18
  recipeA: string;
23
19
  recipeB: string;
@@ -37,13 +33,13 @@ interface RecipeEntry {
37
33
  }
38
34
  export declare class ContradictionDetector {
39
35
  #private;
40
- constructor(db: DatabaseLike, options?: {
36
+ constructor(knowledgeRepo: KnowledgeRepositoryImpl, options?: {
41
37
  signalBus?: SignalBus;
42
38
  });
43
39
  /**
44
40
  * 检测所有 active/staging/evolving Recipe 之间的矛盾
45
41
  */
46
- detectAll(): ContradictionResult[];
42
+ detectAll(): Promise<ContradictionResult[]>;
47
43
  /**
48
44
  * 检测两条 Recipe 是否矛盾
49
45
  */
@@ -13,6 +13,7 @@
13
13
  * 结果:硬矛盾 (confidence ≥ 0.8) / 软矛盾 (0.4-0.8)
14
14
  */
15
15
  var _a;
16
+ import { CONSUMABLE_LIFECYCLES } from '../../domain/knowledge/Lifecycle.js';
16
17
  import Logger from '../../infrastructure/logging/Logger.js';
17
18
  /* ────────────────────── Constants ────────────────────── */
18
19
  const NEGATION_PATTERNS_ZH = /不(再)?使用|禁止|废弃|移除|取消|停止|不要|不采用|弃用|淘汰/;
@@ -71,18 +72,18 @@ const STOP_WORDS = new Set([
71
72
  ]);
72
73
  /* ────────────────────── Class ────────────────────── */
73
74
  export class ContradictionDetector {
74
- #db;
75
+ #knowledgeRepo;
75
76
  #signalBus;
76
77
  #logger = Logger.getInstance();
77
- constructor(db, options = {}) {
78
- this.#db = db;
78
+ constructor(knowledgeRepo, options = {}) {
79
+ this.#knowledgeRepo = knowledgeRepo;
79
80
  this.#signalBus = options.signalBus ?? null;
80
81
  }
81
82
  /**
82
83
  * 检测所有 active/staging/evolving Recipe 之间的矛盾
83
84
  */
84
- detectAll() {
85
- const recipes = this.#loadRecipes();
85
+ async detectAll() {
86
+ const recipes = await this.#loadRecipes();
86
87
  const results = [];
87
88
  for (let i = 0; i < recipes.length; i++) {
88
89
  for (let j = i + 1; j < recipes.length; j++) {
@@ -155,26 +156,18 @@ export class ContradictionDetector {
155
156
  };
156
157
  }
157
158
  /* ── Internal ── */
158
- #loadRecipes() {
159
+ async #loadRecipes() {
159
160
  try {
160
- const rows = this.#db
161
- .prepare(`SELECT id, title, lifecycle, description,
162
- json_extract(content, '$.markdown') AS content_markdown,
163
- doClause,
164
- dontClause,
165
- json_extract(content, '$.pattern') AS guardPattern
166
- FROM knowledge_entries
167
- WHERE lifecycle IN ('active', 'staging', 'evolving')`)
168
- .all();
169
- return rows.map((r) => ({
170
- id: r.id,
171
- title: r.title,
172
- lifecycle: r.lifecycle,
173
- doClause: r.doClause ?? null,
174
- dontClause: r.dontClause ?? null,
175
- guardPattern: r.guardPattern ?? null,
176
- description: r.description ?? null,
177
- content_markdown: r.content_markdown ?? null,
161
+ const entries = await this.#knowledgeRepo.findAllByLifecycles(CONSUMABLE_LIFECYCLES);
162
+ return entries.map((e) => ({
163
+ id: e.id,
164
+ title: e.title,
165
+ lifecycle: e.lifecycle,
166
+ doClause: e.doClause || null,
167
+ dontClause: e.dontClause || null,
168
+ guardPattern: e.content?.pattern || null,
169
+ description: e.description || null,
170
+ content_markdown: e.content?.markdown || null,
178
171
  }));
179
172
  }
180
173
  catch {
@@ -18,13 +18,11 @@
18
18
  * 20-39: 严重 → Grace Period 缩短到 15d
19
19
  * 0-19: 死亡 → 跳过确认直接 deprecated
20
20
  */
21
+ import type { DrizzleDB } from '../../infrastructure/database/drizzle/index.js';
21
22
  import type { SignalBus } from '../../infrastructure/signal/SignalBus.js';
22
- interface DatabaseLike {
23
- prepare(sql: string): {
24
- all(...params: unknown[]): Record<string, unknown>[];
25
- get(...params: unknown[]): Record<string, unknown> | undefined;
26
- };
27
- }
23
+ import type { KnowledgeEdgeRepositoryImpl } from '../../repository/knowledge/KnowledgeEdgeRepository.js';
24
+ import type KnowledgeRepositoryImpl from '../../repository/knowledge/KnowledgeRepository.impl.js';
25
+ import type { RecipeSourceRefRepositoryImpl } from '../../repository/sourceref/RecipeSourceRefRepository.js';
28
26
  export interface DecaySignal {
29
27
  recipeId: string;
30
28
  strategy: DecayStrategy;
@@ -57,16 +55,19 @@ interface RecipeForDecay {
57
55
  }
58
56
  export declare class DecayDetector {
59
57
  #private;
60
- constructor(db: DatabaseLike, options?: {
58
+ constructor(knowledgeRepo: KnowledgeRepositoryImpl, options?: {
61
59
  signalBus?: SignalBus;
60
+ knowledgeEdgeRepo?: KnowledgeEdgeRepositoryImpl;
61
+ sourceRefRepo?: RecipeSourceRefRepositoryImpl;
62
+ drizzle?: DrizzleDB;
62
63
  });
63
64
  /**
64
65
  * 扫描所有 active 条目的衰退状态
65
66
  */
66
- scanAll(): DecayScoreResult[];
67
+ scanAll(): Promise<DecayScoreResult[]>;
67
68
  /**
68
69
  * 评估单条 Recipe 的衰退状态
69
70
  */
70
- evaluate(recipe: RecipeForDecay): DecayScoreResult;
71
+ evaluate(recipe: RecipeForDecay): Promise<DecayScoreResult>;
71
72
  }
72
73
  export {};
@@ -19,6 +19,8 @@
19
19
  * 0-19: 死亡 → 跳过确认直接 deprecated
20
20
  */
21
21
  var _a;
22
+ import { and, like, sql } from 'drizzle-orm';
23
+ import { auditLogs } from '../../infrastructure/database/drizzle/schema.js';
22
24
  import Logger from '../../infrastructure/logging/Logger.js';
23
25
  /* ────────────────────── Helpers ────────────────────── */
24
26
  /**
@@ -49,21 +51,27 @@ const SCORE_WEIGHTS = {
49
51
  };
50
52
  /* ────────────────────── Class ────────────────────── */
51
53
  export class DecayDetector {
52
- #db;
54
+ #knowledgeRepo;
55
+ #edgeRepo;
56
+ #sourceRefRepo;
57
+ #drizzle;
53
58
  #signalBus;
54
59
  #logger = Logger.getInstance();
55
- constructor(db, options = {}) {
56
- this.#db = db;
60
+ constructor(knowledgeRepo, options = {}) {
61
+ this.#knowledgeRepo = knowledgeRepo;
62
+ this.#edgeRepo = options.knowledgeEdgeRepo ?? null;
63
+ this.#sourceRefRepo = options.sourceRefRepo ?? null;
64
+ this.#drizzle = options.drizzle ?? null;
57
65
  this.#signalBus = options.signalBus ?? null;
58
66
  }
59
67
  /**
60
68
  * 扫描所有 active 条目的衰退状态
61
69
  */
62
- scanAll() {
63
- const recipes = this.#loadActiveRecipes();
70
+ async scanAll() {
71
+ const recipes = await this.#loadActiveRecipes();
64
72
  const results = [];
65
73
  for (const recipe of recipes) {
66
- const result = this.evaluate(recipe);
74
+ const result = await this.evaluate(recipe);
67
75
  results.push(result);
68
76
  }
69
77
  // 发射衰退信号
@@ -87,7 +95,7 @@ export class DecayDetector {
87
95
  /**
88
96
  * 评估单条 Recipe 的衰退状态
89
97
  */
90
- evaluate(recipe) {
98
+ async evaluate(recipe) {
91
99
  const stats = _a.#parseStats(recipe.stats);
92
100
  const signals = [];
93
101
  const now = Date.now();
@@ -127,7 +135,7 @@ export class DecayDetector {
127
135
  });
128
136
  }
129
137
  // 策略 3: 符号漂移(由 ReverseGuard 提供,此处从 DB 查 drift 标记)
130
- if (this.#hasSymbolDrift(recipe.id)) {
138
+ if (await this.#hasSymbolDrift(recipe.id)) {
131
139
  signals.push({
132
140
  recipeId: recipe.id,
133
141
  strategy: 'symbol_drift',
@@ -135,7 +143,7 @@ export class DecayDetector {
135
143
  });
136
144
  }
137
145
  // 策略 3b: 来源引用失效(由 SourceRefReconciler 填充 recipe_source_refs)
138
- const staleRefCount = this.#getStaleSourceRefCount(recipe.id);
146
+ const staleRefCount = await this.#getStaleSourceRefCount(recipe.id);
139
147
  if (staleRefCount > 0) {
140
148
  signals.push({
141
149
  recipeId: recipe.id,
@@ -144,7 +152,7 @@ export class DecayDetector {
144
152
  });
145
153
  }
146
154
  // 策略 4: 被取代(有 deprecated_by 关系指向更新版本)
147
- if (this.#isSuperseded(recipe.id)) {
155
+ if (await this.#isSuperseded(recipe.id)) {
148
156
  signals.push({
149
157
  recipeId: recipe.id,
150
158
  strategy: 'superseded',
@@ -152,7 +160,7 @@ export class DecayDetector {
152
160
  });
153
161
  }
154
162
  // 计算 decayScore(staleRatio 影响 quality 维度)
155
- const staleRatio = this.#getSourceRefStaleRatio(recipe.id);
163
+ const staleRatio = await this.#getSourceRefStaleRatio(recipe.id);
156
164
  const dimensions = this.#computeScoreDimensions(stats, recipe, { staleRatio });
157
165
  const decayScore = Math.round(dimensions.freshness * SCORE_WEIGHTS.freshness * 100 +
158
166
  dimensions.usage * SCORE_WEIGHTS.usage * 100 +
@@ -171,23 +179,24 @@ export class DecayDetector {
171
179
  };
172
180
  }
173
181
  /* ── Internal ── */
174
- #loadActiveRecipes() {
182
+ async #loadActiveRecipes() {
175
183
  try {
176
- const rows = this.#db
177
- .prepare(`SELECT id, title, lifecycle, stats, quality, createdAt
178
- FROM knowledge_entries
179
- WHERE lifecycle = 'active'`)
180
- .all();
181
- return rows.map((r) => {
182
- const qualityObj = _a.#parseQuality(r.quality);
184
+ const entries = await this.#knowledgeRepo.findAllByLifecycles(['active']);
185
+ return entries.map((e) => {
186
+ const qualityObj = typeof e.quality === 'object'
187
+ ? {
188
+ grade: e.quality.grade ?? null,
189
+ score: e.quality.overall ?? null,
190
+ }
191
+ : _a.#parseQuality(null);
183
192
  return {
184
- id: r.id,
185
- title: r.title,
186
- lifecycle: r.lifecycle,
187
- stats: r.stats ?? null,
193
+ id: e.id,
194
+ title: e.title,
195
+ lifecycle: e.lifecycle,
196
+ stats: typeof e.stats === 'object' ? JSON.stringify(e.stats) : null,
188
197
  quality_grade: qualityObj.grade,
189
198
  quality_score: qualityObj.score,
190
- created_at: r.createdAt !== undefined ? Number(r.createdAt) : null,
199
+ created_at: e.createdAt ?? null,
191
200
  };
192
201
  });
193
202
  }
@@ -240,61 +249,58 @@ export class DecayDetector {
240
249
  const authority = Math.min(1, authorityRaw / 100);
241
250
  return { freshness, usage, quality, authority };
242
251
  }
243
- #hasSymbolDrift(recipeId) {
252
+ async #hasSymbolDrift(recipeId) {
244
253
  try {
245
- // 查找 audit_logs 中 ReverseGuard 为此 recipe 发过 drift 信号
246
- const row = this.#db
247
- .prepare(`SELECT 1 FROM audit_logs
248
- WHERE action LIKE '%ReverseGuard%'
249
- AND json_extract(details, '$.target') = ?
250
- LIMIT 1`)
251
- .get(recipeId);
254
+ if (!this.#drizzle) {
255
+ return false;
256
+ }
257
+ const row = this.#drizzle
258
+ .select({ id: auditLogs.id })
259
+ .from(auditLogs)
260
+ .where(and(like(auditLogs.action, '%ReverseGuard%'), sql `json_extract(${auditLogs.operationData}, '$.target') = ${recipeId}`))
261
+ .limit(1)
262
+ .get();
252
263
  return !!row;
253
264
  }
254
265
  catch {
255
266
  return false;
256
267
  }
257
268
  }
258
- #getStaleSourceRefCount(recipeId) {
269
+ async #getStaleSourceRefCount(recipeId) {
259
270
  try {
260
- const row = this.#db
261
- .prepare(`SELECT COUNT(*) AS cnt FROM recipe_source_refs
262
- WHERE recipe_id = ? AND status = 'stale'`)
263
- .get(recipeId);
264
- return row?.cnt ?? 0;
271
+ if (!this.#sourceRefRepo) {
272
+ return 0;
273
+ }
274
+ const refs = this.#sourceRefRepo.findByRecipeId(recipeId);
275
+ return refs.filter((r) => r.status === 'stale').length;
265
276
  }
266
277
  catch {
267
- // recipe_source_refs 表可能不存在
268
278
  return 0;
269
279
  }
270
280
  }
271
- /** stale / total 比率(0-1),无 ref 时返回 0(无惩罚) */
272
- #getSourceRefStaleRatio(recipeId) {
281
+ async #getSourceRefStaleRatio(recipeId) {
273
282
  try {
274
- const row = this.#db
275
- .prepare(`SELECT
276
- SUM(CASE WHEN status = 'stale' THEN 1 ELSE 0 END) AS stale,
277
- COUNT(*) AS total
278
- FROM recipe_source_refs
279
- WHERE recipe_id = ?`)
280
- .get(recipeId);
281
- if (!row || row.total === 0) {
283
+ if (!this.#sourceRefRepo) {
282
284
  return 0;
283
285
  }
284
- return row.stale / row.total;
286
+ const refs = this.#sourceRefRepo.findByRecipeId(recipeId);
287
+ if (refs.length === 0) {
288
+ return 0;
289
+ }
290
+ const stale = refs.filter((r) => r.status === 'stale').length;
291
+ return stale / refs.length;
285
292
  }
286
293
  catch {
287
294
  return 0;
288
295
  }
289
296
  }
290
- #isSuperseded(recipeId) {
297
+ async #isSuperseded(recipeId) {
291
298
  try {
292
- const row = this.#db
293
- .prepare(`SELECT 1 FROM knowledge_edges
294
- WHERE source_id = ? AND relation_type = 'deprecated_by'
295
- LIMIT 1`)
296
- .get(recipeId);
297
- return !!row;
299
+ if (!this.#edgeRepo) {
300
+ return false;
301
+ }
302
+ const edges = await this.#edgeRepo.findByRelation(recipeId, 'recipe', 'deprecated_by');
303
+ return edges.length > 0;
298
304
  }
299
305
  catch {
300
306
  return false;