squish-memory 1.1.5 → 1.2.0

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 (499) hide show
  1. package/.env.example +32 -16
  2. package/CHANGELOG.md +147 -0
  3. package/README.md +120 -78
  4. package/{scripts → bin}/dependency-manager.mjs +217 -217
  5. package/{scripts → bin}/detect-clients.mjs +78 -78
  6. package/bin/install-interactive.mjs +321 -0
  7. package/bin/squish-mcp.mjs +46 -0
  8. package/bin/squish.mjs +33 -0
  9. package/config/mcp-migration-map.json +1 -6
  10. package/config/mcp-mode-semantics.json +19 -23
  11. package/config/mcp-remote-auth.json +3 -26
  12. package/config/mcp-universal.schema.json +5 -35
  13. package/config/settings.json +107 -52
  14. package/config.js +5 -0
  15. package/config.ts +218 -0
  16. package/core/adapters/config/claude-code.ts +133 -0
  17. package/core/adapters/config/cursor.ts +90 -0
  18. package/core/adapters/config/opencode.ts +89 -0
  19. package/core/adapters/config/windsurf.ts +90 -0
  20. package/core/adapters/index.ts +102 -0
  21. package/core/adapters/timeline.ts +116 -0
  22. package/core/adapters/types.ts +166 -0
  23. package/core/agent-preferences.ts +140 -0
  24. package/core/algorithms/analytics/token-estimator.ts +216 -0
  25. package/core/algorithms/detection/hash-filters.ts +260 -0
  26. package/core/algorithms/detection/semantic-ranker.ts +194 -0
  27. package/core/algorithms/detection/two-stage-detector.ts +421 -0
  28. package/core/algorithms/handlers/approve-merge.ts +215 -0
  29. package/core/algorithms/handlers/detect-duplicates.ts +192 -0
  30. package/core/algorithms/handlers/get-stats.ts +132 -0
  31. package/core/algorithms/handlers/list-proposals.ts +130 -0
  32. package/core/algorithms/handlers/preview-merge.ts +139 -0
  33. package/core/algorithms/handlers/reject-merge.ts +93 -0
  34. package/core/algorithms/handlers/reverse-merge.ts +155 -0
  35. package/core/algorithms/index.ts +39 -0
  36. package/core/algorithms/operations/cache-maintenance.ts +182 -0
  37. package/core/algorithms/safety/safety-checks.ts +256 -0
  38. package/core/algorithms/strategies/merge-strategies.ts +381 -0
  39. package/core/algorithms/types.ts +140 -0
  40. package/core/algorithms/utils/response-builder.ts +61 -0
  41. package/core/associations.ts +363 -0
  42. package/core/beliefs/decay.ts +289 -0
  43. package/core/beliefs/extractor.ts +131 -0
  44. package/core/beliefs/store.ts +557 -0
  45. package/core/beliefs/types.ts +38 -0
  46. package/core/commands/mcp-server.ts +5 -0
  47. package/core/compression.ts +177 -0
  48. package/core/config.js +2 -0
  49. package/core/consolidation.ts +330 -0
  50. package/core/context/agent-context.ts +388 -0
  51. package/core/context/context-paging.ts +449 -0
  52. package/core/context/context-window.ts +234 -0
  53. package/core/context/context.ts +35 -0
  54. package/core/embeddings/embeddings.ts +616 -0
  55. package/core/embeddings/google-multimodal.ts +200 -0
  56. package/{dist/core/local-embeddings.js → core/embeddings/local-embeddings.ts} +12 -11
  57. package/core/embeddings/qmd-client.ts +495 -0
  58. package/core/embeddings/transformers-local.ts +261 -0
  59. package/core/embeddings.js +4 -0
  60. package/core/error-handling.ts +206 -0
  61. package/core/external +219 -0
  62. package/core/graph/entity-deduplicator.ts +232 -0
  63. package/core/graph/graph-builder.ts +257 -0
  64. package/core/graph/graph-traversal.ts +490 -0
  65. package/core/graph/index.ts +24 -0
  66. package/core/graph/llm-entity-extractor.ts +402 -0
  67. package/core/graph/multi-hop-retrieval.ts +317 -0
  68. package/core/graph/relationship-extractor.ts +465 -0
  69. package/core/hooks/agent-hooks.ts +653 -0
  70. package/core/hooks/auto-tagger.ts +149 -0
  71. package/core/hooks/capture-filter.ts +169 -0
  72. package/core/hot-cache.ts +388 -0
  73. package/core/index.ts +10 -0
  74. package/core/ingestion/agent-memory.ts +167 -0
  75. package/core/ingestion/core-memory.ts +326 -0
  76. package/core/ingestion/learnings.ts +260 -0
  77. package/core/ingestion/signal-engine.ts +266 -0
  78. package/core/integrations/obsidian-vault.ts +197 -0
  79. package/core/layers/generator.ts +115 -0
  80. package/core/lib/db-client.ts +168 -0
  81. package/core/lib/parse-embedding.ts +59 -0
  82. package/core/lib/schemas.ts +102 -0
  83. package/core/lib/types.ts +49 -0
  84. package/core/lib/utils.ts +151 -0
  85. package/core/lib/validation.ts +180 -0
  86. package/core/lifecycle.ts +353 -0
  87. package/core/logger.ts +59 -0
  88. package/core/memory/bridge-discovery.ts +395 -0
  89. package/core/memory/categorizer.ts +390 -0
  90. package/core/memory/conflict-detector.ts +62 -0
  91. package/core/memory/consolidation.ts +372 -0
  92. package/core/memory/context-collector.ts +75 -0
  93. package/core/memory/contradiction-resolver.ts +494 -0
  94. package/core/memory/edit-workflow.ts +174 -0
  95. package/core/memory/entity-extractor.ts +426 -0
  96. package/core/memory/entity-resolver.ts +89 -0
  97. package/core/memory/explain.ts +112 -0
  98. package/core/memory/fact-deriver.ts +300 -0
  99. package/core/memory/fact-extractor.ts +120 -0
  100. package/core/memory/feedback-tracker.ts +200 -0
  101. package/core/memory/hooks.ts +230 -0
  102. package/core/memory/hybrid-retrieval.ts +65 -0
  103. package/core/memory/hybrid-scorer.ts +325 -0
  104. package/core/memory/hybrid-search.ts +748 -0
  105. package/core/memory/importance.ts +319 -0
  106. package/core/memory/index.ts +11 -0
  107. package/core/memory/loader.ts +178 -0
  108. package/core/memory/markdown/markdown-storage.ts +318 -0
  109. package/core/memory/memories.ts +565 -0
  110. package/core/memory/memory-lifecycle.ts +51 -0
  111. package/core/memory/memory-manager.ts +53 -0
  112. package/core/memory/migrate.ts +173 -0
  113. package/core/memory/normalization.ts +30 -0
  114. package/core/memory/path-strengthener.ts +211 -0
  115. package/core/memory/progressive-disclosure.ts +392 -0
  116. package/core/memory/query-processor.ts +130 -0
  117. package/core/memory/query-rewriter.ts +153 -0
  118. package/core/memory/response-analyzer.ts +81 -0
  119. package/core/memory/retrieval-feedback.ts +276 -0
  120. package/core/memory/serialization.ts +83 -0
  121. package/core/memory/stale-cleaner.ts +147 -0
  122. package/core/memory/stats.ts +181 -0
  123. package/core/memory/telemetry.ts +392 -0
  124. package/core/memory/temporal-facts.ts +356 -0
  125. package/core/memory/temporal-parser.ts +477 -0
  126. package/core/memory/trigger-detector.ts +104 -0
  127. package/core/memory/write-gate.ts +288 -0
  128. package/core/places/index.ts +14 -0
  129. package/core/places/memory-places.ts +339 -0
  130. package/core/places/places.ts +406 -0
  131. package/core/places/rules.ts +308 -0
  132. package/core/places/walking.ts +192 -0
  133. package/core/projects +89 -0
  134. package/core/projects.ts +131 -0
  135. package/core/redis.ts +82 -0
  136. package/core/responses.ts +187 -0
  137. package/core/runtime/trust-report.ts +195 -0
  138. package/core/runtime/trust-state.ts +360 -0
  139. package/core/scheduler/cron-scheduler.ts +581 -0
  140. package/core/scheduler/heartbeat.ts +91 -0
  141. package/core/scheduler/index.ts +8 -0
  142. package/core/scheduler/job-runner.ts +197 -0
  143. package/core/search/conversations.ts +166 -0
  144. package/core/search/entities.ts +46 -0
  145. package/core/search/folder-context.ts +154 -0
  146. package/core/search/graph-boost.ts +22 -0
  147. package/core/search/index.ts +4 -0
  148. package/core/search/qmd-wrapper.ts +84 -0
  149. package/core/security/encrypt.ts +51 -0
  150. package/core/security/governance.ts +102 -0
  151. package/core/security/privacy.ts +108 -0
  152. package/core/security/secret-detector.ts +122 -0
  153. package/core/session/auto-load.ts +160 -0
  154. package/core/session/entity-tracker.ts +363 -0
  155. package/core/session/index.ts +7 -0
  156. package/core/session/reference-resolver.ts +158 -0
  157. package/core/session/self-iteration-job.ts +478 -0
  158. package/core/session/session-hooks.ts +69 -0
  159. package/core/session/types.ts +36 -0
  160. package/core/session/working-set.ts +275 -0
  161. package/core/snapshots/cleanup.ts +13 -0
  162. package/core/snapshots/comparison.ts +59 -0
  163. package/core/snapshots/creation.ts +139 -0
  164. package/core/snapshots/retrieval.ts +44 -0
  165. package/core/snapshots/stats.ts +63 -0
  166. package/core/storage/cache.ts +241 -0
  167. package/core/storage/database.ts +23 -0
  168. package/core/summarization/cleanup.ts +13 -0
  169. package/core/summarization/queries.ts +32 -0
  170. package/core/summarization/stats.ts +64 -0
  171. package/core/summarization/strategies.ts +52 -0
  172. package/core/summarization.ts +248 -0
  173. package/core/temporal-facts.ts +244 -0
  174. package/core/tracing/collector.ts +470 -0
  175. package/core/tracing/visualizer.ts +195 -0
  176. package/core/utils/cleanup-operations.ts +50 -0
  177. package/core/utils/content-extraction.ts +95 -0
  178. package/core/utils/filter-builder.ts +56 -0
  179. package/core/utils/history-traversal.ts +63 -0
  180. package/core/utils/memory-operations.ts +56 -0
  181. package/core/utils/query-operations.ts +83 -0
  182. package/core/utils/summarization-helpers.ts +45 -0
  183. package/core/utils/temporal-queries.ts +39 -0
  184. package/core/utils/vector-operations.ts +135 -0
  185. package/core/utils/version-management.ts +74 -0
  186. package/core/worker.ts +324 -0
  187. package/db/adapter.ts +215 -0
  188. package/db/bootstrap.ts +1055 -0
  189. package/db/drizzle/migrations/0000_needy_cerebro.sql +402 -0
  190. package/db/drizzle/migrations/meta/0000_snapshot.json +3451 -0
  191. package/db/drizzle/migrations/meta/_journal.json +13 -0
  192. package/db/drizzle/schema-sqlite.ts +1032 -0
  193. package/db/drizzle/schema.ts +1128 -0
  194. package/db/drizzle.config.ts +12 -0
  195. package/db/index.ts +83 -0
  196. package/db/init.sql +5 -0
  197. package/db/migrations/associations.ts +35 -0
  198. package/db/migrations/beliefs.ts +89 -0
  199. package/db/migrations/core-memory.ts +35 -0
  200. package/db/migrations/fts.ts +59 -0
  201. package/db/migrations/index.ts +54 -0
  202. package/db/migrations/indexes.ts +36 -0
  203. package/db/migrations/learnings.ts +34 -0
  204. package/db/migrations/maintenance.ts +68 -0
  205. package/db/migrations/memories.ts +22 -0
  206. package/db/migrations/memory-places.ts +35 -0
  207. package/db/migrations/places.ts +49 -0
  208. package/db/migrations/projects.ts +21 -0
  209. package/db/migrations/tier-conversion.ts +24 -0
  210. package/db/neon.ts +22 -0
  211. package/db/schema/beliefs.ts +50 -0
  212. package/db/schema/generator.ts +159 -0
  213. package/db/schema/index.ts +58 -0
  214. package/db/schema/learnings.ts +32 -0
  215. package/db/schema/memories.ts +83 -0
  216. package/db/schema/projects.ts +33 -0
  217. package/db/schema.ts +13 -0
  218. package/db/supabase.ts +27 -0
  219. package/dist/config.d.ts +40 -17
  220. package/dist/config.js +150 -198
  221. package/dist/core/adapters/types.d.ts +13 -33
  222. package/dist/core/adapters/types.js +1 -1
  223. package/dist/core/agent-preferences.d.ts +16 -0
  224. package/dist/core/agent-preferences.js +124 -0
  225. package/dist/core/algorithms/safety/safety-checks.d.ts +1 -5
  226. package/dist/core/algorithms/types.d.ts +0 -8
  227. package/dist/core/associations.d.ts +3 -1
  228. package/dist/core/associations.js +37 -1
  229. package/dist/core/beliefs/decay.d.ts +27 -0
  230. package/dist/core/beliefs/decay.js +217 -0
  231. package/dist/core/beliefs/extractor.d.ts +9 -0
  232. package/dist/core/beliefs/extractor.js +113 -0
  233. package/dist/core/beliefs/store.d.ts +46 -0
  234. package/dist/core/beliefs/store.js +466 -0
  235. package/dist/core/beliefs/types.d.ts +28 -0
  236. package/dist/core/beliefs/types.js +2 -0
  237. package/dist/core/commands/mcp-server.d.ts +0 -1
  238. package/dist/core/commands/mcp-server.js +4 -737
  239. package/dist/core/commands/remember.d.ts +24 -0
  240. package/dist/core/commands/remember.js +144 -0
  241. package/dist/core/{toon.d.ts → compression.d.ts} +6 -4
  242. package/dist/core/{toon.js → compression.js} +8 -8
  243. package/dist/core/context/agent-context.js +1 -1
  244. package/dist/core/embeddings/embeddings.d.ts +29 -0
  245. package/dist/core/embeddings/embeddings.js +546 -0
  246. package/dist/core/embeddings/google-multimodal.js +6 -2
  247. package/dist/core/{local-embeddings.d.ts → embeddings/local-embeddings.d.ts} +1 -1
  248. package/dist/core/embeddings/local-embeddings.js +11 -0
  249. package/dist/core/embeddings/qmd-client.js +1 -1
  250. package/dist/core/embeddings/transformers-local.d.ts +64 -0
  251. package/dist/core/embeddings/transformers-local.js +213 -0
  252. package/dist/core/embeddings.d.ts +1 -28
  253. package/dist/core/embeddings.js +2 -453
  254. package/dist/core/graph/entity-deduplicator.d.ts +24 -0
  255. package/dist/core/graph/entity-deduplicator.js +183 -0
  256. package/dist/core/graph/graph-builder.d.ts +46 -0
  257. package/dist/core/graph/graph-builder.js +174 -0
  258. package/dist/core/graph/graph-traversal.d.ts +80 -0
  259. package/dist/core/graph/graph-traversal.js +315 -0
  260. package/dist/core/graph/index.d.ts +19 -0
  261. package/dist/core/graph/index.js +13 -0
  262. package/dist/core/graph/llm-entity-extractor.d.ts +49 -0
  263. package/dist/core/graph/llm-entity-extractor.js +313 -0
  264. package/dist/core/graph/multi-hop-retrieval.d.ts +48 -0
  265. package/dist/core/graph/multi-hop-retrieval.js +215 -0
  266. package/dist/core/graph/relationship-extractor.d.ts +48 -0
  267. package/dist/core/graph/relationship-extractor.js +351 -0
  268. package/dist/core/hooks/agent-hooks.d.ts +10 -1
  269. package/dist/core/hooks/agent-hooks.js +301 -24
  270. package/dist/core/hot-cache.d.ts +86 -0
  271. package/dist/core/hot-cache.js +285 -0
  272. package/dist/core/index.d.ts +9 -9
  273. package/dist/core/index.js +9 -12
  274. package/dist/core/ingestion/core-memory.d.ts +2 -2
  275. package/dist/core/ingestion/core-memory.js +3 -3
  276. package/dist/core/ingestion/learnings.js +3 -0
  277. package/dist/core/ingestion/signal-engine.d.ts +41 -0
  278. package/dist/core/ingestion/signal-engine.js +201 -0
  279. package/dist/core/{obsidian-vault.d.ts → integrations/obsidian-vault.d.ts} +2 -1
  280. package/dist/core/{obsidian-vault.js → integrations/obsidian-vault.js} +69 -7
  281. package/dist/core/lib/parse-embedding.d.ts +9 -0
  282. package/dist/core/lib/parse-embedding.js +58 -0
  283. package/dist/core/lib/schemas.d.ts +57 -54
  284. package/dist/core/lib/types.d.ts +45 -0
  285. package/dist/core/lib/types.js +6 -0
  286. package/dist/core/lib/utils.d.ts +4 -0
  287. package/dist/core/lib/utils.js +55 -0
  288. package/dist/core/lifecycle.d.ts +0 -1
  289. package/dist/core/lifecycle.js +13 -23
  290. package/dist/core/logger.d.ts +1 -0
  291. package/dist/core/logger.js +14 -8
  292. package/dist/core/mcp/tools.d.ts +0 -2
  293. package/dist/core/mcp/tools.js +0 -87
  294. package/dist/core/mcp/types.d.ts +25 -253
  295. package/dist/core/mcp/types.js +2 -2
  296. package/dist/core/memory/categorizer.js +1 -0
  297. package/dist/core/memory/consolidation.js +2 -28
  298. package/dist/core/memory/entity-extractor.d.ts +4 -0
  299. package/dist/core/memory/entity-extractor.js +30 -16
  300. package/dist/core/memory/explain.d.ts +18 -0
  301. package/dist/core/memory/explain.js +92 -0
  302. package/dist/core/memory/fact-deriver.d.ts +31 -0
  303. package/dist/core/memory/fact-deriver.js +236 -0
  304. package/dist/core/memory/hybrid-retrieval.d.ts +14 -16
  305. package/dist/core/memory/hybrid-retrieval.js +25 -127
  306. package/dist/core/memory/hybrid-scorer.js +6 -23
  307. package/dist/core/memory/hybrid-search.d.ts +10 -7
  308. package/dist/core/memory/hybrid-search.js +458 -221
  309. package/dist/core/memory/importance.d.ts +0 -17
  310. package/dist/core/memory/importance.js +1 -58
  311. package/dist/core/memory/index.d.ts +1 -0
  312. package/dist/core/memory/index.js +1 -0
  313. package/dist/core/memory/memories.d.ts +13 -17
  314. package/dist/core/memory/memories.js +78 -75
  315. package/dist/core/memory/memory-lifecycle.d.ts +2 -2
  316. package/dist/core/memory/memory-lifecycle.js +10 -18
  317. package/dist/core/memory/normalization.d.ts +1 -16
  318. package/dist/core/memory/path-strengthener.d.ts +39 -0
  319. package/dist/core/memory/path-strengthener.js +150 -0
  320. package/dist/core/memory/query-processor.js +37 -3
  321. package/dist/core/memory/retrieval-feedback.d.ts +70 -0
  322. package/dist/core/memory/retrieval-feedback.js +213 -0
  323. package/dist/core/memory/stale-cleaner.d.ts +26 -0
  324. package/dist/core/memory/stale-cleaner.js +97 -0
  325. package/dist/core/memory/stats.d.ts +10 -0
  326. package/dist/core/memory/stats.js +8 -3
  327. package/dist/core/memory/trigger-detector.d.ts +8 -1
  328. package/dist/core/memory/trigger-detector.js +42 -5
  329. package/dist/core/places/index.d.ts +1 -1
  330. package/dist/core/places/index.js +1 -1
  331. package/dist/core/places/places.d.ts +13 -13
  332. package/dist/core/places/places.js +27 -27
  333. package/dist/core/places/rules.js +23 -23
  334. package/dist/core/places/walking.d.ts +3 -3
  335. package/dist/core/places/walking.js +7 -7
  336. package/dist/core/projects.js +8 -0
  337. package/dist/core/runtime/trust-report.d.ts +102 -0
  338. package/dist/core/runtime/trust-report.js +107 -0
  339. package/dist/core/runtime/trust-state.d.ts +12 -0
  340. package/dist/core/runtime/trust-state.js +309 -0
  341. package/dist/core/scheduler/cron-scheduler.d.ts +1 -1
  342. package/dist/core/scheduler/cron-scheduler.js +164 -3
  343. package/dist/core/scheduler/job-runner.js +1 -1
  344. package/dist/core/search/qmd-wrapper.d.ts +36 -0
  345. package/dist/core/search/qmd-wrapper.js +58 -0
  346. package/dist/core/session/auto-load.js +28 -3
  347. package/dist/core/session/entity-tracker.d.ts +62 -0
  348. package/dist/core/session/entity-tracker.js +287 -0
  349. package/dist/core/session/reference-resolver.d.ts +26 -0
  350. package/dist/core/session/reference-resolver.js +121 -0
  351. package/dist/core/session/self-iteration-job.d.ts +15 -0
  352. package/dist/core/session/self-iteration-job.js +163 -58
  353. package/dist/core/session/working-set.d.ts +50 -0
  354. package/dist/core/session/working-set.js +212 -0
  355. package/dist/core/snapshots/creation.d.ts +2 -8
  356. package/dist/core/snapshots/creation.js +3 -12
  357. package/dist/core/utils/summarization-helpers.d.ts +0 -4
  358. package/dist/core/utils/summarization-helpers.js +1 -6
  359. package/dist/db/bootstrap.d.ts +2 -0
  360. package/dist/db/bootstrap.js +229 -280
  361. package/dist/db/drizzle/schema-sqlite.d.ts +702 -1
  362. package/dist/db/drizzle/schema-sqlite.js +83 -4
  363. package/dist/db/drizzle/schema.d.ts +653 -1
  364. package/dist/db/drizzle/schema.js +93 -4
  365. package/dist/db/migrations/associations.d.ts +6 -0
  366. package/dist/db/migrations/associations.js +29 -0
  367. package/dist/db/migrations/beliefs.d.ts +10 -0
  368. package/dist/db/migrations/beliefs.js +76 -0
  369. package/dist/db/migrations/core-memory.d.ts +6 -0
  370. package/dist/db/migrations/core-memory.js +29 -0
  371. package/dist/db/migrations/fts.d.ts +6 -0
  372. package/dist/db/migrations/fts.js +52 -0
  373. package/dist/db/migrations/index.d.ts +25 -0
  374. package/dist/db/migrations/index.js +51 -0
  375. package/dist/db/migrations/indexes.d.ts +6 -0
  376. package/dist/db/migrations/indexes.js +30 -0
  377. package/dist/db/migrations/learnings.d.ts +7 -0
  378. package/dist/db/migrations/learnings.js +26 -0
  379. package/dist/db/migrations/maintenance.d.ts +6 -0
  380. package/dist/db/migrations/maintenance.js +61 -0
  381. package/dist/db/migrations/memories.d.ts +7 -0
  382. package/dist/db/migrations/memories.js +16 -0
  383. package/dist/db/migrations/memory-places.d.ts +6 -0
  384. package/dist/db/migrations/memory-places.js +29 -0
  385. package/dist/db/migrations/places.d.ts +6 -0
  386. package/dist/db/migrations/places.js +43 -0
  387. package/dist/db/migrations/projects.d.ts +3 -0
  388. package/dist/db/migrations/projects.js +13 -0
  389. package/dist/db/migrations/tier-conversion.d.ts +7 -0
  390. package/dist/db/migrations/tier-conversion.js +20 -0
  391. package/dist/db/schema/beliefs.d.ts +9 -0
  392. package/dist/db/schema/beliefs.js +46 -0
  393. package/dist/db/schema/generator.d.ts +38 -0
  394. package/dist/db/schema/generator.js +108 -0
  395. package/dist/db/schema/index.d.ts +19 -20
  396. package/dist/db/schema/index.js +25 -79
  397. package/dist/db/schema/learnings.d.ts +7 -0
  398. package/dist/db/schema/learnings.js +30 -0
  399. package/dist/db/schema/memories.d.ts +7 -0
  400. package/dist/db/schema/memories.js +81 -0
  401. package/dist/db/schema/projects.d.ts +4 -0
  402. package/dist/db/schema/projects.js +31 -0
  403. package/dist/packages/mcp/src/index.d.ts +3 -0
  404. package/dist/packages/mcp/src/index.js +733 -0
  405. package/mcp.json.example +8 -11
  406. package/package.json +57 -76
  407. package/packages/cli/package.json +22 -0
  408. package/packages/cli/src/commands/clean.ts +68 -0
  409. package/packages/cli/src/commands/context.ts +79 -0
  410. package/packages/cli/src/commands/doctor.ts +357 -0
  411. package/packages/cli/src/commands/forget.ts +72 -0
  412. package/packages/cli/src/commands/health.ts +36 -0
  413. package/packages/cli/src/commands/inspect.ts +41 -0
  414. package/packages/cli/src/commands/link.ts +50 -0
  415. package/packages/cli/src/commands/migrate.ts +93 -0
  416. package/packages/cli/src/commands/recall.ts +99 -0
  417. package/packages/cli/src/commands/recent.ts +57 -0
  418. package/packages/cli/src/commands/remember.ts +139 -0
  419. package/packages/cli/src/commands/run.ts +58 -0
  420. package/packages/cli/src/commands/stale.ts +43 -0
  421. package/packages/cli/src/commands/stats.ts +42 -0
  422. package/packages/cli/src/index.ts +57 -0
  423. package/packages/cli/tsconfig.json +24 -0
  424. package/packages/mcp/package.json +26 -0
  425. package/packages/mcp/src/index.ts +877 -0
  426. package/packages/mcp/tsconfig.json +20 -0
  427. package/skills/squish-memory/SKILL.md +38 -35
  428. package/skills/squish-memory/{scripts/install.sh → install.sh} +1 -1
  429. package/skills/squish-memory/references/claude-desktop.json +12 -0
  430. package/skills/squish-memory/references/openclaw.json +13 -0
  431. package/skills/squish-memory/references/opencode.json +14 -0
  432. package/config/hooks/claude-code-hooks.json +0 -39
  433. package/config/hooks/cursor-hooks.json +0 -30
  434. package/config/hooks/opencode-hooks.json +0 -30
  435. package/config/hooks/windsurf-hooks.json +0 -30
  436. package/config/mcp-cli-fallback-policy.json +0 -22
  437. package/config/mcp.json +0 -38
  438. package/config/plugin-manifest.json +0 -101
  439. package/config/plugin-manifest.schema.json +0 -244
  440. package/config/plugin.json +0 -32
  441. package/config/remote-memory-policy.json +0 -32
  442. package/core/commands/context-paging.md +0 -51
  443. package/core/commands/context-status.md +0 -22
  444. package/core/commands/context.md +0 -5
  445. package/core/commands/core-memory.md +0 -56
  446. package/core/commands/health.md +0 -5
  447. package/core/commands/init.md +0 -39
  448. package/core/commands/merge.md +0 -113
  449. package/core/commands/recall.md +0 -5
  450. package/core/commands/remember.md +0 -11
  451. package/core/commands/search.md +0 -10
  452. package/dist/core/commands/managed-sync.d.ts +0 -10
  453. package/dist/core/commands/managed-sync.js +0 -64
  454. package/dist/core/external-folder/index.d.ts +0 -102
  455. package/dist/core/external-folder/index.js +0 -294
  456. package/dist/core/namespaces/index.d.ts +0 -71
  457. package/dist/core/namespaces/index.js +0 -305
  458. package/dist/core/namespaces/uri-parser.d.ts +0 -31
  459. package/dist/core/namespaces/uri-parser.js +0 -74
  460. package/dist/core/search/qmd-search.d.ts +0 -61
  461. package/dist/core/search/qmd-search.js +0 -178
  462. package/dist/core/session-hooks/self-iteration-job.d.ts +0 -20
  463. package/dist/core/session-hooks/self-iteration-job.js +0 -282
  464. package/dist/core/session-hooks/session-hooks.d.ts +0 -18
  465. package/dist/core/session-hooks/session-hooks.js +0 -58
  466. package/dist/core/snapshots.d.ts +0 -29
  467. package/dist/core/snapshots.js +0 -220
  468. package/dist/core/sync/qmd-sync.d.ts +0 -94
  469. package/dist/core/sync/qmd-sync.js +0 -201
  470. package/dist/index.d.ts +0 -7
  471. package/dist/index.js +0 -1677
  472. package/dist/vendor/sql.js/sql-wasm.wasm +0 -0
  473. package/dist/webui/server.d.ts +0 -5
  474. package/dist/webui/server.js +0 -642
  475. package/generated/mcp/manifest.json +0 -23
  476. package/generated/mcp/mcp-servers.json +0 -25
  477. package/generated/mcp/mcporter.json +0 -34
  478. package/generated/mcp/openclaw-memory-qmd.json +0 -17
  479. package/generated/mcp/runtime.json +0 -12
  480. package/scripts/README.md +0 -60
  481. package/scripts/build-release.sh +0 -36
  482. package/scripts/check-secrets.js +0 -132
  483. package/scripts/copy-runtime-assets.mjs +0 -26
  484. package/scripts/generate-mcp.mjs +0 -264
  485. package/scripts/github-release.sh +0 -77
  486. package/scripts/init-dirs.mjs +0 -13
  487. package/scripts/install-claude-code.sh +0 -85
  488. package/scripts/install-cursor.sh +0 -56
  489. package/scripts/install-hooks.sh +0 -73
  490. package/scripts/install-interactive.mjs +0 -357
  491. package/scripts/install-opencode.sh +0 -75
  492. package/scripts/install-plugin.mjs +0 -415
  493. package/scripts/install-windsurf.sh +0 -67
  494. package/scripts/remote-preflight.mjs +0 -62
  495. package/scripts/squish-fallback.mjs +0 -132
  496. package/scripts/test-interactive.mjs +0 -131
  497. package/scripts/verify-mcp.mjs +0 -214
  498. package/skills/squish-memory/scripts/install.mjs +0 -335
  499. package/skills/squish-memory/write_skill.js +0 -2
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Memory Statistics Module
3
+ * Provides memory usage statistics for CLI and MCP
4
+ */
5
+
6
+ import { getDb } from '../../db/index.js';
7
+ import { getSchema } from '../../db/schema.js';
8
+ import { config } from '../../config.js';
9
+ import { ensureProject } from '../../core/projects.js';
10
+ import { createDatabaseClient } from '../storage/database.js';
11
+ import { getProjectSignalStats } from '../session/working-set.js';
12
+
13
+ export interface MemoryStats {
14
+ totalMemories: number;
15
+ byType: Record<string, number>;
16
+ totalNotes: number;
17
+ notesByCategory: Record<string, number>;
18
+ totalLearnings: number;
19
+ learningsByType: Record<string, number>;
20
+ totalLinks: number;
21
+ oldestMemory?: string;
22
+ newestMemory?: string;
23
+ projectPath: string;
24
+ mode: string;
25
+ signal?: {
26
+ captured: number;
27
+ suppressed: number;
28
+ sessionOnly: number;
29
+ durable: number;
30
+ durableWithRaw: number;
31
+ tokensSaved: number;
32
+ placeRouted: number;
33
+ graphEnriched: number;
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Get memory statistics for a project
39
+ */
40
+ export async function getMemoryStats(projectPath: string = process.cwd()): Promise<MemoryStats> {
41
+ let db: any;
42
+ try {
43
+ db = createDatabaseClient(await getDb());
44
+ } catch (error) {
45
+ throw new Error(`Database unavailable: ${error instanceof Error ? error.message : 'Unknown error'}`);
46
+ }
47
+
48
+ const schema = await getSchema();
49
+ const project = await ensureProject(projectPath);
50
+ if (!project) {
51
+ throw new Error(`Project not found: ${projectPath}`);
52
+ }
53
+
54
+ const stats: MemoryStats = {
55
+ totalMemories: 0,
56
+ byType: {},
57
+ totalNotes: 0,
58
+ notesByCategory: {},
59
+ totalLearnings: 0,
60
+ learningsByType: {},
61
+ totalLinks: 0,
62
+ projectPath,
63
+ mode: config.isTeamMode ? 'team' : 'local',
64
+ };
65
+
66
+ try {
67
+ // Count total memories
68
+ const countResult = await db
69
+ .select({ count: schema.memories.id })
70
+ .from(schema.memories)
71
+ .where(eq(schema.memories.projectId, project.id));
72
+
73
+ stats.totalMemories = countResult.length;
74
+
75
+ // Count by type
76
+ if (config.isTeamMode) {
77
+ // PostgreSQL - use raw query for GROUP BY
78
+ const typeCounts = await db.execute(sql`
79
+ SELECT type, COUNT(*) as count
80
+ FROM memories
81
+ ${sql`WHERE project_id = ${project.id}`}
82
+ GROUP BY type
83
+ `);
84
+ for (const row of typeCounts.rows) {
85
+ stats.byType[row.type] = Number(row.count);
86
+ }
87
+ } else {
88
+ // SQLite - get all and count in memory
89
+ const allMemories = await db
90
+ .select({ type: schema.memories.type })
91
+ .from(schema.memories)
92
+ .where(eq(schema.memories.projectId, project.id));
93
+
94
+ for (const mem of allMemories) {
95
+ const type = mem.type || 'unknown';
96
+ stats.byType[type] = (stats.byType[type] || 0) + 1;
97
+ }
98
+ }
99
+
100
+ // Get oldest and newest
101
+ const oldest = await db
102
+ .select({ createdAt: schema.memories.createdAt })
103
+ .from(schema.memories)
104
+ .where(eq(schema.memories.projectId, project.id))
105
+ .orderBy(asc(schema.memories.createdAt))
106
+ .limit(1);
107
+
108
+ const newest = await db
109
+ .select({ createdAt: schema.memories.createdAt })
110
+ .from(schema.memories)
111
+ .where(eq(schema.memories.projectId, project.id))
112
+ .orderBy(desc(schema.memories.createdAt))
113
+ .limit(1);
114
+
115
+ if (oldest.length > 0 && oldest[0].createdAt) {
116
+ stats.oldestMemory = oldest[0].createdAt;
117
+ }
118
+ if (newest.length > 0 && newest[0].createdAt) {
119
+ stats.newestMemory = newest[0].createdAt;
120
+ }
121
+
122
+ // Learnings
123
+ const allLearnings = await db
124
+ .select({ category: schema.learnings.category, type: schema.learnings.type })
125
+ .from(schema.learnings)
126
+ .where(eq(schema.learnings.projectId, project.id));
127
+
128
+ stats.totalNotes = allLearnings.length;
129
+ for (const obs of allLearnings) {
130
+ const cat = obs.category || 'uncategorized';
131
+ stats.notesByCategory[cat] = (stats.notesByCategory[cat] || 0) + 1;
132
+ }
133
+
134
+ // Learnings by type
135
+ const learningTypes = ['success', 'failure', 'fix', 'insight'];
136
+ const learningRecords = allLearnings.filter((o: any) => {
137
+ const type = o.type || '';
138
+ return learningTypes.includes(type.toLowerCase());
139
+ });
140
+ stats.totalLearnings = learningRecords.length;
141
+ // Count by type
142
+ for (const obs of learningRecords) {
143
+ const type = (obs as any).type || 'unknown';
144
+ stats.learningsByType[type] = (stats.learningsByType[type] || 0) + 1;
145
+ }
146
+
147
+ // Links
148
+ // Links are scoped via their associated memories
149
+ if (config.isTeamMode) {
150
+ // PostgreSQL - use raw query to join through memories
151
+ const linksCount = await db.execute(sql`
152
+ SELECT COUNT(*) as count FROM memory_associations ma
153
+ JOIN memories m1 ON ma.from_memory_id = m1.id
154
+ JOIN memories m2 ON ma.to_memory_id = m2.id
155
+ ${project ? sql`WHERE m1.project_id = ${project.id} OR m2.project_id = ${project.id}` : sql``}
156
+ `);
157
+ stats.totalLinks = Number(linksCount.rows[0]?.count || 0);
158
+ } else {
159
+ // SQLite - get all and filter in memory
160
+ const allLinks = await db
161
+ .select({
162
+ fromProjectId: schema.memories.projectId,
163
+ toProjectId: schema.memories.projectId
164
+ })
165
+ .from(schema.memoryAssociations)
166
+ .innerJoin(schema.memories, eq(schema.memoryAssociations.fromMemoryId, schema.memories.id))
167
+ .where(project ? eq(schema.memories.projectId, project.id) : undefined);
168
+ stats.totalLinks = allLinks.length;
169
+ }
170
+
171
+ } catch (error) {
172
+ // Return empty stats on error
173
+ console.error('Error getting memory stats:', error);
174
+ }
175
+
176
+ stats.signal = await getProjectSignalStats(projectPath);
177
+
178
+ return stats;
179
+ }
180
+
181
+ import { eq, sql, asc, desc } from 'drizzle-orm';
@@ -0,0 +1,392 @@
1
+ /**
2
+ * Retrieval Quality Telemetry
3
+ * Tracks memory usage patterns (echo/fizzle) to improve retrieval quality
4
+ * Echo: memory was retrieved and used
5
+ * Fizzle: memory was retrieved but not used
6
+ */
7
+
8
+ import { eq, and, desc } from 'drizzle-orm';
9
+ import { getDb } from '../../db/index.js';
10
+ import { getSchema } from '../../db/schema.js';
11
+ import { logger } from '../logger.js';
12
+
13
+ export interface RetrievalEvent {
14
+ memoryId: string;
15
+ query: string;
16
+ position: number; // Position in results
17
+ score: number;
18
+ wasUsed: boolean; // true = echo, false = fizzle
19
+ sessionId?: string;
20
+ timestamp: Date;
21
+ }
22
+
23
+ export interface RetrievalStats {
24
+ totalRetrievals: number;
25
+ echoes: number;
26
+ fizzles: number;
27
+ echoRate: number;
28
+ avgPosition: number;
29
+ topMemories: string[];
30
+ underperformingMemories: string[];
31
+ }
32
+
33
+ export interface MemoryTelemetry {
34
+ memoryId: string;
35
+ retrievalCount: number;
36
+ echoCount: number;
37
+ fizzleCount: number;
38
+ echoRate: number;
39
+ avgPosition: number;
40
+ lastRetrieved?: Date;
41
+ lastEchoed?: Date;
42
+ }
43
+
44
+ // In-memory cache for recent retrieval events (flushed periodically)
45
+ const retrievalEvents: RetrievalEvent[] = [];
46
+ const MAX_CACHE_SIZE = 1000;
47
+
48
+ /**
49
+ * Record a retrieval event
50
+ */
51
+ export function recordRetrieval(
52
+ memoryId: string,
53
+ query: string,
54
+ position: number,
55
+ score: number,
56
+ sessionId?: string
57
+ ): void {
58
+ const event: RetrievalEvent = {
59
+ memoryId,
60
+ query,
61
+ position,
62
+ score,
63
+ wasUsed: false, // Initially false, updated when echoed
64
+ sessionId,
65
+ timestamp: new Date(),
66
+ };
67
+
68
+ retrievalEvents.push(event);
69
+
70
+ // Flush if cache is full
71
+ if (retrievalEvents.length >= MAX_CACHE_SIZE) {
72
+ flushRetrievalEvents().catch(err => {
73
+ logger.error('Failed to flush retrieval events', err);
74
+ });
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Mark a retrieval as "echoed" (memory was actually used)
80
+ */
81
+ export function recordEcho(
82
+ memoryId: string,
83
+ sessionId?: string
84
+ ): void {
85
+ // Find the most recent retrieval for this memory
86
+ const recentIndex = retrievalEvents.findIndex(
87
+ (e, i) =>
88
+ e.memoryId === memoryId &&
89
+ !e.wasUsed &&
90
+ (sessionId ? e.sessionId === sessionId : true)
91
+ );
92
+
93
+ if (recentIndex !== -1) {
94
+ retrievalEvents[recentIndex].wasUsed = true;
95
+ } else {
96
+ // Add a new echo event if not found in cache
97
+ retrievalEvents.push({
98
+ memoryId,
99
+ query: '',
100
+ position: 0,
101
+ score: 0,
102
+ wasUsed: true,
103
+ sessionId,
104
+ timestamp: new Date(),
105
+ });
106
+ }
107
+
108
+ // Update memory's echo count directly
109
+ incrementMemoryEcho(memoryId).catch(err => {
110
+ logger.debug('Failed to increment echo count', err);
111
+ });
112
+ }
113
+
114
+ /**
115
+ * Mark retrievals as "fizzled" (memory was not used)
116
+ * Call this at the end of a session for non-echoed retrievals
117
+ */
118
+ export function recordFizzle(
119
+ memoryId: string,
120
+ sessionId?: string
121
+ ): void {
122
+ incrementMemoryFizzle(memoryId).catch(err => {
123
+ logger.debug('Failed to increment fizzle count', err);
124
+ });
125
+ }
126
+
127
+ /**
128
+ * Flush cached retrieval events to database
129
+ */
130
+ export async function flushRetrievalEvents(): Promise<void> {
131
+ if (retrievalEvents.length === 0) return;
132
+
133
+ const events = [...retrievalEvents];
134
+ retrievalEvents.length = 0; // Clear cache
135
+
136
+ try {
137
+ const db = await getDb();
138
+ const schema = await getSchema();
139
+
140
+ // Group by memoryId for batch updates
141
+ const byMemory = new Map<string, RetrievalEvent[]>();
142
+ for (const event of events) {
143
+ const existing = byMemory.get(event.memoryId) || [];
144
+ existing.push(event);
145
+ byMemory.set(event.memoryId, existing);
146
+ }
147
+
148
+ // Update each memory's telemetry
149
+ for (const [memoryId, memEvents] of byMemory.entries()) {
150
+ const echoCount = memEvents.filter(e => e.wasUsed).length;
151
+ const fizzleCount = memEvents.filter(e => !e.wasUsed).length;
152
+
153
+ // Get current stats
154
+ const memories = await (db as any)
155
+ .select()
156
+ .from(schema.memories)
157
+ .where(eq(schema.memories.id, memoryId))
158
+ .limit(1);
159
+
160
+ if (memories.length > 0) {
161
+ const current = memories[0];
162
+ const newEchoCount = (current.echoCount || 0) + echoCount;
163
+ const newFizzleCount = (current.fizzleCount || 0) + fizzleCount;
164
+ const newRetrievalCount = (current.retrievalCount || 0) + memEvents.length;
165
+
166
+ await (db as any)
167
+ .update(schema.memories)
168
+ .set({
169
+ echoCount: newEchoCount,
170
+ fizzleCount: newFizzleCount,
171
+ retrievalCount: newRetrievalCount,
172
+ lastRetrievedAt: new Date(),
173
+ updatedAt: new Date(),
174
+ })
175
+ .where(eq(schema.memories.id, memoryId));
176
+ }
177
+ }
178
+
179
+ logger.debug('Flushed retrieval events', { count: events.length });
180
+
181
+ } catch (error) {
182
+ logger.error('Error flushing retrieval events', error);
183
+ // Re-add events to cache on failure
184
+ retrievalEvents.push(...events);
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Increment memory's echo count directly
190
+ */
191
+ async function incrementMemoryEcho(memoryId: string): Promise<void> {
192
+ try {
193
+ const db = await getDb();
194
+ const schema = await getSchema();
195
+
196
+ const memories = await (db as any)
197
+ .select()
198
+ .from(schema.memories)
199
+ .where(eq(schema.memories.id, memoryId))
200
+ .limit(1);
201
+
202
+ if (memories.length > 0) {
203
+ const current = memories[0];
204
+ await (db as any)
205
+ .update(schema.memories)
206
+ .set({
207
+ echoCount: (current.echoCount || 0) + 1,
208
+ lastEchoedAt: new Date(),
209
+ coactivationScore: (current.coactivationScore || 0) + 1,
210
+ updatedAt: new Date(),
211
+ })
212
+ .where(eq(schema.memories.id, memoryId));
213
+ }
214
+ } catch (error) {
215
+ logger.debug('Error incrementing echo count', { error });
216
+ }
217
+ }
218
+
219
+ /**
220
+ * Increment memory's fizzle count directly
221
+ */
222
+ async function incrementMemoryFizzle(memoryId: string): Promise<void> {
223
+ try {
224
+ const db = await getDb();
225
+ const schema = await getSchema();
226
+
227
+ const memories = await (db as any)
228
+ .select()
229
+ .from(schema.memories)
230
+ .where(eq(schema.memories.id, memoryId))
231
+ .limit(1);
232
+
233
+ if (memories.length > 0) {
234
+ const current = memories[0];
235
+ await (db as any)
236
+ .update(schema.memories)
237
+ .set({
238
+ fizzleCount: (current.fizzleCount || 0) + 1,
239
+ updatedAt: new Date(),
240
+ })
241
+ .where(eq(schema.memories.id, memoryId));
242
+ }
243
+ } catch (error) {
244
+ logger.debug('Error incrementing fizzle count', { error });
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Get telemetry for a specific memory
250
+ */
251
+ export async function getMemoryTelemetry(memoryId: string): Promise<MemoryTelemetry | null> {
252
+ try {
253
+ const db = await getDb();
254
+ const schema = await getSchema();
255
+
256
+ const memories = await (db as any)
257
+ .select()
258
+ .from(schema.memories)
259
+ .where(eq(schema.memories.id, memoryId))
260
+ .limit(1);
261
+
262
+ if (memories.length === 0) return null;
263
+
264
+ const m = memories[0];
265
+ const echoCount = m.echoCount || 0;
266
+ const fizzleCount = m.fizzleCount || 0;
267
+ const total = echoCount + fizzleCount;
268
+
269
+ return {
270
+ memoryId: m.id,
271
+ retrievalCount: m.retrievalCount || 0,
272
+ echoCount,
273
+ fizzleCount,
274
+ echoRate: total > 0 ? echoCount / total : 0,
275
+ avgPosition: 0, // Would need to calculate from retrieval events
276
+ lastRetrieved: m.lastRetrievedAt,
277
+ lastEchoed: m.lastEchoedAt,
278
+ };
279
+
280
+ } catch (error) {
281
+ logger.error('Error getting memory telemetry', error);
282
+ return null;
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Get overall retrieval statistics
288
+ */
289
+ export async function getRetrievalStats(projectId?: string): Promise<RetrievalStats> {
290
+ try {
291
+ const db = await getDb();
292
+ const schema = await getSchema();
293
+
294
+ const whereClause = projectId
295
+ ? eq(schema.memories.projectId, projectId)
296
+ : undefined;
297
+
298
+ const memories = await (db as any)
299
+ .select()
300
+ .from(schema.memories)
301
+ .where(whereClause)
302
+ .orderBy(desc(schema.memories.retrievalCount))
303
+ .limit(1000);
304
+
305
+ let totalRetrievals = 0;
306
+ let totalEchoes = 0;
307
+ let totalFizzles = 0;
308
+ const topMemories: string[] = [];
309
+ const underperforming: string[] = [];
310
+
311
+ for (const m of memories) {
312
+ const echoes = m.echoCount || 0;
313
+ const fizzles = m.fizzleCount || 0;
314
+ const retrievals = m.retrievalCount || 0;
315
+
316
+ totalRetrievals += retrievals;
317
+ totalEchoes += echoes;
318
+ totalFizzles += fizzles;
319
+
320
+ // Top performers (high echo rate with sufficient data)
321
+ if (echoes >= 3 && (echoes / (echoes + fizzles)) >= 0.8) {
322
+ topMemories.push(m.id);
323
+ }
324
+
325
+ // Underperformers (high fizzle rate with sufficient data)
326
+ if (fizzles >= 5 && (fizzles / (echoes + fizzles)) >= 0.7) {
327
+ underperforming.push(m.id);
328
+ }
329
+ }
330
+
331
+ const echoRate = (totalEchoes + totalFizzles) > 0
332
+ ? totalEchoes / (totalEchoes + totalFizzles)
333
+ : 0;
334
+
335
+ return {
336
+ totalRetrievals,
337
+ echoes: totalEchoes,
338
+ fizzles: totalFizzles,
339
+ echoRate,
340
+ avgPosition: 0, // Would need more detailed tracking
341
+ topMemories: topMemories.slice(0, 10),
342
+ underperformingMemories: underperforming.slice(0, 10),
343
+ };
344
+
345
+ } catch (error) {
346
+ logger.error('Error getting retrieval stats', error);
347
+ return {
348
+ totalRetrievals: 0,
349
+ echoes: 0,
350
+ fizzles: 0,
351
+ echoRate: 0,
352
+ avgPosition: 0,
353
+ topMemories: [],
354
+ underperformingMemories: [],
355
+ };
356
+ }
357
+ }
358
+
359
+ /**
360
+ * Adjust retrieval boosting based on echo/fizzle history
361
+ * Returns a boost factor (0.5 - 2.0) for a memory
362
+ */
363
+ export function calculateTelemetryBoost(telemetry: MemoryTelemetry | null): number {
364
+ if (!telemetry || telemetry.retrievalCount < 3) {
365
+ return 1.0; // Not enough data
366
+ }
367
+
368
+ const echoRate = telemetry.echoRate;
369
+
370
+ // High echo rate = boost
371
+ if (echoRate >= 0.8) {
372
+ return 1.5;
373
+ } else if (echoRate >= 0.6) {
374
+ return 1.2;
375
+ } else if (echoRate >= 0.4) {
376
+ return 1.0;
377
+ } else if (echoRate >= 0.2) {
378
+ return 0.8;
379
+ } else {
380
+ return 0.5; // Low echo rate = penalize
381
+ }
382
+ }
383
+
384
+ /**
385
+ * Periodic cleanup job for telemetry data
386
+ */
387
+ export async function cleanupOldTelemetry(daysToKeep: number = 90): Promise<number> {
388
+ // This would typically clean up a dedicated telemetry_events table
389
+ // For now, we just flush the in-memory cache
390
+ await flushRetrievalEvents();
391
+ return 0;
392
+ }