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,300 @@
1
+ /**
2
+ * Fact Deriver
3
+ *
4
+ * Derives implicit facts from existing relationships in the knowledge graph.
5
+ * Example: works_on(A, X) + uses(X, Y) -> depends_on(A, Y)
6
+ */
7
+
8
+ import { eq, and, or } from 'drizzle-orm';
9
+ import { getDb } from '../../db/index.js';
10
+ import { getSchema } from '../../db/schema.js';
11
+ import { logger } from '../logger.js';
12
+ import type { RelationType } from '../graph/llm-entity-extractor.js';
13
+
14
+ // Extend RelationType to include derived relation types
15
+ type ExtendedRelationType = RelationType | 'oversees' | 'may_affect';
16
+
17
+ // ─── Derivation Rules ─────────────────────────────────────────────────────────
18
+
19
+ interface DerivationRule {
20
+ name: string;
21
+ fromType: RelationType;
22
+ toType: RelationType;
23
+ derivedType: ExtendedRelationType;
24
+ description: string;
25
+ confidence: number;
26
+ }
27
+
28
+ const DERIVATION_RULES: DerivationRule[] = [
29
+ // Transitivity rules
30
+ {
31
+ name: 'works_on_uses_depends_on',
32
+ fromType: 'works_on',
33
+ toType: 'uses',
34
+ derivedType: 'depends_on',
35
+ description: 'If A works on X and X uses Y, then A depends on Y',
36
+ confidence: 0.8,
37
+ },
38
+ {
39
+ name: 'manages_works_oversees',
40
+ fromType: 'manages',
41
+ toType: 'works_on',
42
+ derivedType: 'oversees',
43
+ description: 'If A manages B and B works on X, then A oversees X',
44
+ confidence: 0.75,
45
+ },
46
+ {
47
+ name: 'caused_affects_may_affect',
48
+ fromType: 'caused',
49
+ toType: 'affects',
50
+ derivedType: 'may_affect',
51
+ description: 'If X caused Y and Y affects Z, then X may affect Z',
52
+ confidence: 0.7,
53
+ },
54
+ {
55
+ name: 'part_of_contains',
56
+ fromType: 'part_of',
57
+ toType: 'contains',
58
+ derivedType: 'related_to',
59
+ description: 'If A is part of X and X contains B, then A is related to B',
60
+ confidence: 0.6,
61
+ },
62
+ {
63
+ name: 'uses_depends_on',
64
+ fromType: 'uses',
65
+ toType: 'depends_on',
66
+ derivedType: 'depends_on',
67
+ description: 'If A uses X and X depends on Y, then A depends on Y',
68
+ confidence: 0.85,
69
+ },
70
+ {
71
+ name: 'created_resolved',
72
+ fromType: 'created',
73
+ toType: 'resolved',
74
+ derivedType: 'related_to',
75
+ description: 'If A created X and X was resolved by B, then A is related to B',
76
+ confidence: 0.5,
77
+ },
78
+ {
79
+ name: 'blocks_depends_on',
80
+ fromType: 'blocks',
81
+ toType: 'depends_on',
82
+ derivedType: 'blocks',
83
+ description: 'If X blocks A and A depends on Y, then X may block Y',
84
+ confidence: 0.65,
85
+ },
86
+ ];
87
+
88
+ export interface DerivedFact {
89
+ fromEntityId: string;
90
+ fromEntityName: string;
91
+ toEntityId: string;
92
+ toEntityName: string;
93
+ relationType: RelationType;
94
+ rule: string;
95
+ confidence: number;
96
+ isDerived: boolean;
97
+ }
98
+
99
+ // ─── Main Derivation Function ─────────────────────────────────────────────────
100
+
101
+ /**
102
+ * Derive implicit facts from existing relationships in the knowledge graph.
103
+ * Applies transitivity and causal rules to find new relationships.
104
+ */
105
+ export async function deriveFacts(
106
+ projectId: string,
107
+ options?: {
108
+ maxDerivations?: number;
109
+ minConfidence?: number;
110
+ storeResults?: boolean;
111
+ }
112
+ ): Promise<DerivedFact[]> {
113
+ const { maxDerivations = 50, minConfidence = 0.6, storeResults = true } = options || {};
114
+ const db = await getDb();
115
+ const schema = await getSchema();
116
+
117
+ // Get all entities for this project
118
+ const entities = await (db as any)
119
+ .select()
120
+ .from(schema.entities)
121
+ .where(eq(schema.entities.projectId, projectId));
122
+
123
+ if (entities.length < 2) return [];
124
+
125
+ const entityMap = new Map<string, any>(entities.map((e: any) => [e.id as string, e] as [string, any]));
126
+ const derivedFacts: DerivedFact[] = [];
127
+
128
+ // Get all relations for this project's entities
129
+ const entityIds = entities.map((e: any) => e.id);
130
+ const allRelations: any[] = [];
131
+
132
+ // Fetch in batches to avoid query size limits
133
+ const batchSize = 100;
134
+ for (let i = 0; i < entityIds.length; i += batchSize) {
135
+ const batch = entityIds.slice(i, i + batchSize);
136
+ const relations = await (db as any)
137
+ .select()
138
+ .from(schema.entityRelations)
139
+ .where(
140
+ or(...batch.map((id: string) => eq(schema.entityRelations.fromEntityId, id)))
141
+ );
142
+ allRelations.push(...relations);
143
+ }
144
+
145
+ // Build adjacency list for fast lookup
146
+ const outgoing = new Map<string, Map<string, { relationType: string; weight: number }>>();
147
+
148
+ for (const rel of allRelations) {
149
+ if (!outgoing.has(rel.fromEntityId)) {
150
+ outgoing.set(rel.fromEntityId, new Map());
151
+ }
152
+ outgoing.get(rel.fromEntityId)!.set(rel.toEntityId, {
153
+ relationType: rel.type,
154
+ weight: rel.weight || 1,
155
+ });
156
+ }
157
+
158
+ // Apply derivation rules
159
+ for (const rule of DERIVATION_RULES) {
160
+ if (derivedFacts.length >= maxDerivations) break;
161
+ if (rule.confidence < minConfidence) continue;
162
+
163
+ // Find all pairs where fromType matches
164
+ for (const [fromId, targets] of outgoing) {
165
+ if (derivedFacts.length >= maxDerivations) break;
166
+
167
+ for (const [midId, fromRel] of targets) {
168
+ if (fromRel.relationType !== rule.fromType) continue;
169
+
170
+ // Check if midId has outgoing toType relations
171
+ const midTargets = outgoing.get(midId);
172
+ if (!midTargets) continue;
173
+
174
+ for (const [toId, toRel] of midTargets) {
175
+ if (toRel.relationType !== rule.toType) continue;
176
+
177
+ // Found a derivation: fromId --fromType--> midId --toType--> toId
178
+ // Derive: fromId --derivedType--> toId
179
+ const fromEntity = entityMap.get(fromId);
180
+ const toEntity = entityMap.get(toId);
181
+
182
+ if (!fromEntity || !toEntity) continue;
183
+
184
+ // Check if this derived relation already exists
185
+ const existing = await (db as any)
186
+ .select()
187
+ .from(schema.entityRelations)
188
+ .where(
189
+ and(
190
+ eq(schema.entityRelations.fromEntityId, fromId),
191
+ eq(schema.entityRelations.toEntityId, toId),
192
+ eq(schema.entityRelations.type, rule.derivedType)
193
+ )
194
+ )
195
+ .limit(1);
196
+
197
+ if (existing.length > 0) continue; // Already exists
198
+
199
+ const derivedFact: DerivedFact = {
200
+ fromEntityId: fromId,
201
+ fromEntityName: fromEntity.name,
202
+ toEntityId: toId,
203
+ toEntityName: toEntity.name,
204
+ relationType: rule.derivedType as RelationType,
205
+ rule: rule.name,
206
+ confidence: rule.confidence,
207
+ isDerived: true,
208
+ };
209
+
210
+ derivedFacts.push(derivedFact);
211
+
212
+ // Store the derived fact if requested
213
+ if (storeResults) {
214
+ try {
215
+ await (db as any).insert(schema.entityRelations).values({
216
+ fromEntityId: fromId,
217
+ toEntityId: toId,
218
+ type: rule.derivedType,
219
+ weight: Math.round(rule.confidence * 10),
220
+ properties: {
221
+ derived: true,
222
+ rule: rule.name,
223
+ confidence: rule.confidence,
224
+ description: rule.description,
225
+ } as any,
226
+ });
227
+ } catch (error) {
228
+ logger.debug('Error storing derived fact', {
229
+ rule: rule.name,
230
+ from: fromEntity.name,
231
+ to: toEntity.name,
232
+ error: error as Error,
233
+ });
234
+ }
235
+ }
236
+ }
237
+ }
238
+ }
239
+ }
240
+
241
+ logger.info('Fact derivation completed', {
242
+ projectId,
243
+ derivedCount: derivedFacts.length,
244
+ rulesApplied: DERIVATION_RULES.length,
245
+ });
246
+
247
+ return derivedFacts;
248
+ }
249
+
250
+ /**
251
+ * Get all derived facts for a project.
252
+ */
253
+ export async function getDerivedFacts(projectId: string): Promise<DerivedFact[]> {
254
+ const db = await getDb();
255
+ const schema = await getSchema();
256
+
257
+ // Get all entities for this project
258
+ const entities = await (db as any)
259
+ .select()
260
+ .from(schema.entities)
261
+ .where(eq(schema.entities.projectId, projectId));
262
+
263
+ const entityIds = entities.map((e: any) => e.id);
264
+ if (entityIds.length === 0) return [];
265
+
266
+ // Get all derived relations
267
+ const derivedRelations: any[] = [];
268
+ const batchSize = 100;
269
+
270
+ for (let i = 0; i < entityIds.length; i += batchSize) {
271
+ const batch = entityIds.slice(i, i + batchSize);
272
+ const relations = await (db as any)
273
+ .select()
274
+ .from(schema.entityRelations)
275
+ .where(
276
+ or(...batch.map((id: string) => eq(schema.entityRelations.fromEntityId, id)))
277
+ );
278
+
279
+ for (const rel of relations) {
280
+ const props = rel.properties as Record<string, unknown> | null;
281
+ if (props && props.derived === true) {
282
+ const fromEntity = entities.find((e: any) => e.id === rel.fromEntityId);
283
+ const toEntity = entities.find((e: any) => e.id === rel.toEntityId);
284
+
285
+ derivedRelations.push({
286
+ fromEntityId: rel.fromEntityId,
287
+ fromEntityName: fromEntity?.name || 'Unknown',
288
+ toEntityId: rel.toEntityId,
289
+ toEntityName: toEntity?.name || 'Unknown',
290
+ relationType: rel.type as RelationType,
291
+ rule: (props.rule as string) || 'unknown',
292
+ confidence: (props.confidence as number) || 0.5,
293
+ isDerived: true,
294
+ });
295
+ }
296
+ }
297
+ }
298
+
299
+ return derivedRelations;
300
+ }
@@ -0,0 +1,120 @@
1
+ import type { RememberInput } from './memories.js';
2
+
3
+ export interface ExtractedFact {
4
+ content: string;
5
+ confidence: number;
6
+ entities: string[];
7
+ relation?: string;
8
+ }
9
+
10
+ export interface FactExtractionResult {
11
+ facts: ExtractedFact[];
12
+ summary: string;
13
+ entities: string[];
14
+ }
15
+
16
+ /**
17
+ * Extract facts from conversation text using Claude API
18
+ *
19
+ * This function MUST return valid facts or throw an error.
20
+ * NO FALLBACKS - we need real extraction to reach 90% accuracy.
21
+ */
22
+ export async function extractFacts(
23
+ text: string,
24
+ callClaude: (prompt: string, maxTokens: number) => Promise<string>
25
+ ): Promise<FactExtractionResult> {
26
+ if (!text || text.length < 50) {
27
+ // Too short for meaningful extraction - return as single fact
28
+ return {
29
+ facts: [{ content: text.trim(), confidence: 1.0, entities: [] }],
30
+ summary: text.trim(),
31
+ entities: []
32
+ };
33
+ }
34
+
35
+ const prompt = `Extract atomic facts from this conversation.
36
+
37
+ Requirements:
38
+ - Extract specific, verifiable facts (names, dates, numbers, relationships)
39
+ - Each fact should be a standalone statement
40
+ - Identify entities (people, organizations, projects, locations)
41
+ - Note temporal information and relationships
42
+
43
+ Return ONLY valid JSON in this exact format:
44
+ {"facts":[{"content":"fact statement","confidence":0.95,"entities":["Name"],"relation":"optional"}],"summary":"brief summary","entities":["all","entities"]}
45
+
46
+ Text to analyze:
47
+ ${text.substring(0, 4000)}`;
48
+
49
+ const response = await callClaude(prompt, 2000);
50
+
51
+ // Extract JSON - look for the first { and last }
52
+ const startIdx = response.indexOf('{');
53
+ const endIdx = response.lastIndexOf('}');
54
+
55
+ if (startIdx === -1 || endIdx === -1 || startIdx >= endIdx) {
56
+ throw new Error(`Fact extraction failed: No valid JSON found in response. Response: ${response.substring(0, 200)}`);
57
+ }
58
+
59
+ const jsonStr = response.substring(startIdx, endIdx + 1);
60
+
61
+ let parsed: FactExtractionResult;
62
+ try {
63
+ parsed = JSON.parse(jsonStr) as FactExtractionResult;
64
+ } catch (parseError) {
65
+ throw new Error(`Fact extraction failed: JSON parse error. JSON: ${jsonStr.substring(0, 200)}`);
66
+ }
67
+
68
+ // Validate facts array exists and has content
69
+ if (!parsed.facts || !Array.isArray(parsed.facts)) {
70
+ throw new Error(`Fact extraction failed: Missing 'facts' array in response. Keys: ${Object.keys(parsed).join(', ')}`);
71
+ }
72
+
73
+ // Filter and clean facts
74
+ const validFacts = parsed.facts
75
+ .filter((f: any) => f && typeof f.content === 'string' && f.content.trim().length > 10)
76
+ .map((f: any) => ({
77
+ content: f.content.trim(),
78
+ confidence: Math.max(0, Math.min(1, typeof f.confidence === 'number' ? f.confidence : 0.8)),
79
+ entities: Array.isArray(f.entities) ? f.entities.filter((e: any) => typeof e === 'string') : [],
80
+ relation: typeof f.relation === 'string' ? f.relation : undefined
81
+ }));
82
+
83
+ if (validFacts.length === 0) {
84
+ throw new Error(`Fact extraction failed: No valid facts after filtering. Original count: ${parsed.facts.length}`);
85
+ }
86
+
87
+ return {
88
+ facts: validFacts,
89
+ summary: typeof parsed.summary === 'string' && parsed.summary.trim()
90
+ ? parsed.summary.trim()
91
+ : text.substring(0, 200),
92
+ entities: Array.isArray(parsed.entities)
93
+ ? parsed.entities.filter((e: any) => typeof e === 'string')
94
+ : []
95
+ };
96
+ }
97
+
98
+ /**
99
+ * Convert extracted facts to memory inputs
100
+ */
101
+ export function factsToMemoryInputs(
102
+ sourceMemory: RememberInput,
103
+ extraction: FactExtractionResult,
104
+ sourceId: string
105
+ ): RememberInput[] {
106
+ return extraction.facts.map((fact, index) => ({
107
+ content: fact.content,
108
+ type: 'fact' as const,
109
+ metadata: {
110
+ sourceMemoryId: sourceId,
111
+ extractedAt: new Date().toISOString(),
112
+ entities: fact.entities,
113
+ relation: fact.relation,
114
+ confidence: Math.floor(fact.confidence * 100),
115
+ factIndex: index
116
+ },
117
+ tags: [...(sourceMemory.tags || []), 'extracted-fact', ...fact.entities],
118
+ project: sourceMemory.project
119
+ }));
120
+ }
@@ -0,0 +1,200 @@
1
+ /** Feedback Tracker - Track memory usage in responses for Echo/Fizzle loop */
2
+
3
+ import { logger } from '../logger.js';
4
+ import { config } from '../../config.js';
5
+ import { getDb } from '../../db/index.js';
6
+ import { memoryFeedback, memories, type MemoryFeedback } from '../../db/drizzle/schema-sqlite.js';
7
+ import { eq, and } from 'drizzle-orm';
8
+ import { analyzeResponseForMemoryReferences, mightContainMemoryReferences } from './response-analyzer.js';
9
+
10
+ interface InjectionRecord {
11
+ memoryIds: string[];
12
+ memoryContent: Map<string, string>;
13
+ injectedAt: Date;
14
+ }
15
+
16
+ const injectionTracker = new Map<string, InjectionRecord>();
17
+
18
+ export async function recordInjection(
19
+ sessionId: string,
20
+ memoryIds: string[],
21
+ memoryContent: Map<string, string>
22
+ ): Promise<void> {
23
+ if (!config.feedbackTrackingEnabled) return;
24
+
25
+ injectionTracker.set(sessionId, {
26
+ memoryIds,
27
+ memoryContent,
28
+ injectedAt: new Date(),
29
+ });
30
+
31
+ const db = await getDb();
32
+ if (!db) return;
33
+
34
+ try {
35
+ const now = new Date();
36
+ const sqliteDb = db as any;
37
+ for (const memoryId of memoryIds) {
38
+ await sqliteDb.insert(memoryFeedback).values({
39
+ memoryId,
40
+ sessionId,
41
+ wasInjected: true,
42
+ wasReferenced: false,
43
+ referenceCount: 0,
44
+ retrievalPriorityDelta: 0,
45
+ injectedAt: now,
46
+ }).onConflictDoNothing();
47
+ }
48
+ logger.debug(`[FeedbackTracker] Recorded injection of ${memoryIds.length} memories for session ${sessionId}`);
49
+ } catch (error) {
50
+ logger.error('[FeedbackTracker] Failed to record injection:', error);
51
+ }
52
+ }
53
+
54
+ export async function analyzeAndRecordFeedback(
55
+ sessionId: string,
56
+ responseText: string
57
+ ): Promise<void> {
58
+ if (!config.feedbackTrackingEnabled) return;
59
+
60
+ const injection = injectionTracker.get(sessionId);
61
+ if (!injection) {
62
+ logger.debug(`[FeedbackTracker] No injection record for session ${sessionId}`);
63
+ return;
64
+ }
65
+
66
+ if (!mightContainMemoryReferences(responseText)) {
67
+ await applyFizzlePenalty(injection.memoryIds);
68
+ injectionTracker.delete(sessionId);
69
+ return;
70
+ }
71
+
72
+ const analysis = analyzeResponseForMemoryReferences(
73
+ responseText,
74
+ injection.memoryIds,
75
+ injection.memoryContent
76
+ );
77
+
78
+ const db = await getDb();
79
+ if (!db) return;
80
+
81
+ try {
82
+ const now = new Date();
83
+ const sqliteDb = db as any;
84
+
85
+ for (const memoryId of injection.memoryIds) {
86
+ const wasReferenced = analysis.referencedMemoryIds.includes(memoryId);
87
+ const delta = wasReferenced ? config.feedbackEchoBonus : -config.feedbackFizzlePenalty;
88
+
89
+ const existing = await sqliteDb
90
+ .select()
91
+ .from(memoryFeedback)
92
+ .where(and(
93
+ eq(memoryFeedback.memoryId, memoryId),
94
+ eq(memoryFeedback.sessionId, sessionId)
95
+ ))
96
+ .limit(1);
97
+
98
+ if (existing.length > 0) {
99
+ await sqliteDb
100
+ .update(memoryFeedback)
101
+ .set({
102
+ wasReferenced,
103
+ referenceCount: wasReferenced ? 1 : 0,
104
+ retrievalPriorityDelta: delta,
105
+ referencedAt: wasReferenced ? now : null,
106
+ })
107
+ .where(eq(memoryFeedback.id, existing[0].id));
108
+ }
109
+
110
+ await updateRetrievalPriority(memoryId, delta);
111
+ }
112
+
113
+ logger.info(
114
+ `[FeedbackTracker] Feedback recorded: ${analysis.referenceCount} echoes, ${injection.memoryIds.length - analysis.referenceCount} fizzles`
115
+ );
116
+
117
+ injectionTracker.delete(sessionId);
118
+ } catch (error) {
119
+ logger.error('[FeedbackTracker] Failed to record feedback:', error);
120
+ }
121
+ }
122
+
123
+ async function applyFizzlePenalty(memoryIds: string[]): Promise<void> {
124
+ try {
125
+ for (const memoryId of memoryIds) {
126
+ await updateRetrievalPriority(memoryId, -config.feedbackFizzlePenalty);
127
+ }
128
+ logger.debug(`[FeedbackTracker] Applied fizzle penalty to ${memoryIds.length} memories`);
129
+ } catch (error) {
130
+ logger.error('[FeedbackTracker] Failed to apply fizzle penalty:', error);
131
+ }
132
+ }
133
+
134
+ export async function updateRetrievalPriority(memoryId: string, delta: number): Promise<void> {
135
+ const db = await getDb();
136
+ if (!db) return;
137
+
138
+ try {
139
+ const sqliteDb = db as any;
140
+ const [memory] = await sqliteDb
141
+ .select({ retrievalPriority: memories.retrievalPriority })
142
+ .from(memories)
143
+ .where(eq(memories.id, memoryId))
144
+ .limit(1);
145
+
146
+ if (!memory) return;
147
+
148
+ const currentPriority = memory.retrievalPriority ?? 50;
149
+ const newPriority = Math.max(0, Math.min(100, currentPriority + delta));
150
+
151
+ await sqliteDb
152
+ .update(memories)
153
+ .set({ retrievalPriority: newPriority })
154
+ .where(eq(memories.id, memoryId));
155
+
156
+ logger.debug(`[FeedbackTracker] Updated priority for ${memoryId}: ${currentPriority} -> ${newPriority}`);
157
+ } catch (error) {
158
+ logger.error('[FeedbackTracker] Failed to update retrieval priority:', error);
159
+ }
160
+ }
161
+
162
+ export async function getMemoryFeedbackStats(memoryId: string): Promise<{
163
+ totalInjections: number;
164
+ totalReferences: number;
165
+ echoRate: number;
166
+ averagePriorityDelta: number;
167
+ }> {
168
+ const db = await getDb();
169
+ if (!db) {
170
+ return { totalInjections: 0, totalReferences: 0, echoRate: 0, averagePriorityDelta: 0 };
171
+ }
172
+
173
+ try {
174
+ const sqliteDb = db as any;
175
+ const records = await sqliteDb
176
+ .select()
177
+ .from(memoryFeedback)
178
+ .where(eq(memoryFeedback.memoryId, memoryId));
179
+
180
+ const totalInjections = records.filter((r: MemoryFeedback) => r.wasInjected).length;
181
+ const totalReferences = records.filter((r: MemoryFeedback) => r.wasReferenced).length;
182
+ const echoRate = totalInjections > 0 ? totalReferences / totalInjections : 0;
183
+ const totalDelta = records.reduce((sum: number, r: MemoryFeedback) => sum + (r.retrievalPriorityDelta ?? 0), 0);
184
+ const averagePriorityDelta = records.length > 0 ? totalDelta / records.length : 0;
185
+
186
+ return { totalInjections, totalReferences, echoRate, averagePriorityDelta };
187
+ } catch (error) {
188
+ logger.error('[FeedbackTracker] Failed to get feedback stats:', error);
189
+ return { totalInjections: 0, totalReferences: 0, echoRate: 0, averagePriorityDelta: 0 };
190
+ }
191
+ }
192
+
193
+ export function cleanupInjectionTracker(maxAgeMs: number = 3600000): void {
194
+ const now = Date.now();
195
+ for (const [sessionId, injection] of injectionTracker.entries()) {
196
+ if (now - injection.injectedAt.getTime() > maxAgeMs) {
197
+ injectionTracker.delete(sessionId);
198
+ }
199
+ }
200
+ }