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,426 @@
1
+ /**
2
+ * Entity Extractor
3
+ * Extracts named entities from memory content
4
+ * Supports people, files, functions, dates, locations, concepts, tools, and patterns
5
+ */
6
+
7
+ import { getDb } from '../../db/index.js';
8
+ import { getSchema } from '../../db/schema.js';
9
+ import { eq, and } from 'drizzle-orm';
10
+ import { logger } from '../../core/logger.js';
11
+
12
+ export type EntityType =
13
+ | 'person'
14
+ | 'file'
15
+ | 'function'
16
+ | 'class'
17
+ | 'concept'
18
+ | 'tool'
19
+ | 'date'
20
+ | 'location'
21
+ | 'pattern'
22
+ | 'technique'
23
+ | 'other';
24
+
25
+ export interface ExtractedEntity {
26
+ name: string;
27
+ type: EntityType;
28
+ confidence: number; // 0-1
29
+ startIndex: number;
30
+ endIndex: number;
31
+ context: string;
32
+ normalized?: string;
33
+ }
34
+
35
+ // Regex patterns for entity detection
36
+ const PATTERNS = {
37
+ // File paths: src/components/Button.tsx
38
+ filePath: /(?:^|[^\w])(?:\.?\/[\w.-]*[\w.-]*(?:\/[\w.-]+)*|[\w.-]+\.(?:ts|tsx|js|jsx|py|rb|go|java|cpp|c|h|json|yaml|yml|env|md|txt|csv|sql|graphql))\b/gm,
39
+
40
+ // Functions/methods
41
+ functionCall: /\b([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(?=\()/g,
42
+
43
+ // Classes
44
+ className: /\b(?:class|new|extends|implements)\s+([A-Z][a-zA-Z0-9_$]*)\b/g,
45
+
46
+ // Common names
47
+ personName: /(?:^|[^.\w])\b([A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)\b(?![^.\w])/g,
48
+
49
+ // Capitalized concepts
50
+ concept: /\b(?:[A-Z][a-z]+\s+)+(?:System|Architecture|Pattern|Model|Algorithm|Framework|Library|Process|Concept|Method)\b/g,
51
+
52
+ // Tools
53
+ tool: /\b(?:React|Vue|Angular|Node\.?js?|Express|Django|Flask|FastAPI|PostgreSQL|MongoDB|Redis|Docker|Kubernetes)\b/g,
54
+
55
+ // Design patterns
56
+ designPattern: /\b(?:abstract\s+)?(?:factory|singleton|observer|decorator|strategy|adapter)\s+(?:pattern|method)\b/gi,
57
+
58
+ // Techniques
59
+ technique: /\b(?:memoization|caching|lazy\s+loading|debouncing|throttling)\b/gi,
60
+
61
+ // ISO dates
62
+ date: /\b(\d{4}-\d{2}-\d{2})(?:T\d{2}:\d{2}:\d{2})?\b/g,
63
+ };
64
+
65
+ /**
66
+ * Extract unique entity names for auto-linking
67
+ */
68
+ export function extractEntityNames(content: string): string[] {
69
+ const names = new Set<string>();
70
+
71
+ // Extract person names
72
+ const namePattern = /(?:^|[^.\w])\b([A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)\b(?![^.\w])/g;
73
+ let match;
74
+ while ((match = namePattern.exec(content)) !== null) {
75
+ names.add(match[1].toLowerCase());
76
+ }
77
+
78
+ // Extract capitalized concepts
79
+ const conceptPattern = /\b[A-Z][a-z]+(?:\s+[A-Z][a-z]+)+\b/g;
80
+ while ((match = conceptPattern.exec(content)) !== null) {
81
+ names.add(match[0].toLowerCase());
82
+ }
83
+
84
+ return Array.from(names).slice(0, 10);
85
+ }
86
+
87
+ /**
88
+ * Extract entities from content
89
+ */
90
+ export async function extractEntities(content: string): Promise<ExtractedEntity[]> {
91
+ const entities: ExtractedEntity[] = [];
92
+ const seenKeys = new Set<string>(); // Deduplicate entities
93
+
94
+ // Extract file paths
95
+ const filePaths = Array.from(content.matchAll(PATTERNS.filePath));
96
+ for (const match of filePaths) {
97
+ const name = match[0].trim();
98
+ const key = `file:${name}`;
99
+ if (!seenKeys.has(key)) {
100
+ entities.push({
101
+ name,
102
+ type: 'file',
103
+ confidence: 0.9,
104
+ startIndex: match.index || 0,
105
+ endIndex: (match.index || 0) + match[0].length,
106
+ context: extractContext(content, match.index || 0),
107
+ normalized: normalizePath(name),
108
+ });
109
+ seenKeys.add(key);
110
+ }
111
+ }
112
+
113
+ // Extract function calls
114
+ const functionCalls = Array.from(content.matchAll(PATTERNS.functionCall));
115
+ for (const match of functionCalls) {
116
+ const name = match[1];
117
+ const key = `function:${name}`;
118
+ if (!seenKeys.has(key) && name.length > 2) {
119
+ entities.push({
120
+ name,
121
+ type: 'function',
122
+ confidence: 0.85,
123
+ startIndex: match.index || 0,
124
+ endIndex: (match.index || 0) + match[0].length,
125
+ context: extractContext(content, match.index || 0),
126
+ });
127
+ seenKeys.add(key);
128
+ }
129
+ }
130
+
131
+ // Extract class names
132
+ const classNames = Array.from(content.matchAll(PATTERNS.className));
133
+ for (const match of classNames) {
134
+ const name = match[1];
135
+ const key = `class:${name}`;
136
+ if (!seenKeys.has(key)) {
137
+ entities.push({
138
+ name,
139
+ type: 'class',
140
+ confidence: 0.95,
141
+ startIndex: match.index || 0,
142
+ endIndex: (match.index || 0) + match[0].length,
143
+ context: extractContext(content, match.index || 0),
144
+ });
145
+ seenKeys.add(key);
146
+ }
147
+ }
148
+
149
+ // Extract technologies/tools
150
+ const tools = Array.from(content.matchAll(PATTERNS.tool));
151
+ for (const match of tools) {
152
+ const name = match[0];
153
+ const key = `tool:${name}`;
154
+ if (!seenKeys.has(key)) {
155
+ entities.push({
156
+ name,
157
+ type: 'tool',
158
+ confidence: 0.9,
159
+ startIndex: match.index || 0,
160
+ endIndex: (match.index || 0) + match[0].length,
161
+ context: extractContext(content, match.index || 0),
162
+ });
163
+ seenKeys.add(key);
164
+ }
165
+ }
166
+
167
+ // Extract design patterns
168
+ const patterns = Array.from(content.matchAll(PATTERNS.designPattern));
169
+ for (const match of patterns) {
170
+ const name = match[0];
171
+ const key = `pattern:${name}`;
172
+ if (!seenKeys.has(key)) {
173
+ entities.push({
174
+ name,
175
+ type: 'pattern',
176
+ confidence: 0.92,
177
+ startIndex: match.index || 0,
178
+ endIndex: (match.index || 0) + match[0].length,
179
+ context: extractContext(content, match.index || 0),
180
+ });
181
+ seenKeys.add(key);
182
+ }
183
+ }
184
+
185
+ // Extract techniques/methodologies
186
+ const techniques = Array.from(content.matchAll(PATTERNS.technique));
187
+ for (const match of techniques) {
188
+ const name = match[0];
189
+ const key = `technique:${name}`;
190
+ if (!seenKeys.has(key)) {
191
+ entities.push({
192
+ name,
193
+ type: 'technique',
194
+ confidence: 0.88,
195
+ startIndex: match.index || 0,
196
+ endIndex: (match.index || 0) + match[0].length,
197
+ context: extractContext(content, match.index || 0),
198
+ });
199
+ seenKeys.add(key);
200
+ }
201
+ }
202
+
203
+ // Extract dates
204
+ const dates = Array.from(content.matchAll(PATTERNS.date));
205
+ for (const match of dates) {
206
+ const name = match[0];
207
+ const key = `date:${name}`;
208
+ if (!seenKeys.has(key)) {
209
+ entities.push({
210
+ name,
211
+ type: 'date',
212
+ confidence: 0.95,
213
+ startIndex: match.index || 0,
214
+ endIndex: (match.index || 0) + match[0].length,
215
+ context: extractContext(content, match.index || 0),
216
+ });
217
+ seenKeys.add(key);
218
+ }
219
+ }
220
+
221
+ // Extract quoted important concepts
222
+ const quotedConcepts = Array.from(content.matchAll(PATTERNS.quotedConcept));
223
+ for (const match of quotedConcepts) {
224
+ const name = match[1];
225
+ const key = `concept:${name}`;
226
+ if (!seenKeys.has(key) && name.length > 2) {
227
+ entities.push({
228
+ name,
229
+ type: 'concept',
230
+ confidence: 0.8,
231
+ startIndex: match.index || 0,
232
+ endIndex: (match.index || 0) + match[0].length,
233
+ context: extractContext(content, match.index || 0),
234
+ });
235
+ seenKeys.add(key);
236
+ }
237
+ }
238
+
239
+ // Extract capitalized concepts
240
+ const concepts = Array.from(content.matchAll(PATTERNS.concept));
241
+ for (const match of concepts) {
242
+ const name = match[0];
243
+ const key = `concept:${name}`;
244
+ if (!seenKeys.has(key)) {
245
+ entities.push({
246
+ name,
247
+ type: 'concept',
248
+ confidence: 0.75,
249
+ startIndex: match.index || 0,
250
+ endIndex: (match.index || 0) + match[0].length,
251
+ context: extractContext(content, match.index || 0),
252
+ });
253
+ seenKeys.add(key);
254
+ }
255
+ }
256
+
257
+ // Sort by start index
258
+ entities.sort((a, b) => a.startIndex - b.startIndex);
259
+
260
+ logger.debug('Entities extracted', {
261
+ count: entities.length,
262
+ byType: countByType(entities),
263
+ });
264
+
265
+ return entities;
266
+ }
267
+
268
+ /**
269
+ * Link extracted entities to memory records
270
+ * Creates entity records in the knowledge graph
271
+ */
272
+ export async function linkEntitiesToMemories(
273
+ memoryId: string,
274
+ entities: ExtractedEntity[]
275
+ ): Promise<void> {
276
+ if (entities.length === 0) return;
277
+
278
+ try {
279
+ const db = await getDb();
280
+ const schema = await getSchema();
281
+
282
+ // Get memory to find project
283
+ const memories = await (db as any)
284
+ .select()
285
+ .from(schema.memories)
286
+ .where(eq(schema.memories.id, memoryId))
287
+ .limit(1);
288
+
289
+ if (memories.length === 0) return;
290
+ const memory = memories[0];
291
+
292
+ // Insert unique entities into the knowledge graph
293
+ for (const entity of entities) {
294
+ try {
295
+ // Check if entity already exists
296
+ const existing = await (db as any)
297
+ .select()
298
+ .from(schema.entities)
299
+ .where(
300
+ and(
301
+ eq(schema.entities.projectId, memory.projectId),
302
+ eq(schema.entities.name, entity.name),
303
+ eq(schema.entities.type, entity.type)
304
+ )
305
+ )
306
+ .limit(1);
307
+
308
+ if (existing.length === 0) {
309
+ // Insert new entity with metadata in properties
310
+ await (db as any).insert(schema.entities).values({
311
+ name: entity.name,
312
+ type: entity.type,
313
+ projectId: memory.projectId,
314
+ description: entity.context,
315
+ properties: {
316
+ confidence: entity.confidence,
317
+ extractedFrom: memoryId,
318
+ normalized: entity.normalized,
319
+ },
320
+ });
321
+ }
322
+ } catch (error) {
323
+ logger.error('Error inserting entity', { entity, error });
324
+ }
325
+ }
326
+
327
+ logger.debug('Entities linked to memory', {
328
+ memoryId,
329
+ entityCount: entities.length,
330
+ });
331
+ } catch (error) {
332
+ logger.error('Error linking entities to memories', error);
333
+ }
334
+ }
335
+
336
+ /**
337
+ * Get entities extracted from a memory based on properties
338
+ */
339
+ export async function getMemoryEntities(memoryId: string): Promise<ExtractedEntity[]> {
340
+ try {
341
+ const db = await getDb();
342
+ const schema = await getSchema();
343
+
344
+ // Find all entities with this memory ID in properties
345
+ const allEntities = await (db as any).select().from(schema.entities);
346
+
347
+ const entities: ExtractedEntity[] = [];
348
+
349
+ for (const entity of allEntities) {
350
+ const props = entity.properties as Record<string, unknown>;
351
+ if (props && props.extractedFrom === memoryId) {
352
+ entities.push({
353
+ name: entity.name,
354
+ type: entity.type as EntityType,
355
+ confidence: (props.confidence as number) || 0.8,
356
+ startIndex: 0,
357
+ endIndex: 0,
358
+ context: entity.description || '',
359
+ normalized: props.normalized as string | undefined,
360
+ });
361
+ }
362
+ }
363
+
364
+ return entities;
365
+ } catch (error) {
366
+ logger.error('Error getting memory entities', error);
367
+ return [];
368
+ }
369
+ }
370
+
371
+ /**
372
+ * Get all entities for a project
373
+ */
374
+ export async function getProjectEntities(
375
+ projectId: string,
376
+ type?: EntityType
377
+ ): Promise<any[]> {
378
+ try {
379
+ const db = await getDb();
380
+ const schema = await getSchema();
381
+
382
+ let query: any = (db as any).select().from(schema.entities).where(eq(schema.entities.projectId, projectId));
383
+
384
+ if (type) {
385
+ query = query.where(eq(schema.entities.type, type));
386
+ }
387
+
388
+ return await query;
389
+ } catch (error) {
390
+ logger.error('Error getting project entities', error);
391
+ return [];
392
+ }
393
+ }
394
+
395
+ /**
396
+ * Extract context around entity
397
+ */
398
+ function extractContext(content: string, index: number, contextLength: number = 50): string {
399
+ const start = Math.max(0, index - contextLength);
400
+ const end = Math.min(content.length, index + contextLength);
401
+ return content.substring(start, end).trim();
402
+ }
403
+
404
+ /**
405
+ * Normalize file path
406
+ */
407
+ function normalizePath(path: string): string {
408
+ return path
409
+ .trim()
410
+ .replace(/^\.\//, '')
411
+ .toLowerCase()
412
+ .replace(/\\/g, '/');
413
+ }
414
+
415
+ /**
416
+ * Count entities by type
417
+ */
418
+ function countByType(entities: ExtractedEntity[]): Record<EntityType, number> {
419
+ const counts = {} as Record<EntityType, number>;
420
+
421
+ for (const entity of entities) {
422
+ counts[entity.type] = (counts[entity.type] || 0) + 1;
423
+ }
424
+
425
+ return counts;
426
+ }
@@ -0,0 +1,89 @@
1
+ export interface ExtractedEntities {
2
+ primary: string[]; // Main entities (people, projects)
3
+ secondary: string[]; // Supporting entities
4
+ queryType: 'factual' | 'relational' | 'temporal';
5
+ }
6
+
7
+ /**
8
+ * Extract entities from a query using Claude
9
+ * NO FALLBACKS - real extraction or throw
10
+ */
11
+ export async function extractQueryEntities(
12
+ query: string,
13
+ callClaudeFn: (prompt: string, maxTokens: number) => Promise<string>
14
+ ): Promise<ExtractedEntities> {
15
+ const prompt = `Extract entities from this question. Return ONLY JSON:
16
+ {
17
+ "primary": ["Alice", "project name"],
18
+ "secondary": ["team", "budget"],
19
+ "queryType": "factual"
20
+ }
21
+
22
+ Question: ${query}`;
23
+
24
+ const response = await callClaudeFn(prompt, 500);
25
+
26
+ const jsonMatch = response.match(/\{[\s\S]*\}/);
27
+ if (!jsonMatch) {
28
+ throw new Error('No JSON in entity extraction');
29
+ }
30
+
31
+ const parsed = JSON.parse(jsonMatch[0]) as ExtractedEntities;
32
+
33
+ return {
34
+ primary: parsed.primary || [],
35
+ secondary: parsed.secondary || [],
36
+ queryType: parsed.queryType || 'factual',
37
+ };
38
+ }
39
+
40
+ /**
41
+ * Score memory relevance based on entity matching
42
+ * Returns boost factor (0-1)
43
+ */
44
+ export function scoreEntityMatch(
45
+ memoryEntities: string[],
46
+ queryEntities: string[]
47
+ ): number {
48
+ if (!queryEntities.length || !memoryEntities.length) {
49
+ return 0.5; // Neutral if no entities
50
+ }
51
+
52
+ const querySet = new Set(queryEntities.map(e => e.toLowerCase()));
53
+ const memorySet = new Set(memoryEntities.map(e => e.toLowerCase()));
54
+
55
+ // Count matches
56
+ let matches = 0;
57
+ for (const entity of querySet) {
58
+ if (memorySet.has(entity)) {
59
+ matches++;
60
+ }
61
+ }
62
+
63
+ // Calculate boost (0-1)
64
+ const matchRatio = matches / querySet.size;
65
+ return 0.5 + (matchRatio * 0.5); // 0.5 to 1.0
66
+ }
67
+
68
+ /**
69
+ * Filter and boost memories by entity relevance
70
+ */
71
+ export function filterByEntities(
72
+ memories: any[],
73
+ queryEntities: string[]
74
+ ): Array<{ memory: any; entityBoost: number }> {
75
+ if (!queryEntities.length) {
76
+ // No entities to filter by, return all with neutral boost
77
+ return memories.map(m => ({ memory: m, entityBoost: 0.5 }));
78
+ }
79
+
80
+ return memories.map(memory => {
81
+ const memoryEntities = (memory.metadata?.entities as string[]) || [];
82
+ const boost = scoreEntityMatch(memoryEntities, queryEntities);
83
+
84
+ return {
85
+ memory,
86
+ entityBoost: boost,
87
+ };
88
+ });
89
+ }
@@ -0,0 +1,112 @@
1
+ import { eq } from 'drizzle-orm';
2
+ import { getDbClient } from '../lib/db-client.js';
3
+ import { deserializeMetadata } from './serialization.js';
4
+ import { getMemorySnapshot } from '../snapshots/retrieval.js';
5
+ import { getMemoryPlace } from '../places/memory-places.js';
6
+ import { getPlace } from '../places/places.js';
7
+ import { getBeliefsForMemory } from '../beliefs/store.js';
8
+ import type { StoredBelief } from '../beliefs/types.js';
9
+
10
+ export interface MemoryInspection {
11
+ id: string;
12
+ type: string;
13
+ classification: string;
14
+ reasons: string[];
15
+ rawFallbackSnapshotId?: string | null;
16
+ nuanceSuppressed: boolean;
17
+ place?: string | null;
18
+ placeType?: string | null;
19
+ graphStatus?: string | null;
20
+ content: string;
21
+ legacyMetadata: boolean;
22
+ beliefs?: StoredBelief[];
23
+ }
24
+
25
+ export function summarizeInspection(input: MemoryInspection): string {
26
+ const lines = [
27
+ `Memory ${input.id}`,
28
+ `Type: ${input.type}`,
29
+ `Classification: ${input.classification}`,
30
+ `Reasons: ${input.reasons.join('; ') || 'n/a'}`,
31
+ `Raw fallback: ${input.rawFallbackSnapshotId ?? 'none'}`,
32
+ `nuance suppressed: ${input.nuanceSuppressed ? 'yes' : 'no'}`,
33
+ `Place: ${input.place ?? 'none'}${input.placeType ? ` (${input.placeType})` : ''}`,
34
+ `Graph: ${input.graphStatus ?? 'none'}`,
35
+ `Content: ${input.content}`,
36
+ `Legacy metadata: ${input.legacyMetadata ? 'yes' : 'no'}`,
37
+ ];
38
+ if (input.beliefs && input.beliefs.length > 0) {
39
+ lines.push('Beliefs:');
40
+ for (const belief of input.beliefs) {
41
+ const confidence = typeof belief.confidence === 'number' ? belief.confidence.toFixed(1) : '?';
42
+ const sourceCount = belief.sourceMemoryIds?.length ?? 1;
43
+ const origin = sourceCount > 1 ? `derived from ${sourceCount} memories` : 'derived from 1 memory';
44
+ const evidence = belief.evidenceSummary
45
+ ? `\n Evidence: ${belief.evidenceSummary.slice(0, 100)}${belief.evidenceSummary.length > 100 ? '...' : ''}`
46
+ : '';
47
+ lines.push(`- [${belief.type}] ${belief.statement}`);
48
+ lines.push(` Status: ${belief.status}, Confidence: ${confidence}/100, ${origin}${evidence}`);
49
+ if (belief.status === 'superseded') {
50
+ lines.push(` Note: This belief supersedes a previous version`);
51
+ }
52
+ if (belief.status === 'disputed') {
53
+ lines.push(` Warning: This belief has been disputed`);
54
+ }
55
+ }
56
+ } else {
57
+ lines.push(`Beliefs: ${input.legacyMetadata ? 'No derived beliefs available for this legacy record' : 'none derived'}`);
58
+ }
59
+ return lines.join('\n');
60
+ }
61
+
62
+ export async function explainMemory(id: string): Promise<MemoryInspection | null> {
63
+ const { db, schema } = await getDbClient();
64
+ const rows = await db.select().from(schema.memories).where(eq(schema.memories.id, id)).limit(1);
65
+ const row = rows[0];
66
+ if (!row) return null;
67
+
68
+ const metadata = deserializeMetadata(row.metadata ?? null) as Record<string, unknown> | null;
69
+ const rawClassification = metadata?.signal?.classification ?? metadata?.classification ?? null;
70
+ const classification = typeof rawClassification === 'string' && rawClassification.trim().length > 0
71
+ ? rawClassification
72
+ : 'legacy-durable';
73
+ const reasons = Array.isArray(metadata?.signal?.reasons)
74
+ ? (metadata?.signal?.reasons as string[])
75
+ : Array.isArray(metadata?.reasons)
76
+ ? (metadata?.reasons as string[])
77
+ : ['This record predates signal tracking, so detailed ingestion metadata is unavailable.'];
78
+ const rawFallbackSnapshotId = typeof metadata?.rawFallbackSnapshotId === 'string'
79
+ ? metadata.rawFallbackSnapshotId
80
+ : null;
81
+ const nuanceSuppressed = Boolean(metadata?.signal?.nuanceSuppressed ?? metadata?.nuanceSuppressed);
82
+ const graphStatus =
83
+ typeof metadata?.graphStatus === 'string'
84
+ ? metadata.graphStatus
85
+ : typeof metadata?.graph === 'object' && metadata.graph
86
+ ? JSON.stringify(metadata.graph)
87
+ : 'Unavailable for this legacy record';
88
+ const legacyMetadata = rawClassification == null;
89
+
90
+ const placeId = await getMemoryPlace(id);
91
+ const place = placeId ? await getPlace(placeId) : null;
92
+
93
+ if (rawFallbackSnapshotId) {
94
+ await getMemorySnapshot(rawFallbackSnapshotId);
95
+ }
96
+ const beliefs = await getBeliefsForMemory(id);
97
+
98
+ return {
99
+ id: row.id,
100
+ type: row.type,
101
+ classification,
102
+ reasons,
103
+ rawFallbackSnapshotId,
104
+ nuanceSuppressed,
105
+ place: place?.name ?? null,
106
+ placeType: place?.placeType ?? null,
107
+ graphStatus,
108
+ content: row.content,
109
+ legacyMetadata,
110
+ beliefs,
111
+ };
112
+ }