autosnippet 3.0.1 → 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 +655 -260
  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
@@ -32,23 +32,23 @@ import { jaccardSimilarity, tokenizeForSimilarity } from '../../shared/similarit
32
32
  // ──────────────────────────────────────────────────────────────
33
33
 
34
34
  /** 检索打分权重 (借鉴 Generative Agents) */
35
- const WEIGHT_RECENCY = 0.2;
35
+ const WEIGHT_RECENCY = 0.2;
36
36
  const WEIGHT_IMPORTANCE = 0.3;
37
- const WEIGHT_RELEVANCE = 0.5;
37
+ const WEIGHT_RELEVANCE = 0.5;
38
38
 
39
39
  /** Recency 半衰期 (天) — 7 天未访问的记忆分数下降一半 */
40
40
  const RECENCY_HALF_LIFE_DAYS = 7;
41
41
 
42
42
  /** 自然遗忘阈值 */
43
- const ARCHIVE_DAYS = 30; // 30 天未访问 + importance < 3 → 归档
44
- const FORGET_DAYS = 90; // 90 天未访问 → 完全遗忘
43
+ const ARCHIVE_DAYS = 30; // 30 天未访问 + importance < 3 → 归档
44
+ const FORGET_DAYS = 90; // 90 天未访问 → 完全遗忘
45
45
 
46
46
  /** 最大记忆条数 (防止无限膨胀) */
47
- const MAX_MEMORIES = 500;
47
+ const MAX_MEMORIES = 500;
48
48
 
49
49
  /** 相似度阈值 */
50
- const SIMILARITY_UPDATE = 0.85; // ≥85% 同义 → UPDATE
51
- const SIMILARITY_MERGE = 0.60; // ≥60% 相关 → MERGE
50
+ const SIMILARITY_UPDATE = 0.85; // ≥85% 同义 → UPDATE
51
+ const SIMILARITY_MERGE = 0.6; // ≥60% 相关 → MERGE
52
52
 
53
53
  // ──────────────────────────────────────────────────────────────
54
54
  // ProjectSemanticMemory 类
@@ -70,7 +70,9 @@ export class ProjectSemanticMemory {
70
70
  * @param {object} [opts.logger] — Logger 实例
71
71
  */
72
72
  constructor(db, { logger } = {}) {
73
- if (!db) throw new Error('ProjectSemanticMemory requires a database instance');
73
+ if (!db) {
74
+ throw new Error('ProjectSemanticMemory requires a database instance');
75
+ }
74
76
  this.#db = typeof db?.getDb === 'function' ? db.getDb() : db;
75
77
  this.#logger = logger || null;
76
78
 
@@ -137,7 +139,9 @@ export class ProjectSemanticMemory {
137
139
  */
138
140
  update(id, updates) {
139
141
  const existing = this.#stmts.getById.get(id);
140
- if (!existing) return false;
142
+ if (!existing) {
143
+ return false;
144
+ }
141
145
 
142
146
  const now = new Date().toISOString();
143
147
  const fields = [];
@@ -168,7 +172,9 @@ export class ProjectSemanticMemory {
168
172
  params.tags = JSON.stringify(updates.tags);
169
173
  }
170
174
 
171
- if (fields.length === 0) return false;
175
+ if (fields.length === 0) {
176
+ return false;
177
+ }
172
178
 
173
179
  fields.push('updated_at = @updated_at');
174
180
  params.updated_at = now;
@@ -268,7 +274,9 @@ export class ProjectSemanticMemory {
268
274
 
269
275
  runConsolidate();
270
276
 
271
- this.#log(`Consolidation: +${stats.added} ADD, ~${stats.updated} UPDATE, ⊕${stats.merged} MERGE, =${stats.skipped} SKIP`);
277
+ this.#log(
278
+ `Consolidation: +${stats.added} ADD, ~${stats.updated} UPDATE, ⊕${stats.merged} MERGE, =${stats.skipped} SKIP`
279
+ );
272
280
 
273
281
  // 容量控制
274
282
  this.#enforceCapacity();
@@ -293,19 +301,21 @@ export class ProjectSemanticMemory {
293
301
  */
294
302
  retrieve(query, { limit = 10, source, type } = {}) {
295
303
  const all = this.#getAllActive({ source, type });
296
- if (all.length === 0) return [];
304
+ if (all.length === 0) {
305
+ return [];
306
+ }
297
307
 
298
308
  const now = Date.now();
299
309
  const lowerQuery = (query || '').toLowerCase();
300
310
  const queryTokens = this.#tokenizeWords(lowerQuery);
301
311
 
302
- const scored = all.map(m => {
312
+ const scored = all.map((m) => {
303
313
  // Recency: 指数衰减 (半衰期 7 天)
304
314
  const lastAccess = m.last_accessed_at
305
315
  ? new Date(m.last_accessed_at).getTime()
306
316
  : new Date(m.updated_at).getTime();
307
317
  const daysSinceAccess = (now - lastAccess) / 86400_000;
308
- const recency = Math.exp(-daysSinceAccess * Math.LN2 / RECENCY_HALF_LIFE_DAYS);
318
+ const recency = Math.exp((-daysSinceAccess * Math.LN2) / RECENCY_HALF_LIFE_DAYS);
309
319
 
310
320
  // Importance: 归一化到 0-1
311
321
  const importance = (m.importance || 5) / 10;
@@ -313,9 +323,8 @@ export class ProjectSemanticMemory {
313
323
  // Relevance: token overlap + 子串匹配
314
324
  const relevance = this.#computeRelevance(lowerQuery, queryTokens, m.content);
315
325
 
316
- const score = WEIGHT_RECENCY * recency
317
- + WEIGHT_IMPORTANCE * importance
318
- + WEIGHT_RELEVANCE * relevance;
326
+ const score =
327
+ WEIGHT_RECENCY * recency + WEIGHT_IMPORTANCE * importance + WEIGHT_RELEVANCE * relevance;
319
328
 
320
329
  return {
321
330
  ...this.#deserialize(m),
@@ -347,7 +356,7 @@ export class ProjectSemanticMemory {
347
356
  */
348
357
  search(content, { limit = 5 } = {}) {
349
358
  const results = this.#findSimilar(content, null, limit);
350
- return results.map(r => this.#deserialize(r));
359
+ return results.map((r) => this.#deserialize(r));
351
360
  }
352
361
 
353
362
  // ─── Prompt 生成 (兼容 Memory.js) ──────────────────────
@@ -381,12 +390,14 @@ export class ProjectSemanticMemory {
381
390
  return scoreB - scoreA;
382
391
  })
383
392
  .slice(0, limit)
384
- .map(m => this.#deserialize(m));
393
+ .map((m) => this.#deserialize(m));
385
394
  }
386
395
 
387
- if (memories.length === 0) return '';
396
+ if (memories.length === 0) {
397
+ return '';
398
+ }
388
399
 
389
- const lines = memories.map(m => {
400
+ const lines = memories.map((m) => {
390
401
  const badge = m.importance >= 8 ? '⚠️' : m.importance >= 5 ? '📌' : '💡';
391
402
  return `- ${badge} [${m.type}] ${m.content}`;
392
403
  });
@@ -412,7 +423,7 @@ export class ProjectSemanticMemory {
412
423
  return tB - tA;
413
424
  })
414
425
  .slice(0, limit);
415
- return rows.map(r => ({
426
+ return rows.map((r) => ({
416
427
  ts: r.updated_at,
417
428
  type: r.type,
418
429
  content: r.content,
@@ -432,7 +443,9 @@ export class ProjectSemanticMemory {
432
443
  */
433
444
  append(entry) {
434
445
  const content = (entry.content || '').trim().substring(0, 500);
435
- if (!content) return;
446
+ if (!content) {
447
+ return;
448
+ }
436
449
 
437
450
  // 去重: 检查是否已有高相似度记忆
438
451
  const similar = this.#findSimilar(content, entry.type, 1);
@@ -459,13 +472,13 @@ export class ProjectSemanticMemory {
459
472
  */
460
473
  size({ source } = {}) {
461
474
  if (source) {
462
- return this.#db.prepare(
463
- 'SELECT COUNT(*) as cnt FROM semantic_memories WHERE source = ?'
464
- ).get(source)?.cnt || 0;
475
+ return (
476
+ this.#db
477
+ .prepare('SELECT COUNT(*) as cnt FROM semantic_memories WHERE source = ?')
478
+ .get(source)?.cnt || 0
479
+ );
465
480
  }
466
- return this.#db.prepare(
467
- 'SELECT COUNT(*) as cnt FROM semantic_memories'
468
- ).get()?.cnt || 0;
481
+ return this.#db.prepare('SELECT COUNT(*) as cnt FROM semantic_memories').get()?.cnt || 0;
469
482
  }
470
483
 
471
484
  // ─── 维护: 过期清理 + 容量控制 ────────────────────────
@@ -484,31 +497,36 @@ export class ProjectSemanticMemory {
484
497
 
485
498
  const runCompact = this.#db.transaction(() => {
486
499
  // 1. 删除 TTL 过期
487
- const expiredResult = this.#db.prepare(
488
- 'DELETE FROM semantic_memories WHERE expires_at IS NOT NULL AND expires_at < ?'
489
- ).run(now);
500
+ const expiredResult = this.#db
501
+ .prepare('DELETE FROM semantic_memories WHERE expires_at IS NOT NULL AND expires_at < ?')
502
+ .run(now);
490
503
  stats.expired = expiredResult.changes;
491
504
 
492
505
  // 2. 完全遗忘: 90 天未访问
493
506
  const forgetThreshold = new Date(nowMs - FORGET_DAYS * 86400_000).toISOString();
494
- const forgottenResult = this.#db.prepare(
495
- 'DELETE FROM semantic_memories WHERE last_accessed_at < ? AND importance < 7'
496
- ).run(forgetThreshold);
507
+ const forgottenResult = this.#db
508
+ .prepare('DELETE FROM semantic_memories WHERE last_accessed_at < ? AND importance < 7')
509
+ .run(forgetThreshold);
497
510
  stats.forgotten = forgottenResult.changes;
498
511
 
499
512
  // 3. 归档: 30 天未访问 + 低重要性 → 降低 importance
500
513
  const archiveThreshold = new Date(nowMs - ARCHIVE_DAYS * 86400_000).toISOString();
501
- const archiveResult = this.#db.prepare(
502
- 'UPDATE semantic_memories SET importance = MAX(1, importance - 1) WHERE last_accessed_at < ? AND importance < 3'
503
- ).run(archiveThreshold);
514
+ const archiveResult = this.#db
515
+ .prepare(
516
+ 'UPDATE semantic_memories SET importance = MAX(1, importance - 1) WHERE last_accessed_at < ? AND importance < 3'
517
+ )
518
+ .run(archiveThreshold);
504
519
  stats.archived = archiveResult.changes;
505
520
 
506
- stats.remaining = this.#db.prepare('SELECT COUNT(*) as cnt FROM semantic_memories').get()?.cnt || 0;
521
+ stats.remaining =
522
+ this.#db.prepare('SELECT COUNT(*) as cnt FROM semantic_memories').get()?.cnt || 0;
507
523
  });
508
524
 
509
525
  runCompact();
510
526
 
511
- this.#log(`Compact: ${stats.expired} expired, ${stats.forgotten} forgotten, ${stats.archived} archived, ${stats.remaining} remaining`);
527
+ this.#log(
528
+ `Compact: ${stats.expired} expired, ${stats.forgotten} forgotten, ${stats.archived} archived, ${stats.remaining} remaining`
529
+ );
512
530
  return stats;
513
531
  }
514
532
 
@@ -520,20 +538,19 @@ export class ProjectSemanticMemory {
520
538
  */
521
539
  getStats() {
522
540
  const total = this.#db.prepare('SELECT COUNT(*) as cnt FROM semantic_memories').get()?.cnt || 0;
523
- const byType = this.#db.prepare(
524
- 'SELECT type, COUNT(*) as cnt FROM semantic_memories GROUP BY type'
525
- ).all();
526
- const bySource = this.#db.prepare(
527
- 'SELECT source, COUNT(*) as cnt FROM semantic_memories GROUP BY source'
528
- ).all();
529
- const avgImportance = this.#db.prepare(
530
- 'SELECT AVG(importance) as avg FROM semantic_memories'
531
- ).get()?.avg || 0;
541
+ const byType = this.#db
542
+ .prepare('SELECT type, COUNT(*) as cnt FROM semantic_memories GROUP BY type')
543
+ .all();
544
+ const bySource = this.#db
545
+ .prepare('SELECT source, COUNT(*) as cnt FROM semantic_memories GROUP BY source')
546
+ .all();
547
+ const avgImportance =
548
+ this.#db.prepare('SELECT AVG(importance) as avg FROM semantic_memories').get()?.avg || 0;
532
549
 
533
550
  return {
534
551
  total,
535
- byType: Object.fromEntries(byType.map(r => [r.type, r.cnt])),
536
- bySource: Object.fromEntries(bySource.map(r => [r.source, r.cnt])),
552
+ byType: Object.fromEntries(byType.map((r) => [r.type, r.cnt])),
553
+ bySource: Object.fromEntries(bySource.map((r) => [r.source, r.cnt])),
537
554
  avgImportance: Math.round(avgImportance * 10) / 10,
538
555
  };
539
556
  }
@@ -543,9 +560,9 @@ export class ProjectSemanticMemory {
543
560
  * @returns {number} 删除数量
544
561
  */
545
562
  clearBootstrapMemories() {
546
- const result = this.#db.prepare(
547
- "DELETE FROM semantic_memories WHERE source = 'bootstrap'"
548
- ).run();
563
+ const result = this.#db
564
+ .prepare("DELETE FROM semantic_memories WHERE source = 'bootstrap'")
565
+ .run();
549
566
  this.#log(`Cleared ${result.changes} bootstrap memories`);
550
567
  return result.changes;
551
568
  }
@@ -556,9 +573,9 @@ export class ProjectSemanticMemory {
556
573
  * 确保表存在 (用于 migration 未运行的情况)
557
574
  */
558
575
  #ensureTable() {
559
- const exists = this.#db.prepare(
560
- "SELECT name FROM sqlite_master WHERE type='table' AND name='semantic_memories'"
561
- ).get();
576
+ const exists = this.#db
577
+ .prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='semantic_memories'")
578
+ .get();
562
579
 
563
580
  if (!exists) {
564
581
  this.#db.exec(`
@@ -602,13 +619,9 @@ export class ProjectSemanticMemory {
602
619
  @source_dimension, @source_evidence, @bootstrap_session, @tags)
603
620
  `),
604
621
 
605
- getById: this.#db.prepare(
606
- 'SELECT * FROM semantic_memories WHERE id = ?'
607
- ),
622
+ getById: this.#db.prepare('SELECT * FROM semantic_memories WHERE id = ?'),
608
623
 
609
- deleteById: this.#db.prepare(
610
- 'DELETE FROM semantic_memories WHERE id = ?'
611
- ),
624
+ deleteById: this.#db.prepare('DELETE FROM semantic_memories WHERE id = ?'),
612
625
 
613
626
  touchAccess: this.#db.prepare(`
614
627
  UPDATE semantic_memories
@@ -685,7 +698,9 @@ export class ProjectSemanticMemory {
685
698
  #touchAccess(id) {
686
699
  try {
687
700
  this.#stmts.touchAccess.run({ id, now: new Date().toISOString() });
688
- } catch { /* non-critical */ }
701
+ } catch {
702
+ /* non-critical */
703
+ }
689
704
  }
690
705
 
691
706
  /**
@@ -706,11 +721,11 @@ export class ProjectSemanticMemory {
706
721
  const contentTokens = tokenizeForSimilarity(lowerContent);
707
722
 
708
723
  const scored = candidates
709
- .map(row => {
724
+ .map((row) => {
710
725
  const similarity = this.#computeSimilarity(contentTokens, lowerContent, row.content);
711
726
  return { ...row, similarity, related_memories_raw: row.related_memories };
712
727
  })
713
- .filter(r => r.similarity > 0.1)
728
+ .filter((r) => r.similarity > 0.1)
714
729
  .sort((a, b) => b.similarity - a.similarity);
715
730
 
716
731
  return scored.slice(0, limit);
@@ -728,13 +743,17 @@ export class ProjectSemanticMemory {
728
743
  const lowerB = (contentB || '').toLowerCase();
729
744
  const tokensB = tokenizeForSimilarity(lowerB);
730
745
 
731
- if (tokensA.size === 0 && tokensB.size === 0) return 1.0;
732
- if (tokensA.size === 0 || tokensB.size === 0) return 0.0;
746
+ if (tokensA.size === 0 && tokensB.size === 0) {
747
+ return 1.0;
748
+ }
749
+ if (tokensA.size === 0 || tokensB.size === 0) {
750
+ return 0.0;
751
+ }
733
752
 
734
753
  const jaccard = jaccardSimilarity(tokensA, tokensB);
735
754
 
736
755
  // 子串包含加分
737
- const containsBonus = (lowerA.includes(lowerB) || lowerB.includes(lowerA)) ? 0.3 : 0;
756
+ const containsBonus = lowerA.includes(lowerB) || lowerB.includes(lowerA) ? 0.3 : 0;
738
757
 
739
758
  return Math.min(1.0, jaccard + containsBonus);
740
759
  }
@@ -748,17 +767,23 @@ export class ProjectSemanticMemory {
748
767
  * @returns {number} 0.0-1.0
749
768
  */
750
769
  #computeRelevance(lowerQuery, queryTokens, content) {
751
- if (!lowerQuery || !content) return 0;
770
+ if (!lowerQuery || !content) {
771
+ return 0;
772
+ }
752
773
 
753
774
  const lowerContent = content.toLowerCase();
754
775
  const contentTokens = this.#tokenizeWords(lowerContent);
755
776
 
756
- if (queryTokens.size === 0) return 0;
777
+ if (queryTokens.size === 0) {
778
+ return 0;
779
+ }
757
780
 
758
781
  // Token overlap
759
782
  let matchCount = 0;
760
783
  for (const t of queryTokens) {
761
- if (contentTokens.has(t)) matchCount++;
784
+ if (contentTokens.has(t)) {
785
+ matchCount++;
786
+ }
762
787
  }
763
788
  const tokenOverlap = matchCount / queryTokens.size;
764
789
 
@@ -783,12 +808,14 @@ export class ProjectSemanticMemory {
783
808
  * @returns {Set<string>}
784
809
  */
785
810
  #tokenizeWords(text) {
786
- if (!text) return new Set();
811
+ if (!text) {
812
+ return new Set();
813
+ }
787
814
  return new Set(
788
815
  text
789
816
  .split(/[\s,;:!?。,;:!?\-_/\\|()[\]{}'"<>]+/)
790
- .filter(t => t.length >= 2)
791
- .map(t => t.toLowerCase())
817
+ .filter((t) => t.length >= 2)
818
+ .map((t) => t.toLowerCase())
792
819
  );
793
820
  }
794
821
 
@@ -832,16 +859,20 @@ export class ProjectSemanticMemory {
832
859
  */
833
860
  #enforceCapacity() {
834
861
  const count = this.#db.prepare('SELECT COUNT(*) as cnt FROM semantic_memories').get()?.cnt || 0;
835
- if (count <= MAX_MEMORIES) return;
862
+ if (count <= MAX_MEMORIES) {
863
+ return;
864
+ }
836
865
 
837
866
  const excess = count - MAX_MEMORIES;
838
- this.#db.prepare(`
867
+ this.#db
868
+ .prepare(`
839
869
  DELETE FROM semantic_memories WHERE id IN (
840
870
  SELECT id FROM semantic_memories
841
871
  ORDER BY importance ASC, access_count ASC, updated_at ASC
842
872
  LIMIT ?
843
873
  )
844
- `).run(excess);
874
+ `)
875
+ .run(excess);
845
876
 
846
877
  this.#log(`Capacity enforced: removed ${excess} lowest-priority memories`);
847
878
  }