autosnippet 3.0.0 → 3.0.2

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 (290) hide show
  1. package/README.md +230 -324
  2. package/bin/api-server.js +1 -1
  3. package/bin/cli.js +204 -244
  4. package/bin/mcp-server.js +5 -3
  5. package/config/knowledge-base.config.js +132 -132
  6. package/dashboard/dist/assets/{icons-CEfgGaZi.js → icons-Cdq22n2i.js} +95 -100
  7. package/dashboard/dist/assets/index-ClkyPkDX.js +133 -0
  8. package/dashboard/dist/assets/index-t4QrJwv1.css +1 -0
  9. package/dashboard/dist/index.html +3 -3
  10. package/lib/bootstrap.js +8 -8
  11. package/lib/cli/AiScanService.js +86 -40
  12. package/lib/cli/KnowledgeSyncService.js +113 -74
  13. package/lib/cli/SetupService.js +439 -277
  14. package/lib/cli/UpgradeService.js +63 -100
  15. package/lib/core/AstAnalyzer.js +276 -597
  16. package/lib/core/ast/ProjectGraph.js +101 -40
  17. package/lib/core/ast/ensure-grammars.js +232 -0
  18. package/lib/core/ast/index.js +115 -0
  19. package/lib/core/ast/lang-dart.js +661 -0
  20. package/lib/core/ast/lang-go.js +530 -0
  21. package/lib/core/ast/lang-java.js +435 -0
  22. package/lib/core/ast/lang-javascript.js +272 -0
  23. package/lib/core/ast/lang-kotlin.js +423 -0
  24. package/lib/core/ast/lang-objc.js +388 -0
  25. package/lib/core/ast/lang-python.js +371 -0
  26. package/lib/core/ast/lang-swift.js +337 -0
  27. package/lib/core/ast/lang-typescript.js +503 -0
  28. package/lib/core/capability/CapabilityProbe.js +18 -9
  29. package/lib/core/constitution/Constitution.js +2 -3
  30. package/lib/core/constitution/ConstitutionValidator.js +65 -24
  31. package/lib/core/discovery/DartDiscoverer.js +534 -0
  32. package/lib/core/discovery/DiscovererRegistry.js +83 -0
  33. package/lib/core/discovery/GenericDiscoverer.js +225 -0
  34. package/lib/core/discovery/GoDiscoverer.js +541 -0
  35. package/lib/core/discovery/JvmDiscoverer.js +506 -0
  36. package/lib/core/discovery/NodeDiscoverer.js +466 -0
  37. package/lib/core/discovery/ProjectDiscoverer.js +93 -0
  38. package/lib/core/discovery/PythonDiscoverer.js +338 -0
  39. package/lib/core/discovery/SpmDiscoverer.js +5 -0
  40. package/lib/core/discovery/index.js +53 -0
  41. package/lib/core/enhancement/EnhancementPack.js +71 -0
  42. package/lib/core/enhancement/EnhancementRegistry.js +47 -0
  43. package/lib/core/enhancement/android-enhancement.js +102 -0
  44. package/lib/core/enhancement/django-enhancement.js +70 -0
  45. package/lib/core/enhancement/fastapi-enhancement.js +63 -0
  46. package/lib/core/enhancement/go-grpc-enhancement.js +152 -0
  47. package/lib/core/enhancement/go-web-enhancement.js +201 -0
  48. package/lib/core/enhancement/index.js +65 -0
  49. package/lib/core/enhancement/node-server-enhancement.js +88 -0
  50. package/lib/core/enhancement/react-enhancement.js +86 -0
  51. package/lib/core/enhancement/spring-enhancement.js +112 -0
  52. package/lib/core/enhancement/vue-enhancement.js +96 -0
  53. package/lib/core/gateway/Gateway.js +8 -9
  54. package/lib/core/gateway/GatewayActionRegistry.js +1 -1
  55. package/lib/core/permission/PermissionManager.js +12 -8
  56. package/lib/domain/index.js +13 -9
  57. package/lib/domain/knowledge/KnowledgeEntry.js +111 -101
  58. package/lib/domain/knowledge/KnowledgeRepository.js +0 -1
  59. package/lib/domain/knowledge/Lifecycle.js +22 -22
  60. package/lib/domain/knowledge/index.js +9 -12
  61. package/lib/domain/knowledge/values/Constraints.js +31 -21
  62. package/lib/domain/knowledge/values/Content.js +21 -13
  63. package/lib/domain/knowledge/values/Quality.js +31 -18
  64. package/lib/domain/knowledge/values/Reasoning.js +20 -12
  65. package/lib/domain/knowledge/values/Relations.js +37 -25
  66. package/lib/domain/knowledge/values/Stats.js +18 -12
  67. package/lib/domain/knowledge/values/index.js +4 -3
  68. package/lib/domain/snippet/Snippet.js +35 -10
  69. package/lib/external/ai/AiFactory.js +48 -16
  70. package/lib/external/ai/AiProvider.js +184 -90
  71. package/lib/external/ai/providers/ClaudeProvider.js +25 -12
  72. package/lib/external/ai/providers/GoogleGeminiProvider.js +59 -30
  73. package/lib/external/ai/providers/MockProvider.js +9 -3
  74. package/lib/external/ai/providers/OpenAiProvider.js +51 -29
  75. package/lib/external/mcp/McpServer.js +66 -36
  76. package/lib/external/mcp/errorHandler.js +23 -11
  77. package/lib/external/mcp/handlers/LanguageExtensions.js +138 -53
  78. package/lib/external/mcp/handlers/TargetClassifier.js +52 -16
  79. package/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +81 -20
  80. package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +71 -42
  81. package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +9 -17
  82. package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +14 -9
  83. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +15 -7
  84. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +352 -153
  85. package/lib/external/mcp/handlers/bootstrap/pipeline/tier-scheduler.js +52 -12
  86. package/lib/external/mcp/handlers/bootstrap/skills.js +143 -39
  87. package/lib/external/mcp/handlers/bootstrap.js +691 -168
  88. package/lib/external/mcp/handlers/browse.js +66 -22
  89. package/lib/external/mcp/handlers/candidate.js +118 -35
  90. package/lib/external/mcp/handlers/consolidated.js +49 -17
  91. package/lib/external/mcp/handlers/guard.js +104 -39
  92. package/lib/external/mcp/handlers/knowledge.js +60 -36
  93. package/lib/external/mcp/handlers/search.js +43 -14
  94. package/lib/external/mcp/handlers/skill.js +120 -45
  95. package/lib/external/mcp/handlers/structure.js +240 -86
  96. package/lib/external/mcp/handlers/system.js +42 -12
  97. package/lib/external/mcp/handlers/wiki.js +58 -33
  98. package/lib/external/mcp/tools.js +306 -123
  99. package/lib/http/HttpServer.js +72 -47
  100. package/lib/http/middleware/RateLimiter.js +5 -3
  101. package/lib/http/middleware/errorHandler.js +6 -1
  102. package/lib/http/middleware/requestLogger.js +14 -3
  103. package/lib/http/middleware/roleResolver.js +30 -23
  104. package/lib/http/routes/ai.js +387 -265
  105. package/lib/http/routes/auth.js +81 -61
  106. package/lib/http/routes/candidates.js +430 -320
  107. package/lib/http/routes/commands.js +289 -189
  108. package/lib/http/routes/extract.js +158 -125
  109. package/lib/http/routes/guardRules.js +309 -217
  110. package/lib/http/routes/knowledge.js +213 -154
  111. package/lib/http/routes/modules.js +578 -0
  112. package/lib/http/routes/monitoring.js +6 -6
  113. package/lib/http/routes/recipes.js +104 -93
  114. package/lib/http/routes/search.js +361 -305
  115. package/lib/http/routes/skills.js +145 -98
  116. package/lib/http/routes/snippets.js +42 -30
  117. package/lib/http/routes/spm.js +3 -405
  118. package/lib/http/routes/violations.js +113 -93
  119. package/lib/http/routes/wiki.js +211 -170
  120. package/lib/http/utils/routeHelpers.js +3 -1
  121. package/lib/http/utils/sse-sessions.js +16 -6
  122. package/lib/http/utils/sse.js +15 -5
  123. package/lib/infrastructure/audit/AuditLogger.js +5 -2
  124. package/lib/infrastructure/audit/AuditStore.js +10 -7
  125. package/lib/infrastructure/cache/CacheService.js +3 -1
  126. package/lib/infrastructure/cache/GraphCache.js +8 -4
  127. package/lib/infrastructure/cache/UnifiedCacheAdapter.js +1 -1
  128. package/lib/infrastructure/config/ConfigLoader.js +9 -5
  129. package/lib/infrastructure/config/Defaults.js +30 -10
  130. package/lib/infrastructure/config/Paths.js +28 -8
  131. package/lib/infrastructure/config/TriggerSymbol.js +22 -10
  132. package/lib/infrastructure/database/DatabaseConnection.js +15 -10
  133. package/lib/infrastructure/database/migrations/001_initial_schema.js +0 -1
  134. package/lib/infrastructure/external/ClipboardManager.js +6 -2
  135. package/lib/infrastructure/external/NativeUi.js +50 -43
  136. package/lib/infrastructure/external/OpenBrowser.js +14 -17
  137. package/lib/infrastructure/external/XcodeAutomation.js +14 -258
  138. package/lib/infrastructure/logging/Logger.js +46 -30
  139. package/lib/infrastructure/monitoring/ErrorTracker.js +7 -5
  140. package/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -4
  141. package/lib/infrastructure/paths/HeaderResolver.js +25 -9
  142. package/lib/infrastructure/paths/PathFinder.js +34 -12
  143. package/lib/infrastructure/plugin/PluginManager.js +26 -8
  144. package/lib/infrastructure/realtime/RealtimeService.js +2 -2
  145. package/lib/infrastructure/vector/Chunker.js +22 -7
  146. package/lib/infrastructure/vector/IndexingPipeline.js +46 -22
  147. package/lib/infrastructure/vector/JsonVectorAdapter.js +90 -53
  148. package/lib/infrastructure/vector/VectorStore.js +28 -10
  149. package/lib/injection/ServiceContainer.js +247 -93
  150. package/lib/platform/ios/index.js +63 -0
  151. package/lib/platform/ios/routes/spm.js +437 -0
  152. package/lib/platform/ios/snippet/PlaceholderConverter.js +55 -0
  153. package/lib/platform/ios/snippet/XcodeCodec.js +112 -0
  154. package/lib/{service → platform/ios}/spm/DependencyGraph.js +41 -17
  155. package/lib/{service → platform/ios}/spm/PackageSwiftParser.js +41 -14
  156. package/lib/{service → platform/ios}/spm/PolicyEngine.js +9 -4
  157. package/lib/platform/ios/spm/SpmDiscoverer.js +122 -0
  158. package/lib/{service → platform/ios}/spm/SpmService.js +385 -127
  159. package/lib/{service/automation → platform/ios/xcode}/SaveEventFilter.js +8 -7
  160. package/lib/platform/ios/xcode/XcodeAutomation.js +350 -0
  161. package/lib/{service/automation → platform/ios/xcode}/XcodeIntegration.js +325 -145
  162. package/lib/repository/base/BaseRepository.js +7 -9
  163. package/lib/repository/knowledge/KnowledgeRepository.impl.js +98 -75
  164. package/lib/repository/token/TokenUsageStore.js +4 -2
  165. package/lib/service/automation/ActionPipeline.js +1 -1
  166. package/lib/service/automation/AutomationOrchestrator.js +8 -4
  167. package/lib/service/automation/ContextCollector.js +7 -5
  168. package/lib/service/automation/DirectiveDetector.js +23 -16
  169. package/lib/service/automation/FileWatcher.js +112 -56
  170. package/lib/service/automation/TriggerResolver.js +6 -4
  171. package/lib/service/automation/handlers/AlinkHandler.js +24 -12
  172. package/lib/service/automation/handlers/CreateHandler.js +19 -20
  173. package/lib/service/automation/handlers/DraftHandler.js +14 -8
  174. package/lib/service/automation/handlers/GuardHandler.js +93 -63
  175. package/lib/service/automation/handlers/HeaderHandler.js +1 -6
  176. package/lib/service/automation/handlers/SearchHandler.js +155 -88
  177. package/lib/service/bootstrap/BootstrapTaskManager.js +77 -35
  178. package/lib/service/candidate/SimilarityService.js +25 -9
  179. package/lib/service/chat/AnalystAgent.js +50 -24
  180. package/lib/service/chat/CandidateGuardrail.js +143 -17
  181. package/lib/service/chat/ChatAgent.js +759 -243
  182. package/lib/service/chat/ContextWindow.js +116 -71
  183. package/lib/service/chat/ConversationStore.js +77 -36
  184. package/lib/service/chat/EpisodicConsolidator.js +47 -23
  185. package/lib/service/chat/HandoffProtocol.js +98 -22
  186. package/lib/service/chat/Memory.js +34 -14
  187. package/lib/service/chat/ProducerAgent.js +40 -20
  188. package/lib/service/chat/ProjectSemanticMemory.js +109 -78
  189. package/lib/service/chat/ReasoningLayer.js +148 -70
  190. package/lib/service/chat/ReasoningTrace.js +44 -32
  191. package/lib/service/chat/TaskPipeline.js +39 -19
  192. package/lib/service/chat/ToolRegistry.js +48 -29
  193. package/lib/service/chat/WorkingMemory.js +44 -18
  194. package/lib/service/chat/tools.js +1096 -494
  195. package/lib/service/context/RecipeExtractor.js +132 -51
  196. package/lib/service/cursor/CursorDeliveryPipeline.js +82 -37
  197. package/lib/service/cursor/KnowledgeCompressor.js +25 -22
  198. package/lib/service/cursor/RulesGenerator.js +13 -7
  199. package/lib/service/cursor/SkillsSyncer.js +77 -27
  200. package/lib/service/cursor/TokenBudget.js +2 -2
  201. package/lib/service/cursor/TopicClassifier.js +54 -20
  202. package/lib/service/guard/ComplianceReporter.js +55 -43
  203. package/lib/service/guard/ExclusionManager.js +67 -29
  204. package/lib/service/guard/GuardCheckEngine.js +381 -86
  205. package/lib/service/guard/GuardFeedbackLoop.js +22 -10
  206. package/lib/service/guard/GuardService.js +29 -19
  207. package/lib/service/guard/RuleLearner.js +55 -23
  208. package/lib/service/guard/SourceFileCollector.js +27 -20
  209. package/lib/service/guard/ViolationsStore.js +43 -38
  210. package/lib/service/knowledge/CodeEntityGraph.js +147 -82
  211. package/lib/service/knowledge/ConfidenceRouter.js +12 -10
  212. package/lib/service/knowledge/KnowledgeFileWriter.js +147 -56
  213. package/lib/service/knowledge/KnowledgeGraphService.js +81 -34
  214. package/lib/service/knowledge/KnowledgeService.js +222 -112
  215. package/lib/service/module/ModuleService.js +969 -0
  216. package/lib/service/quality/FeedbackCollector.js +27 -15
  217. package/lib/service/quality/QualityScorer.js +78 -24
  218. package/lib/service/recipe/RecipeCandidateValidator.js +110 -44
  219. package/lib/service/recipe/RecipeParser.js +78 -45
  220. package/lib/service/search/CoarseRanker.js +43 -28
  221. package/lib/service/search/CrossEncoderReranker.js +32 -21
  222. package/lib/service/search/InvertedIndex.js +21 -7
  223. package/lib/service/search/MultiSignalRanker.js +90 -28
  224. package/lib/service/search/RetrievalFunnel.js +45 -24
  225. package/lib/service/search/SearchEngine.js +255 -103
  226. package/lib/service/skills/EventAggregator.js +32 -15
  227. package/lib/service/skills/SignalCollector.js +140 -64
  228. package/lib/service/skills/SkillAdvisor.js +79 -42
  229. package/lib/service/skills/SkillHooks.js +16 -14
  230. package/lib/service/snippet/PlaceholderConverter.js +5 -0
  231. package/lib/service/snippet/SnippetFactory.js +116 -99
  232. package/lib/service/snippet/SnippetInstaller.js +234 -62
  233. package/lib/service/snippet/codecs/SnippetCodec.js +67 -0
  234. package/lib/service/snippet/codecs/VSCodeCodec.js +102 -0
  235. package/lib/service/snippet/codecs/XcodeCodec.js +5 -0
  236. package/lib/service/wiki/WikiGenerator.js +637 -263
  237. package/lib/shared/DimensionCopyRegistry.js +472 -0
  238. package/lib/shared/LanguageService.js +399 -0
  239. package/lib/shared/PathGuard.js +45 -28
  240. package/lib/shared/RecipeReadinessChecker.js +72 -12
  241. package/lib/shared/constants.js +41 -41
  242. package/lib/shared/errors/BaseError.js +2 -2
  243. package/lib/shared/errors/index.js +4 -4
  244. package/lib/shared/similarity.js +25 -8
  245. package/lib/shared/token-utils.js +6 -2
  246. package/lib/shared/utils/common.js +12 -4
  247. package/package.json +49 -13
  248. package/scripts/bench-real-projects.mjs +256 -0
  249. package/scripts/build-native-ui.js +30 -30
  250. package/scripts/clear-old-vector-index.js +5 -35
  251. package/scripts/clear-vector-cache.js +7 -37
  252. package/scripts/collect-test-project-stats.mjs +160 -0
  253. package/scripts/diagnose-mcp.js +41 -32
  254. package/scripts/ensure-parse-package.js +6 -9
  255. package/scripts/generate-recipe-drafts.js +116 -77
  256. package/scripts/init-db.js +3 -20
  257. package/scripts/init-snippets.js +305 -0
  258. package/scripts/init-vector-db.js +173 -170
  259. package/scripts/install-cursor-skill.js +148 -104
  260. package/scripts/install-full.js +8 -21
  261. package/scripts/install-vscode-copilot.js +146 -145
  262. package/scripts/migrate-md-to-knowledge.mjs +139 -151
  263. package/scripts/postinstall-safe.js +5 -17
  264. package/scripts/recipe-audit.js +106 -82
  265. package/scripts/release.js +283 -323
  266. package/scripts/setup-mcp-config.js +60 -52
  267. package/scripts/verify-context-api.js +20 -20
  268. package/skills/autosnippet-analysis/SKILL.md +10 -6
  269. package/skills/autosnippet-candidates/SKILL.md +27 -26
  270. package/skills/autosnippet-coldstart/SKILL.md +555 -38
  271. package/skills/autosnippet-concepts/SKILL.md +349 -337
  272. package/skills/autosnippet-create/SKILL.md +5 -5
  273. package/skills/autosnippet-reference-dart/SKILL.md +543 -0
  274. package/skills/autosnippet-reference-go/SKILL.md +539 -0
  275. package/skills/autosnippet-reference-java/SKILL.md +534 -0
  276. package/skills/autosnippet-reference-jsts/SKILL.md +41 -9
  277. package/skills/autosnippet-reference-kotlin/SKILL.md +526 -0
  278. package/skills/autosnippet-reference-objc/SKILL.md +29 -6
  279. package/skills/autosnippet-reference-python/SKILL.md +800 -0
  280. package/skills/autosnippet-reference-swift/SKILL.md +70 -14
  281. package/skills/autosnippet-structure/SKILL.md +4 -4
  282. package/templates/cursor-rules/autosnippet-conventions.mdc +2 -2
  283. package/templates/recipes-setup/README.md +2 -2
  284. package/templates/recipes-setup/_template.md +1 -1
  285. package/dashboard/dist/assets/index-Bun3ld_J.css +0 -1
  286. package/dashboard/dist/assets/index-_Sk_Dmg3.js +0 -143
  287. package/resources/asd-entry/main.swift +0 -159
  288. package/scripts/build-asd-entry.js +0 -51
  289. package/scripts/init-xcode-snippets.js +0 -311
  290. package/template.json +0 -39
@@ -1,7 +1,7 @@
1
1
  import { KnowledgeEntry } from '../../domain/knowledge/KnowledgeEntry.js';
2
- import { Lifecycle, inferKind } from '../../domain/knowledge/Lifecycle.js';
2
+ import { inferKind, Lifecycle } from '../../domain/knowledge/Lifecycle.js';
3
3
  import Logger from '../../infrastructure/logging/Logger.js';
4
- import { ValidationError, ConflictError, NotFoundError } from '../../shared/errors/index.js';
4
+ import { ConflictError, NotFoundError, ValidationError } from '../../shared/errors/index.js';
5
5
 
6
6
  /**
7
7
  * KnowledgeService — 统一知识服务
@@ -26,15 +26,15 @@ export class KnowledgeService {
26
26
  * @param {import('../quality/QualityScorer.js').QualityScorer} [options.qualityScorer]
27
27
  */
28
28
  constructor(repository, auditLogger, gateway, knowledgeGraphService, options = {}) {
29
- this.repository = repository;
30
- this.auditLogger = auditLogger;
31
- this.gateway = gateway;
29
+ this.repository = repository;
30
+ this.auditLogger = auditLogger;
31
+ this.gateway = gateway;
32
32
  this._knowledgeGraphService = knowledgeGraphService || null;
33
- this._fileWriter = options.fileWriter || null;
34
- this._skillHooks = options.skillHooks || null;
35
- this._confidenceRouter = options.confidenceRouter || null;
36
- this._qualityScorer = options.qualityScorer || null;
37
- this.logger = Logger.getInstance();
33
+ this._fileWriter = options.fileWriter || null;
34
+ this._skillHooks = options.skillHooks || null;
35
+ this._confidenceRouter = options.confidenceRouter || null;
36
+ this._qualityScorer = options.qualityScorer || null;
37
+ this.logger = Logger.getInstance();
38
38
  }
39
39
 
40
40
  /* ═══ CRUD ══════════════════════════════════════════════ */
@@ -56,9 +56,9 @@ export class KnowledgeService {
56
56
 
57
57
  const entry = KnowledgeEntry.fromJSON({
58
58
  ...data,
59
- lifecycle: Lifecycle.PENDING,
60
- source: data.source || 'manual',
61
- createdBy: context.userId,
59
+ lifecycle: Lifecycle.PENDING,
60
+ source: data.source || 'manual',
61
+ createdBy: context.userId,
62
62
  });
63
63
 
64
64
  if (!entry.isValid()) {
@@ -90,7 +90,7 @@ export class KnowledgeService {
90
90
  this._syncRelationsToGraph(saved.id, saved.relations);
91
91
 
92
92
  // 自动发现同域条目建立 related 边(best effort, 不阻塞)
93
- this._autoDiscoverRelations(saved.id, saved).catch(err =>
93
+ this._autoDiscoverRelations(saved.id, saved).catch((err) =>
94
94
  this.logger.warn('_autoDiscoverRelations error', { id: saved.id, error: err.message })
95
95
  );
96
96
 
@@ -113,9 +113,13 @@ export class KnowledgeService {
113
113
 
114
114
  // ── SkillHooks: onKnowledgeCreated (fire-and-forget) ──
115
115
  if (this._skillHooks) {
116
- this._skillHooks.run('onKnowledgeCreated', saved, {
117
- userId: context.userId,
118
- }).catch(err => this.logger.warn('SkillHook onKnowledgeCreated error', { error: err.message }));
116
+ this._skillHooks
117
+ .run('onKnowledgeCreated', saved, {
118
+ userId: context.userId,
119
+ })
120
+ .catch((err) =>
121
+ this.logger.warn('SkillHook onKnowledgeCreated error', { error: err.message })
122
+ );
119
123
  }
120
124
 
121
125
  return saved;
@@ -150,22 +154,43 @@ export class KnowledgeService {
150
154
  */
151
155
  async update(id, data, context) {
152
156
  try {
153
- const entry = await this._findOrThrow(id);
157
+ const _entry = await this._findOrThrow(id);
154
158
 
155
159
  const UPDATABLE = [
156
- 'title', 'description', 'trigger', 'language', 'category',
157
- 'knowledgeType', 'complexity', 'scope', 'difficulty',
158
- 'content', 'relations', 'constraints', 'reasoning',
159
- 'tags', 'headers', 'headerPaths', 'moduleName', 'includeHeaders',
160
- 'agentNotes', 'aiInsight',
160
+ 'title',
161
+ 'description',
162
+ 'trigger',
163
+ 'language',
164
+ 'category',
165
+ 'knowledgeType',
166
+ 'complexity',
167
+ 'scope',
168
+ 'difficulty',
169
+ 'content',
170
+ 'relations',
171
+ 'constraints',
172
+ 'reasoning',
173
+ 'tags',
174
+ 'headers',
175
+ 'headerPaths',
176
+ 'moduleName',
177
+ 'includeHeaders',
178
+ 'agentNotes',
179
+ 'aiInsight',
161
180
  // Cursor 交付字段
162
- 'topicHint', 'whenClause', 'doClause', 'dontClause', 'coreCode',
181
+ 'topicHint',
182
+ 'whenClause',
183
+ 'doClause',
184
+ 'dontClause',
185
+ 'coreCode',
163
186
  ];
164
187
 
165
188
  const dbUpdates = {};
166
189
 
167
190
  for (const key of UPDATABLE) {
168
- if (data[key] === undefined) continue;
191
+ if (data[key] === undefined) {
192
+ continue;
193
+ }
169
194
 
170
195
  switch (key) {
171
196
  // 标量字段直传
@@ -232,13 +257,16 @@ export class KnowledgeService {
232
257
  });
233
258
 
234
259
  this.logger.info('Knowledge entry updated', {
235
- id, updatedBy: context.userId, fields: Object.keys(dbUpdates),
260
+ id,
261
+ updatedBy: context.userId,
262
+ fields: Object.keys(dbUpdates),
236
263
  });
237
264
 
238
265
  return updated;
239
266
  } catch (error) {
240
267
  this.logger.error('Error updating knowledge entry', {
241
- id, error: error.message,
268
+ id,
269
+ error: error.message,
242
270
  });
243
271
  throw error;
244
272
  }
@@ -267,13 +295,16 @@ export class KnowledgeService {
267
295
  });
268
296
 
269
297
  this.logger.info('Knowledge entry deleted', {
270
- id, deletedBy: context.userId, title: entry.title,
298
+ id,
299
+ deletedBy: context.userId,
300
+ title: entry.title,
271
301
  });
272
302
 
273
303
  return { success: true, id };
274
304
  } catch (error) {
275
305
  this.logger.error('Error deleting knowledge entry', {
276
- id, error: error.message,
306
+ id,
307
+ error: error.message,
277
308
  });
278
309
  throw error;
279
310
  }
@@ -305,7 +336,9 @@ export class KnowledgeService {
305
336
  const container = getServiceContainer();
306
337
  if (container.services.cursorDeliveryPipeline) {
307
338
  const pipeline = container.get('cursorDeliveryPipeline');
308
- pipeline.deliver().catch(() => { /* ignore */ });
339
+ pipeline.deliver().catch(() => {
340
+ /* ignore */
341
+ });
309
342
  }
310
343
  })
311
344
  .catch(() => {
@@ -335,22 +368,34 @@ export class KnowledgeService {
335
368
  // ── 向后兼容别名 ──
336
369
 
337
370
  /** @deprecated 简化后所有条目直接进 pending */
338
- async submit(id, context) { return this.get(id); }
371
+ async submit(id, context) {
372
+ return this.get(id);
373
+ }
339
374
 
340
375
  /** @deprecated 简化后 approve = publish */
341
- async approve(id, context) { return this.publish(id, context); }
376
+ async approve(id, context) {
377
+ return this.publish(id, context);
378
+ }
342
379
 
343
380
  /** @deprecated 简化后无需 autoApprove */
344
- async autoApprove(id, context) { return this.get(id); }
381
+ async autoApprove(id, context) {
382
+ return this.get(id);
383
+ }
345
384
 
346
385
  /** @deprecated 简化后 reject = deprecate */
347
- async reject(id, reason, context) { return this.deprecate(id, reason, context); }
386
+ async reject(id, reason, context) {
387
+ return this.deprecate(id, reason, context);
388
+ }
348
389
 
349
390
  /** @deprecated 简化后 toDraft = reactivate */
350
- async toDraft(id, context) { return this.reactivate(id, context); }
391
+ async toDraft(id, context) {
392
+ return this.reactivate(id, context);
393
+ }
351
394
 
352
395
  /** @deprecated 简化后 fastTrack = publish */
353
- async fastTrack(id, context) { return this.publish(id, context); }
396
+ async fastTrack(id, context) {
397
+ return this.publish(id, context);
398
+ }
354
399
 
355
400
  /* ═══ 查询 ══════════════════════════════════════════════ */
356
401
 
@@ -365,19 +410,36 @@ export class KnowledgeService {
365
410
  const { page = 1, pageSize = 20 } = pagination;
366
411
 
367
412
  const dbFilters = {};
368
- if (lifecycle) dbFilters.lifecycle = lifecycle;
369
- if (kind) dbFilters.kind = kind;
370
- if (language) dbFilters.language = language;
371
- if (category) dbFilters.category = category;
372
- if (knowledgeType) dbFilters.knowledgeType = knowledgeType;
373
- if (source) dbFilters.source = source;
374
- if (scope) dbFilters.scope = scope;
375
- if (tag) dbFilters._tagLike = tag;
413
+ if (lifecycle) {
414
+ dbFilters.lifecycle = lifecycle;
415
+ }
416
+ if (kind) {
417
+ dbFilters.kind = kind;
418
+ }
419
+ if (language) {
420
+ dbFilters.language = language;
421
+ }
422
+ if (category) {
423
+ dbFilters.category = category;
424
+ }
425
+ if (knowledgeType) {
426
+ dbFilters.knowledgeType = knowledgeType;
427
+ }
428
+ if (source) {
429
+ dbFilters.source = source;
430
+ }
431
+ if (scope) {
432
+ dbFilters.scope = scope;
433
+ }
434
+ if (tag) {
435
+ dbFilters._tagLike = tag;
436
+ }
376
437
 
377
438
  return this.repository.findWithPagination(dbFilters, { page, pageSize });
378
439
  } catch (error) {
379
440
  this.logger.error('Error listing knowledge entries', {
380
- error: error.message, filters,
441
+ error: error.message,
442
+ filters,
381
443
  });
382
444
  throw error;
383
445
  }
@@ -405,7 +467,8 @@ export class KnowledgeService {
405
467
  return this.repository.search(keyword, { page, pageSize });
406
468
  } catch (error) {
407
469
  this.logger.error('Error searching knowledge', {
408
- keyword, error: error.message,
470
+ keyword,
471
+ error: error.message,
409
472
  });
410
473
  throw error;
411
474
  }
@@ -453,7 +516,8 @@ export class KnowledgeService {
453
516
  return entry;
454
517
  } catch (error) {
455
518
  this.logger.error(`Error incrementing knowledge ${type}`, {
456
- id, error: error.message,
519
+ id,
520
+ error: error.message,
457
521
  });
458
522
  throw error;
459
523
  }
@@ -479,11 +543,11 @@ export class KnowledgeService {
479
543
  // 更新 Quality 值对象
480
544
  await this.repository.update(id, {
481
545
  quality: JSON.stringify({
482
- completeness: result.dimensions.completeness,
483
- adaptation: result.dimensions.metadata,
546
+ completeness: result.dimensions.completeness,
547
+ adaptation: result.dimensions.metadata,
484
548
  documentation: result.dimensions.format,
485
- overall: result.score,
486
- grade: result.grade,
549
+ overall: result.score,
550
+ grade: result.grade,
487
551
  }),
488
552
  updatedAt: Math.floor(Date.now() / 1000),
489
553
  });
@@ -496,13 +560,16 @@ export class KnowledgeService {
496
560
  }
497
561
 
498
562
  this.logger.info('Knowledge quality updated', {
499
- id, score: result.score, grade: result.grade,
563
+ id,
564
+ score: result.score,
565
+ grade: result.grade,
500
566
  });
501
567
 
502
568
  return result;
503
569
  } catch (error) {
504
570
  this.logger.error('Error updating knowledge quality', {
505
- id, error: error.message,
571
+ id,
572
+ error: error.message,
506
573
  });
507
574
  throw error;
508
575
  }
@@ -522,30 +589,39 @@ export class KnowledgeService {
522
589
  const result = entry[method](...entityArgs);
523
590
 
524
591
  if (!result.success) {
525
- throw new ConflictError(
526
- result.error,
527
- `Lifecycle ${method} failed for ${id}`,
528
- );
592
+ throw new ConflictError(result.error, `Lifecycle ${method} failed for ${id}`);
529
593
  }
530
594
 
531
595
  // 构建 DB 更新
532
- // 注意: 不在此处 JSON.stringify — repository.update() 内部
596
+ // 注意: 不在此处 JSON.stringify — repository.update() 内部
533
597
  // 通过 _entityToRow() 统一执行序列化, 传入原始值即可
534
598
  const dbUpdates = {
535
- lifecycle: entry.lifecycle,
536
- lifecycleHistory: entry.lifecycleHistory,
537
- updatedAt: entry.updatedAt,
599
+ lifecycle: entry.lifecycle,
600
+ lifecycleHistory: entry.lifecycleHistory,
601
+ updatedAt: entry.updatedAt,
538
602
  };
539
603
 
540
604
  // 审核字段
541
- if (entry.reviewedBy) dbUpdates.reviewedBy = entry.reviewedBy;
542
- if (entry.reviewedAt) dbUpdates.reviewedAt = entry.reviewedAt;
543
- if (entry.rejectionReason !== null) dbUpdates.rejectionReason = entry.rejectionReason;
605
+ if (entry.reviewedBy) {
606
+ dbUpdates.reviewedBy = entry.reviewedBy;
607
+ }
608
+ if (entry.reviewedAt) {
609
+ dbUpdates.reviewedAt = entry.reviewedAt;
610
+ }
611
+ if (entry.rejectionReason !== null) {
612
+ dbUpdates.rejectionReason = entry.rejectionReason;
613
+ }
544
614
 
545
615
  // 发布字段
546
- if (entry.publishedAt) dbUpdates.publishedAt = entry.publishedAt;
547
- if (entry.publishedBy) dbUpdates.publishedBy = entry.publishedBy;
548
- if (entry.autoApprovable !== undefined) dbUpdates.autoApprovable = entry.autoApprovable ? 1 : 0;
616
+ if (entry.publishedAt) {
617
+ dbUpdates.publishedAt = entry.publishedAt;
618
+ }
619
+ if (entry.publishedBy) {
620
+ dbUpdates.publishedBy = entry.publishedBy;
621
+ }
622
+ if (entry.autoApprovable !== undefined) {
623
+ dbUpdates.autoApprovable = entry.autoApprovable ? 1 : 0;
624
+ }
549
625
 
550
626
  const updated = await this.repository.update(id, dbUpdates);
551
627
 
@@ -555,7 +631,8 @@ export class KnowledgeService {
555
631
  this._fileWriter.moveOnLifecycleChange(updated);
556
632
  } catch (err) {
557
633
  this.logger.warn('moveOnLifecycleChange failed (non-blocking)', {
558
- id, error: err.message,
634
+ id,
635
+ error: err.message,
559
636
  });
560
637
  }
561
638
  }
@@ -566,14 +643,17 @@ export class KnowledgeService {
566
643
  });
567
644
 
568
645
  this.logger.info(`Knowledge entry ${method}`, {
569
- id, from: prevLifecycle, to: entry.lifecycle,
646
+ id,
647
+ from: prevLifecycle,
648
+ to: entry.lifecycle,
570
649
  actor: context.userId,
571
650
  });
572
651
 
573
652
  return updated;
574
653
  } catch (error) {
575
654
  this.logger.error(`Error in lifecycle ${method}`, {
576
- id, error: error.message,
655
+ id,
656
+ error: error.message,
577
657
  });
578
658
  throw error;
579
659
  }
@@ -611,15 +691,15 @@ export class KnowledgeService {
611
691
  */
612
692
  _adaptForScorer(entry) {
613
693
  return {
614
- title: entry.title,
615
- trigger: entry.trigger,
616
- code: entry.content?.pattern || entry.content?.markdown || '',
617
- language: entry.language,
618
- category: entry.category,
619
- summary: entry.description || '',
694
+ title: entry.title,
695
+ trigger: entry.trigger,
696
+ code: entry.content?.pattern || entry.content?.markdown || '',
697
+ language: entry.language,
698
+ category: entry.category,
699
+ summary: entry.description || '',
620
700
  usageGuide: entry.content?.markdown || entry.doClause || '',
621
- headers: entry.headers || [],
622
- tags: entry.tags || [],
701
+ headers: entry.headers || [],
702
+ tags: entry.tags || [],
623
703
  };
624
704
  }
625
705
 
@@ -632,30 +712,37 @@ export class KnowledgeService {
632
712
  */
633
713
  async _autoDiscoverRelations(id, entry) {
634
714
  const gs = this._knowledgeGraphService;
635
- if (!gs) return;
715
+ if (!gs) {
716
+ return;
717
+ }
636
718
 
637
719
  try {
638
720
  const candidates = [];
639
721
 
640
- // moduleName 查同模块条目
722
+ // 仅与已发布 Recipe(active)建立关联,不与其他候选(pending)互关联
723
+ const activeOnly = { lifecycle: Lifecycle.ACTIVE };
724
+
725
+ // 按 moduleName 查同模块已发布条目
641
726
  if (entry.moduleName) {
642
727
  const sameModule = await this.repository.findWithPagination(
643
- { moduleName: entry.moduleName },
644
- { page: 1, pageSize: 20 },
728
+ { ...activeOnly, moduleName: entry.moduleName },
729
+ { page: 1, pageSize: 20 }
645
730
  );
646
731
  for (const r of sameModule.data) {
647
- if (r.id !== id) candidates.push({ target: r.id, relation: 'related', weight: 0.8 });
732
+ if (r.id !== id) {
733
+ candidates.push({ target: r.id, relation: 'related', weight: 0.8 });
734
+ }
648
735
  }
649
736
  }
650
737
 
651
- // 按 category 查同类条目(弱关联)
738
+ // 按 category 查同类已发布条目(弱关联)
652
739
  if (entry.category && candidates.length < 10) {
653
740
  const sameCat = await this.repository.findWithPagination(
654
- { category: entry.category },
655
- { page: 1, pageSize: 10 },
741
+ { ...activeOnly, category: entry.category },
742
+ { page: 1, pageSize: 10 }
656
743
  );
657
744
  for (const r of sameCat.data) {
658
- if (r.id !== id && !candidates.some(c => c.target === r.id)) {
745
+ if (r.id !== id && !candidates.some((c) => c.target === r.id)) {
659
746
  candidates.push({ target: r.id, relation: 'related', weight: 0.4 });
660
747
  }
661
748
  }
@@ -665,19 +752,25 @@ export class KnowledgeService {
665
752
  for (const c of candidates.slice(0, 10)) {
666
753
  try {
667
754
  gs.addEdge(id, 'knowledge', c.target, 'knowledge', c.relation, { weight: c.weight });
668
- } catch { /* ignore duplicates */ }
755
+ } catch {
756
+ /* ignore duplicates */
757
+ }
669
758
  }
670
759
 
671
760
  // 将发现的关系写回 entry 的 relations 字段
672
761
  if (candidates.length > 0) {
673
- const relatedItems = candidates.slice(0, 10).map(c => ({
762
+ const relatedItems = candidates.slice(0, 10).map((c) => ({
674
763
  target: c.target,
675
764
  description: 'auto-discovered',
676
765
  }));
677
- const existingRelations = typeof entry.relations?.toJSON === 'function'
678
- ? entry.relations.toJSON()
679
- : (entry.relations || {});
680
- const merged = { ...existingRelations, related: [...(existingRelations.related || []), ...relatedItems] };
766
+ const existingRelations =
767
+ typeof entry.relations?.toJSON === 'function'
768
+ ? entry.relations.toJSON()
769
+ : entry.relations || {};
770
+ const merged = {
771
+ ...existingRelations,
772
+ related: [...(existingRelations.related || []), ...relatedItems],
773
+ };
681
774
  await this.repository.update(id, {
682
775
  relations: JSON.stringify(merged),
683
776
  updatedAt: Math.floor(Date.now() / 1000),
@@ -685,7 +778,8 @@ export class KnowledgeService {
685
778
  }
686
779
  } catch (err) {
687
780
  this.logger.warn('Auto-discover relations failed (non-blocking)', {
688
- id, error: err.message,
781
+ id,
782
+ error: err.message,
689
783
  });
690
784
  }
691
785
  }
@@ -695,20 +789,26 @@ export class KnowledgeService {
695
789
  */
696
790
  _syncRelationsToGraph(id, relations) {
697
791
  const gs = this._knowledgeGraphService;
698
- if (!gs) return;
792
+ if (!gs) {
793
+ return;
794
+ }
699
795
 
700
796
  try {
701
- gs.db.prepare(
702
- `DELETE FROM knowledge_edges WHERE from_id = ? AND from_type = 'knowledge'`
703
- ).run(id);
797
+ gs.db
798
+ .prepare(`DELETE FROM knowledge_edges WHERE from_id = ? AND from_type = 'knowledge'`)
799
+ .run(id);
704
800
 
705
- if (!relations || typeof relations !== 'object') return;
801
+ if (!relations || typeof relations !== 'object') {
802
+ return;
803
+ }
706
804
 
707
805
  // Relations 可能是 Relations 值对象或普通对象
708
806
  const relObj = typeof relations.toJSON === 'function' ? relations.toJSON() : relations;
709
807
 
710
808
  for (const [relType, targets] of Object.entries(relObj)) {
711
- if (!Array.isArray(targets)) continue;
809
+ if (!Array.isArray(targets)) {
810
+ continue;
811
+ }
712
812
  for (const t of targets) {
713
813
  const targetId = t.target || t.id || (typeof t === 'string' ? t : null);
714
814
  if (targetId) {
@@ -720,7 +820,8 @@ export class KnowledgeService {
720
820
  }
721
821
  } catch (err) {
722
822
  this.logger.warn('Failed to sync relations to knowledge_edges', {
723
- id, error: err.message,
823
+ id,
824
+ error: err.message,
724
825
  });
725
826
  }
726
827
  }
@@ -730,12 +831,12 @@ export class KnowledgeService {
730
831
  */
731
832
  _removeAllEdges(id) {
732
833
  const gs = this._knowledgeGraphService;
733
- if (!gs) return;
834
+ if (!gs) {
835
+ return;
836
+ }
734
837
 
735
838
  try {
736
- gs.db.prepare(
737
- `DELETE FROM knowledge_edges WHERE from_id = ? OR to_id = ?`
738
- ).run(id, id);
839
+ gs.db.prepare(`DELETE FROM knowledge_edges WHERE from_id = ? OR to_id = ?`).run(id, id);
739
840
  } catch (err) {
740
841
  this.logger.warn('Failed to remove edges', { id, error: err.message });
741
842
  }
@@ -747,20 +848,24 @@ export class KnowledgeService {
747
848
  * 落盘到 .md 文件 + 回写 sourceFile
748
849
  */
749
850
  _persistToFile(entry) {
750
- if (!this._fileWriter) return;
851
+ if (!this._fileWriter) {
852
+ return;
853
+ }
751
854
  try {
752
855
  const oldSourceFile = entry.sourceFile;
753
856
  this._fileWriter.persist(entry);
754
857
  if (entry.sourceFile && entry.sourceFile !== oldSourceFile) {
755
- this.repository.update(entry.id, { sourceFile: entry.sourceFile }).catch(err => {
858
+ this.repository.update(entry.id, { sourceFile: entry.sourceFile }).catch((err) => {
756
859
  this.logger.warn('Failed to update sourceFile in DB', {
757
- id: entry.id, error: err.message,
860
+ id: entry.id,
861
+ error: err.message,
758
862
  });
759
863
  });
760
864
  }
761
865
  } catch (err) {
762
866
  this.logger.warn('Knowledge file persist failed (non-blocking)', {
763
- id: entry?.id, error: err.message,
867
+ id: entry?.id,
868
+ error: err.message,
764
869
  });
765
870
  }
766
871
  }
@@ -769,12 +874,15 @@ export class KnowledgeService {
769
874
  * 删除 .md 文件
770
875
  */
771
876
  _removeFile(entry) {
772
- if (!this._fileWriter) return;
877
+ if (!this._fileWriter) {
878
+ return;
879
+ }
773
880
  try {
774
881
  this._fileWriter.remove(entry);
775
882
  } catch (err) {
776
883
  this.logger.warn('Knowledge file remove failed (non-blocking)', {
777
- id: entry?.id, error: err.message,
884
+ id: entry?.id,
885
+ error: err.message,
778
886
  });
779
887
  }
780
888
  }
@@ -795,7 +903,9 @@ export class KnowledgeService {
795
903
  });
796
904
  } catch (err) {
797
905
  this.logger.warn('Audit log failed (non-blocking)', {
798
- action, id, error: err.message,
906
+ action,
907
+ id,
908
+ error: err.message,
799
909
  });
800
910
  }
801
911
  }