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
@@ -1,6 +1,7 @@
1
1
  import { existsSync, mkdirSync } from 'fs';
2
2
  import { logger } from '../core/logger.js';
3
3
  import { getDataDir } from '../config.js';
4
+ import { runAllMigrations } from './migrations/index.js';
4
5
  /**
5
6
  * Note on boolean columns:
6
7
  * SQLite uses INTEGER 0/1 for boolean values (no native boolean type)
@@ -9,6 +10,30 @@ import { getDataDir } from '../config.js';
9
10
  const sqliteSchemaSql = `
10
11
  PRAGMA foreign_keys = ON;
11
12
 
13
+ -- Schema version tracking table (v1.2.0+)
14
+ CREATE TABLE IF NOT EXISTS _schema_versions (
15
+ version TEXT PRIMARY KEY,
16
+ description TEXT NOT NULL,
17
+ applied_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
18
+ );
19
+
20
+ -- Agent preferences table (v1.2.0+) - stores accumulated agent preferences from learnings
21
+ CREATE TABLE IF NOT EXISTS agent_preferences (
22
+ id TEXT PRIMARY KEY,
23
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
24
+ key TEXT NOT NULL,
25
+ value TEXT NOT NULL,
26
+ source_memory_id TEXT,
27
+ confidence REAL DEFAULT 0.5,
28
+ usage_count INTEGER DEFAULT 1,
29
+ last_updated INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
30
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
31
+ UNIQUE(project_id, key)
32
+ );
33
+
34
+ CREATE INDEX IF NOT EXISTS agent_preferences_project_idx ON agent_preferences(project_id);
35
+ CREATE INDEX IF NOT EXISTS agent_preferences_key_idx ON agent_preferences(key);
36
+
12
37
  CREATE TABLE IF NOT EXISTS users (
13
38
  id TEXT PRIMARY KEY,
14
39
  external_id TEXT UNIQUE,
@@ -55,22 +80,33 @@ CREATE TABLE IF NOT EXISTS memories (
55
80
  is_merged INTEGER DEFAULT 0,
56
81
  merged_into_id TEXT,
57
82
  merged_at INTEGER,
58
- is_canonical INTEGER DEFAULT 0,
59
- merge_source_ids TEXT,
60
- is_mergeable INTEGER DEFAULT 1,
61
- merge_version INTEGER DEFAULT 1,
62
- importance_score INTEGER DEFAULT 50,
63
- importance_decay_rate INTEGER DEFAULT 30,
64
- last_importance_recalc INTEGER,
65
- consolidated_into TEXT,
66
- consolidated_at INTEGER,
67
- is_consolidated INTEGER DEFAULT 0,
68
- sector TEXT DEFAULT 'episodic',
69
- tier TEXT DEFAULT 'hot',
70
- context_status TEXT DEFAULT 'out-of-context',
71
- decay_rate INTEGER DEFAULT 30,
72
- coactivation_score INTEGER DEFAULT 0,
73
- last_decay_at INTEGER DEFAULT (strftime('%s','now')),
83
+ is_canonical INTEGER DEFAULT 0,
84
+ merge_source_ids TEXT,
85
+ is_mergeable INTEGER DEFAULT 1,
86
+ merge_version INTEGER DEFAULT 1,
87
+ namespace_id TEXT REFERENCES namespaces(id) ON DELETE SET NULL,
88
+ namespace_path TEXT,
89
+ has_l0_abstract INTEGER DEFAULT 0,
90
+ has_l1_overview INTEGER DEFAULT 0,
91
+ last_layer_update INTEGER,
92
+ importance_score INTEGER DEFAULT 50,
93
+ importance_decay_rate INTEGER DEFAULT 30,
94
+ last_importance_recalc INTEGER,
95
+ retrieval_priority INTEGER DEFAULT 50,
96
+ tokens_estimate INTEGER DEFAULT 0,
97
+ consolidated_into TEXT,
98
+ consolidated_at INTEGER,
99
+ is_consolidated INTEGER DEFAULT 0,
100
+ sector TEXT DEFAULT 'episodic',
101
+ tier TEXT DEFAULT 'hot',
102
+ status TEXT DEFAULT 'active',
103
+ encrypted_content TEXT,
104
+ encryption_nonce TEXT,
105
+ is_encrypted INTEGER DEFAULT 0,
106
+ context_status TEXT DEFAULT 'out-of-context',
107
+ decay_rate INTEGER DEFAULT 30,
108
+ coactivation_score INTEGER DEFAULT 0,
109
+ last_decay_at INTEGER DEFAULT (strftime('%s','now')),
74
110
  agent_id TEXT,
75
111
  agent_role TEXT,
76
112
  visibility_scope TEXT DEFAULT 'private',
@@ -82,11 +118,14 @@ CREATE TABLE IF NOT EXISTS memories (
82
118
  triggered_by TEXT,
83
119
  capture_reason TEXT,
84
120
  last_used_at INTEGER,
85
- usage_count INTEGER DEFAULT 0,
86
- valid_from INTEGER,
87
- valid_to INTEGER,
88
- superseded_by TEXT,
89
- version INTEGER DEFAULT 1,
121
+ usage_count INTEGER DEFAULT 0,
122
+ valid_from INTEGER,
123
+ valid_to INTEGER,
124
+ recorded_at INTEGER DEFAULT (strftime('%s','now')),
125
+ superseded_by TEXT,
126
+ version INTEGER DEFAULT 1,
127
+ place_id TEXT,
128
+ place_sort_order INTEGER DEFAULT 0,
90
129
  created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
91
130
  updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
92
131
  );
@@ -168,6 +207,7 @@ CREATE TABLE IF NOT EXISTS learnings (
168
207
  relevance_score INTEGER DEFAULT 50,
169
208
  category TEXT,
170
209
  importance INTEGER DEFAULT 50,
210
+ confidence INTEGER DEFAULT 50,
171
211
  metadata TEXT,
172
212
  is_imported INTEGER DEFAULT 0,
173
213
  -- UAM: Agent integration columns
@@ -180,7 +220,7 @@ CREATE TABLE IF NOT EXISTS learnings (
180
220
  CREATE INDEX IF NOT EXISTS learnings_project_idx ON learnings(project_id);
181
221
  CREATE INDEX IF NOT EXISTS learnings_type_idx ON learnings(type);
182
222
  CREATE INDEX IF NOT EXISTS learnings_action_idx ON learnings(action);
183
- CREATE INDEX IF NOT EXISTS observations_created_idx ON observations(created_at);
223
+ CREATE INDEX IF NOT EXISTS learnings_created_idx ON learnings(created_at);
184
224
 
185
225
  CREATE TABLE IF NOT EXISTS entities (
186
226
  id TEXT PRIMARY KEY,
@@ -393,7 +433,7 @@ CREATE TABLE IF NOT EXISTS places (
393
433
  name TEXT NOT NULL,
394
434
  place_type TEXT NOT NULL,
395
435
  parent_id TEXT REFERENCES places(id) ON DELETE SET NULL,
396
- loci_index INTEGER DEFAULT 0,
436
+ sort_order INTEGER DEFAULT 0,
397
437
  position_x INTEGER DEFAULT 0,
398
438
  position_y INTEGER DEFAULT 0,
399
439
  description TEXT,
@@ -405,13 +445,14 @@ CREATE TABLE IF NOT EXISTS places (
405
445
  CREATE INDEX IF NOT EXISTS places_project_idx ON places(project_id);
406
446
  CREATE INDEX IF NOT EXISTS places_type_idx ON places(place_type);
407
447
  CREATE INDEX IF NOT EXISTS places_parent_idx ON places(parent_id);
408
- CREATE INDEX IF NOT EXISTS places_loci_idx ON places(project_id, loci_index);
448
+ CREATE INDEX IF NOT EXISTS places_sort_order_idx ON places(project_id, sort_order);
409
449
 
410
450
  -- Memory-Place assignments
411
451
  CREATE TABLE IF NOT EXISTS memory_places (
412
452
  id TEXT PRIMARY KEY,
413
453
  memory_id TEXT REFERENCES memories(id) ON DELETE CASCADE NOT NULL,
414
454
  place_id TEXT REFERENCES places(id) ON DELETE CASCADE NOT NULL,
455
+ place_sort_order INTEGER DEFAULT 0,
415
456
  is_manual INTEGER DEFAULT 0,
416
457
  rule_id TEXT,
417
458
  created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
@@ -436,6 +477,69 @@ CREATE TABLE IF NOT EXISTS place_rules (
436
477
  );
437
478
  CREATE INDEX IF NOT EXISTS place_rules_project_idx ON place_rules(project_id);
438
479
  CREATE INDEX IF NOT EXISTS place_rules_type_idx ON place_rules(place_type);
480
+ -- session_summaries table
481
+ CREATE TABLE IF NOT EXISTS session_summaries (
482
+ id TEXT PRIMARY KEY,
483
+ conversation_id TEXT REFERENCES conversations(id) ON DELETE CASCADE NOT NULL,
484
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
485
+ summary_type TEXT NOT NULL,
486
+ content TEXT NOT NULL,
487
+ compressed_from INTEGER,
488
+ tokens_saved INTEGER,
489
+ embedding BLOB,
490
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
491
+ );
492
+ CREATE INDEX IF NOT EXISTS session_summaries_conversation_idx ON session_summaries(conversation_id);
493
+ CREATE INDEX IF NOT EXISTS session_summaries_project_idx ON session_summaries(project_id);
494
+ CREATE INDEX IF NOT EXISTS session_summaries_type_idx ON session_summaries(summary_type);
495
+ CREATE INDEX IF NOT EXISTS session_summaries_created_idx ON session_summaries(created_at);
496
+
497
+ -- Belief Systems - Derived Beliefs from Memory (v1.3.0+)
498
+ CREATE TABLE IF NOT EXISTS beliefs (
499
+ id TEXT PRIMARY KEY,
500
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
501
+ belief_type TEXT NOT NULL,
502
+ statement TEXT NOT NULL,
503
+ normalized_key TEXT NOT NULL,
504
+ confidence REAL DEFAULT 0.5,
505
+ belief_decay_rate INTEGER DEFAULT 30,
506
+ last_confirmed_at INTEGER,
507
+ source_count INTEGER DEFAULT 1,
508
+ status TEXT DEFAULT 'active',
509
+ reason TEXT,
510
+ context TEXT,
511
+ evidence_summary TEXT,
512
+ metadata TEXT,
513
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
514
+ updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
515
+ UNIQUE(project_id, normalized_key)
516
+ );
517
+ CREATE INDEX IF NOT EXISTS beliefs_project_idx ON beliefs(project_id);
518
+ CREATE INDEX IF NOT EXISTS beliefs_type_idx ON beliefs(belief_type);
519
+ CREATE INDEX IF NOT EXISTS beliefs_status_idx ON beliefs(status);
520
+ CREATE INDEX IF NOT EXISTS beliefs_confidence_idx ON beliefs(confidence);
521
+
522
+ CREATE TABLE IF NOT EXISTS belief_memory_sources (
523
+ id TEXT PRIMARY KEY,
524
+ belief_id TEXT REFERENCES beliefs(id) ON DELETE CASCADE,
525
+ memory_id TEXT REFERENCES memories(id) ON DELETE CASCADE,
526
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
527
+ UNIQUE(belief_id, memory_id)
528
+ );
529
+ CREATE INDEX IF NOT EXISTS belief_sources_belief_idx ON belief_memory_sources(belief_id);
530
+ CREATE INDEX IF NOT EXISTS belief_sources_memory_idx ON belief_memory_sources(memory_id);
531
+
532
+ CREATE TABLE IF NOT EXISTS belief_edges (
533
+ id TEXT PRIMARY KEY,
534
+ from_belief_id TEXT REFERENCES beliefs(id) ON DELETE CASCADE,
535
+ to_belief_id TEXT REFERENCES beliefs(id) ON DELETE CASCADE,
536
+ edge_type TEXT NOT NULL,
537
+ metadata TEXT,
538
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
539
+ UNIQUE(from_belief_id, to_belief_id, edge_type)
540
+ );
541
+ CREATE INDEX IF NOT EXISTS belief_edges_from_idx ON belief_edges(from_belief_id);
542
+ CREATE INDEX IF NOT EXISTS belief_edges_to_idx ON belief_edges(to_belief_id);
439
543
  `;
440
544
  const postgresStatements = [
441
545
  `CREATE EXTENSION IF NOT EXISTS pgcrypto;`,
@@ -574,6 +678,7 @@ const postgresStatements = [
574
678
  memory_id UUID REFERENCES memories(id) ON DELETE SET NULL,
575
679
  category TEXT,
576
680
  importance INTEGER DEFAULT 50,
681
+ confidence INTEGER DEFAULT 50,
577
682
  metadata JSONB,
578
683
  is_imported BOOLEAN DEFAULT FALSE,
579
684
  -- UAM: Agent integration columns
@@ -750,7 +855,7 @@ const postgresStatements = [
750
855
  name TEXT NOT NULL,
751
856
  place_type TEXT NOT NULL,
752
857
  parent_id UUID REFERENCES places(id) ON DELETE SET NULL,
753
- loci_index INTEGER DEFAULT 0,
858
+ sort_order INTEGER DEFAULT 0,
754
859
  position_x INTEGER DEFAULT 0,
755
860
  position_y INTEGER DEFAULT 0,
756
861
  description TEXT,
@@ -762,7 +867,7 @@ const postgresStatements = [
762
867
  `CREATE INDEX IF NOT EXISTS places_project_idx ON places(project_id);`,
763
868
  `CREATE INDEX IF NOT EXISTS places_type_idx ON places(place_type);`,
764
869
  `CREATE INDEX IF NOT EXISTS places_parent_idx ON places(parent_id);`,
765
- `CREATE INDEX IF NOT EXISTS places_loci_idx ON places(project_id, loci_index);`,
870
+ `CREATE INDEX IF NOT EXISTS places_sort_order_idx ON places(project_id, sort_order);`,
766
871
  // memory_places table
767
872
  `CREATE TABLE IF NOT EXISTS memory_places (
768
873
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
@@ -790,7 +895,51 @@ const postgresStatements = [
790
895
  updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
791
896
  );`,
792
897
  `CREATE INDEX IF NOT EXISTS place_rules_project_idx ON place_rules(project_id);`,
793
- `CREATE INDEX IF NOT EXISTS place_rules_type_idx ON place_rules(place_type);`
898
+ `CREATE INDEX IF NOT EXISTS place_rules_type_idx ON place_rules(place_type);`,
899
+ // Belief Systems - Derived Beliefs from Memory (v1.3.0+)
900
+ `CREATE TABLE IF NOT EXISTS beliefs (
901
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
902
+ project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
903
+ belief_type TEXT NOT NULL,
904
+ statement TEXT NOT NULL,
905
+ normalized_key TEXT NOT NULL,
906
+ confidence REAL DEFAULT 0.5,
907
+ belief_decay_rate INTEGER DEFAULT 30,
908
+ last_confirmed_at TIMESTAMPTZ,
909
+ source_count INTEGER DEFAULT 1,
910
+ status TEXT DEFAULT 'active',
911
+ reason TEXT,
912
+ context TEXT,
913
+ evidence_summary TEXT,
914
+ metadata JSONB,
915
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
916
+ updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
917
+ UNIQUE(project_id, normalized_key)
918
+ );`,
919
+ `CREATE INDEX IF NOT EXISTS beliefs_project_idx ON beliefs(project_id);`,
920
+ `CREATE INDEX IF NOT EXISTS beliefs_type_idx ON beliefs(belief_type);`,
921
+ `CREATE INDEX IF NOT EXISTS beliefs_status_idx ON beliefs(status);`,
922
+ `CREATE INDEX IF NOT EXISTS beliefs_confidence_idx ON beliefs(confidence);`,
923
+ `CREATE TABLE IF NOT EXISTS belief_memory_sources (
924
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
925
+ belief_id UUID REFERENCES beliefs(id) ON DELETE CASCADE,
926
+ memory_id UUID REFERENCES memories(id) ON DELETE CASCADE,
927
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
928
+ UNIQUE(belief_id, memory_id)
929
+ );`,
930
+ `CREATE INDEX IF NOT EXISTS belief_sources_belief_idx ON belief_memory_sources(belief_id);`,
931
+ `CREATE INDEX IF NOT EXISTS belief_sources_memory_idx ON belief_memory_sources(memory_id);`,
932
+ `CREATE TABLE IF NOT EXISTS belief_edges (
933
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
934
+ from_belief_id UUID REFERENCES beliefs(id) ON DELETE CASCADE,
935
+ to_belief_id UUID REFERENCES beliefs(id) ON DELETE CASCADE,
936
+ edge_type TEXT NOT NULL,
937
+ metadata JSONB,
938
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
939
+ UNIQUE(from_belief_id, to_belief_id, edge_type)
940
+ );`,
941
+ `CREATE INDEX IF NOT EXISTS belief_edges_from_idx ON belief_edges(from_belief_id);`,
942
+ `CREATE INDEX IF NOT EXISTS belief_edges_to_idx ON belief_edges(to_belief_id);`
794
943
  ];
795
944
  /**
796
945
  * Ensure the data directory exists (.squish folder in project root)
@@ -809,272 +958,72 @@ export async function ensureDataDirectory() {
809
958
  }
810
959
  }
811
960
  export async function ensureSqliteSchema(sqlite) {
812
- // Run schema creation FIRST (creates tables with latest schema)
813
- sqlite.exec(sqliteSchemaSql);
961
+ // Run schema creation FIRST (creates tables with latest schema).
962
+ // Older installs may fail partway through when later indexes/triggers refer
963
+ // to columns that migrations have not added yet, so tolerate that first pass.
964
+ execSqliteSchema(sqlite, { tolerant: true });
965
+ // Initialize schema version tracking
966
+ await initializeSchemaVersionTable(sqlite);
814
967
  // Run migrations AFTER (for existing databases that need column additions)
815
968
  await runSqliteMigrations(sqlite);
969
+ // Replay the full schema after migrations so deferred indexes/triggers land.
970
+ execSqliteSchema(sqlite, { tolerant: false });
816
971
  }
817
- async function runSqliteMigrations(sqlite) {
818
- // Check if memories table exists
819
- const tableCheck = sqlite.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='memories'").get();
820
- if (!tableCheck) {
821
- // Table doesn't exist yet - it will be created by schema SQL with all columns
822
- // No migrations needed
823
- return;
824
- }
825
- // Migrations for memories table (deduplicated, ordered by version)
826
- const memoriesMigrations = [
827
- // Base columns (v0.1.x - v0.5.x)
828
- { col: 'embedding', sql: 'ALTER TABLE memories ADD COLUMN embedding BLOB' },
829
- { col: 'relevance_score', sql: 'ALTER TABLE memories ADD COLUMN relevance_score INTEGER DEFAULT 50' },
830
- // Merge tracking (v0.6.x)
831
- { col: 'is_merged', sql: 'ALTER TABLE memories ADD COLUMN is_merged INTEGER DEFAULT 0' },
832
- { col: 'merged_into_id', sql: 'ALTER TABLE memories ADD COLUMN merged_into_id TEXT' },
833
- { col: 'is_mergeable', sql: 'ALTER TABLE memories ADD COLUMN is_mergeable INTEGER DEFAULT 1' },
834
- { col: 'is_canonical', sql: 'ALTER TABLE memories ADD COLUMN is_canonical INTEGER DEFAULT 0' },
835
- { col: 'merged_at', sql: 'ALTER TABLE memories ADD COLUMN merged_at INTEGER' },
836
- { col: 'merge_source_ids', sql: 'ALTER TABLE memories ADD COLUMN merge_source_ids TEXT' },
837
- { col: 'merge_version', sql: 'ALTER TABLE memories ADD COLUMN merge_version INTEGER DEFAULT 1' },
838
- // Importance scoring (v0.8.0)
839
- { col: 'importance_score', sql: 'ALTER TABLE memories ADD COLUMN importance_score INTEGER DEFAULT 50' },
840
- { col: 'importance_decay_rate', sql: 'ALTER TABLE memories ADD COLUMN importance_decay_rate INTEGER DEFAULT 30' },
841
- { col: 'last_importance_recalc', sql: 'ALTER TABLE memories ADD COLUMN last_importance_recalc INTEGER' },
842
- // Consolidation (v0.8.0)
843
- { col: 'consolidated_into', sql: 'ALTER TABLE memories ADD COLUMN consolidated_into TEXT' },
844
- { col: 'consolidated_at', sql: 'ALTER TABLE memories ADD COLUMN consolidated_at INTEGER' },
845
- { col: 'is_consolidated', sql: 'ALTER TABLE memories ADD COLUMN is_consolidated INTEGER DEFAULT 0' },
846
- // Memory lifecycle (v0.8.0)
847
- { col: 'sector', sql: 'ALTER TABLE memories ADD COLUMN sector TEXT DEFAULT "episodic"' },
848
- { col: 'tier', sql: 'ALTER TABLE memories ADD COLUMN tier TEXT DEFAULT "hot"' },
849
- { col: 'context_status', sql: 'ALTER TABLE memories ADD COLUMN context_status TEXT DEFAULT "out-of-context"' },
850
- { col: 'decay_rate', sql: 'ALTER TABLE memories ADD COLUMN decay_rate INTEGER DEFAULT 30' },
851
- { col: 'coactivation_score', sql: 'ALTER TABLE memories ADD COLUMN coactivation_score INTEGER DEFAULT 0' },
852
- { col: 'last_decay_at', sql: 'ALTER TABLE memories ADD COLUMN last_decay_at INTEGER DEFAULT (strftime(\'%s\',\'now\'))' },
853
- // Agent tracking (v0.8.0)
854
- { col: 'agent_id', sql: 'ALTER TABLE memories ADD COLUMN agent_id TEXT' },
855
- { col: 'agent_role', sql: 'ALTER TABLE memories ADD COLUMN agent_role TEXT' },
856
- { col: 'retrieval_priority', sql: 'ALTER TABLE memories ADD COLUMN retrieval_priority INTEGER DEFAULT 50' },
857
- // Data governance (v0.9.0)
858
- { col: 'recorded_at', sql: 'ALTER TABLE memories ADD COLUMN recorded_at INTEGER DEFAULT (strftime(\'%s\',\'now\'))' },
859
- { col: 'confidence', sql: 'ALTER TABLE memories ADD COLUMN confidence INTEGER DEFAULT 50' },
860
- { col: 'valid_from', sql: 'ALTER TABLE memories ADD COLUMN valid_from INTEGER' },
861
- { col: 'valid_to', sql: 'ALTER TABLE memories ADD COLUMN valid_to INTEGER' },
862
- { col: 'superseded_by', sql: 'ALTER TABLE memories ADD COLUMN superseded_by TEXT' },
863
- { col: 'version', sql: 'ALTER TABLE memories ADD COLUMN version INTEGER DEFAULT 1' },
864
- { col: 'is_active', sql: 'ALTER TABLE memories ADD COLUMN is_active INTEGER DEFAULT 1' },
865
- { col: 'expires_at', sql: 'ALTER TABLE memories ADD COLUMN expires_at INTEGER' },
866
- // Privacy & access (v0.9.0)
867
- { col: 'is_private', sql: 'ALTER TABLE memories ADD COLUMN is_private INTEGER DEFAULT 0' },
868
- { col: 'has_secrets', sql: 'ALTER TABLE memories ADD COLUMN has_secrets INTEGER DEFAULT 0' },
869
- { col: 'visibility_scope', sql: 'ALTER TABLE memories ADD COLUMN visibility_scope TEXT DEFAULT "private"' },
870
- { col: 'is_protected', sql: 'ALTER TABLE memories ADD COLUMN is_protected INTEGER DEFAULT 0' },
871
- { col: 'is_pinned', sql: 'ALTER TABLE memories ADD COLUMN is_pinned INTEGER DEFAULT 0' },
872
- { col: 'is_immutable', sql: 'ALTER TABLE memories ADD COLUMN is_immutable INTEGER DEFAULT 0' },
873
- { col: 'write_scope', sql: 'ALTER TABLE memories ADD COLUMN write_scope TEXT' },
874
- { col: 'read_scope', sql: 'ALTER TABLE memories ADD COLUMN read_scope TEXT' },
875
- // Usage tracking (v0.9.0)
876
- { col: 'triggered_by', sql: 'ALTER TABLE memories ADD COLUMN triggered_by TEXT' },
877
- { col: 'capture_reason', sql: 'ALTER TABLE memories ADD COLUMN capture_reason TEXT' },
878
- { col: 'last_used_at', sql: 'ALTER TABLE memories ADD COLUMN last_used_at INTEGER' },
879
- { col: 'usage_count', sql: 'ALTER TABLE memories ADD COLUMN usage_count INTEGER DEFAULT 0' },
880
- { col: 'user_id', sql: 'ALTER TABLE memories ADD COLUMN user_id TEXT' },
881
- // Layer tracking (v0.9.x)
882
- { col: 'has_l0_abstract', sql: 'ALTER TABLE memories ADD COLUMN has_l0_abstract INTEGER DEFAULT 0' },
883
- { col: 'has_l1_overview', sql: 'ALTER TABLE memories ADD COLUMN has_l1_overview INTEGER DEFAULT 0' },
884
- { col: 'last_layer_update', sql: 'ALTER TABLE memories ADD COLUMN last_layer_update INTEGER' },
885
- // Namespace support (v1.0.x)
886
- { col: 'namespace_id', sql: 'ALTER TABLE memories ADD COLUMN namespace_id TEXT REFERENCES namespaces(id) ON DELETE SET NULL' },
887
- { col: 'namespace_path', sql: 'ALTER TABLE memories ADD COLUMN namespace_path TEXT' },
888
- // Places support (v1.1.5) - Spatial memory organization
889
- { col: 'place_id', sql: 'ALTER TABLE memories ADD COLUMN place_id TEXT REFERENCES places(id) ON DELETE SET NULL' },
890
- { col: 'place_loci_index', sql: 'ALTER TABLE memories ADD COLUMN place_loci_index INTEGER' },
891
- // Token tracking (v1.0.x)
892
- { col: 'tokens_estimate', sql: 'ALTER TABLE memories ADD COLUMN tokens_estimate INTEGER DEFAULT 0' },
893
- // Iteration 3: Confidence flags (default: speculative)
894
- { col: 'confidence_level', sql: 'ALTER TABLE memories ADD COLUMN confidence_level TEXT DEFAULT "speculative"' },
895
- // v1.1.0: Status and encryption
896
- { col: 'status', sql: 'ALTER TABLE memories ADD COLUMN status TEXT DEFAULT "active"' },
897
- { col: 'encrypted_content', sql: 'ALTER TABLE memories ADD COLUMN encrypted_content TEXT' },
898
- { col: 'encryption_nonce', sql: 'ALTER TABLE memories ADD COLUMN encryption_nonce TEXT' },
899
- { col: 'is_encrypted', sql: 'ALTER TABLE memories ADD COLUMN is_encrypted INTEGER DEFAULT 0' },
900
- // Places support (v1.1.5) - Spatial memory organization
901
- { col: 'place_id', sql: 'ALTER TABLE memories ADD COLUMN place_id UUID REFERENCES places(id) ON DELETE SET NULL' },
902
- { col: 'place_loci_index', sql: 'ALTER TABLE memories ADD COLUMN place_loci_index INTEGER' }
903
- ];
904
- // Get existing columns for memories table
905
- const tableInfo = sqlite.prepare("PRAGMA table_info(memories)").all();
906
- const existingColumns = new Set(tableInfo.map(col => col.name));
907
- for (const migration of memoriesMigrations) {
908
- if (!existingColumns.has(migration.col)) {
909
- try {
910
- sqlite.exec(migration.sql);
911
- logger.info(`Migration: Added column ${migration.col} to memories table`);
912
- }
913
- catch (error) {
914
- // Re-throw real errors - only ignore "duplicate column" errors
915
- const msg = error instanceof Error ? error.message : String(error);
916
- if (msg.includes('duplicate column name')) {
917
- logger.debug(`Migration skipped for ${migration.col}: column already exists`);
918
- }
919
- else {
920
- throw new Error(`Migration failed for column ${migration.col}: ${msg}`);
921
- }
922
- }
923
- }
924
- }
925
- // v0.9.2: Add tokens_estimate to core_memory
926
- const coreMemoryTableCheck = sqlite.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='core_memory'").get();
927
- if (coreMemoryTableCheck) {
928
- const coreMemoryInfo = sqlite.prepare("PRAGMA table_info(core_memory)").all();
929
- const existingCoreMemoryColumns = new Set(coreMemoryInfo.map(col => col.name));
930
- const coreMemoryMigrations = [
931
- { col: 'tokens_estimate', sql: 'ALTER TABLE core_memory ADD COLUMN tokens_estimate INTEGER DEFAULT 0 NOT NULL' },
932
- ];
933
- for (const migration of coreMemoryMigrations) {
934
- if (!existingCoreMemoryColumns.has(migration.col)) {
935
- try {
936
- sqlite.exec(migration.sql);
937
- logger.info(`Migration: Added column ${migration.col} to core_memory table`);
938
- }
939
- catch (error) {
940
- const msg = error instanceof Error ? error.message : String(error);
941
- if (msg.includes('duplicate column name')) {
942
- logger.debug(`Migration skipped for ${migration.col}: column already exists`);
943
- }
944
- else {
945
- throw new Error(`Migration failed for column ${migration.col}: ${msg}`);
946
- }
947
- }
948
- }
949
- }
950
- }
951
- // Migrations for learnings table (v1.2.x) - renamed from observations
952
- // First, check if we need to rename observations -> learnings
953
- const observationsTableCheck = sqlite.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='observations'").get();
954
- const learningsTableCheck = sqlite.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='learnings'").get();
955
- if (observationsTableCheck && !learningsTableCheck) {
956
- // Rename observations to learnings
957
- try {
958
- sqlite.exec("ALTER TABLE observations RENAME TO learnings");
959
- logger.info("Migration: Renamed observations table to learnings");
960
- }
961
- catch (error) {
962
- const err = error instanceof Error ? error.message : String(error);
963
- logger.warn(`Migration note: Could not rename observations to learnings: ${err}`);
964
- }
965
- }
966
- // Now run migrations on learnings table (whether renamed or new)
967
- const learningsInfo = sqlite.prepare("PRAGMA table_info(learnings)").all();
968
- const existingLearningsColumns = new Set(learningsInfo.map(col => col.name));
969
- const learningsMigrations = [
970
- { col: 'embedding', sql: 'ALTER TABLE learnings ADD COLUMN embedding BLOB' },
971
- { col: 'folder_path', sql: 'ALTER TABLE learnings ADD COLUMN folder_path TEXT' },
972
- { col: 'project_path', sql: 'ALTER TABLE learnings ADD COLUMN project_path TEXT' },
973
- { col: 'is_private', sql: 'ALTER TABLE learnings ADD COLUMN is_private INTEGER DEFAULT 0' },
974
- { col: 'has_secrets', sql: 'ALTER TABLE learnings ADD COLUMN has_secrets INTEGER DEFAULT 0' },
975
- { col: 'relevance_score', sql: 'ALTER TABLE learnings ADD COLUMN relevance_score INTEGER DEFAULT 50' },
976
- { col: 'memory_id', sql: 'ALTER TABLE learnings ADD COLUMN memory_id TEXT REFERENCES memories(id) ON DELETE SET NULL' },
977
- { col: 'is_imported', sql: 'ALTER TABLE learnings ADD COLUMN is_imported INTEGER DEFAULT 0' },
978
- ];
979
- for (const migration of learningsMigrations) {
980
- if (!existingLearningsColumns.has(migration.col)) {
972
+ // Schema versions for tracking
973
+ const SCHEMA_VERSIONS = [
974
+ { version: '1.2.0-base', description: 'Initial v1.2.0 schema with schema_versions table' },
975
+ { version: '1.2.0-place-sort', description: 'Add place_sort_order column to places' },
976
+ { version: '1.2.0-mem-place', description: 'Add place_sort_order to memories and memory_places' },
977
+ { version: '1.2.0-agent-prefs', description: 'Add agent_preferences table for agent evolution' },
978
+ ];
979
+ async function initializeSchemaVersionTable(sqlite) {
980
+ // Get existing versions
981
+ const existingVersions = sqlite.prepare("SELECT version FROM _schema_versions").all();
982
+ const appliedVersions = new Set(existingVersions.map(v => v.version));
983
+ // Insert any missing versions
984
+ for (const { version, description } of SCHEMA_VERSIONS) {
985
+ if (!appliedVersions.has(version)) {
981
986
  try {
982
- sqlite.exec(migration.sql);
983
- logger.info(`Migration: Added column ${migration.col} to learnings table`);
987
+ sqlite.prepare("INSERT INTO _schema_versions (version, description) VALUES (?, ?)").run(version, description);
988
+ logger.info(`Schema version ${version} recorded`);
984
989
  }
985
990
  catch (error) {
991
+ // Ignore duplicate errors
986
992
  const msg = error instanceof Error ? error.message : String(error);
987
- if (msg.includes('duplicate column name')) {
988
- logger.debug(`Migration skipped for ${migration.col}: column already exists`);
989
- }
990
- else {
991
- logger.warn(`Migration note for ${migration.col}: ${msg}`);
993
+ if (!msg.includes('UNIQUE constraint failed')) {
994
+ logger.warn(`Could not record schema version ${version}: ${msg}`);
992
995
  }
993
996
  }
994
997
  }
995
998
  }
996
- // Add indexes if they don't exist
997
- const existingIndexes = sqlite.prepare("SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='learnings'").all();
998
- const existingIndexNames = new Set(existingIndexes.map(idx => idx.name));
999
- const indexMigrations = [
1000
- { name: 'learnings_folder_idx', sql: 'CREATE INDEX IF NOT EXISTS learnings_folder_idx ON learnings(folder_path)' },
1001
- { name: 'learnings_relevance_idx', sql: 'CREATE INDEX IF NOT EXISTS learnings_relevance_idx ON learnings(relevance_score)' },
1002
- { name: 'learnings_private_idx', sql: 'CREATE INDEX IF NOT EXISTS learnings_private_idx ON learnings(is_private)' },
1003
- { name: 'learnings_memory_idx', sql: 'CREATE INDEX IF NOT EXISTS learnings_memory_idx ON learnings(memory_id)' },
1004
- ];
1005
- for (const idx of indexMigrations) {
1006
- if (!existingIndexNames.has(idx.name)) {
1007
- try {
1008
- sqlite.exec(idx.sql);
1009
- logger.info(`Migration: Added index ${idx.name} to learnings table`);
1010
- }
1011
- catch (error) {
1012
- const msg = error instanceof Error ? error.message : String(error);
1013
- logger.warn(`Index migration note for ${idx.name}: ${msg}`);
1014
- }
1015
- }
999
+ }
1000
+ export async function getSchemaVersion(sqlite) {
1001
+ const result = sqlite.prepare("SELECT version FROM _schema_versions ORDER BY applied_at DESC LIMIT 1").get();
1002
+ return result?.version || null;
1003
+ }
1004
+ export async function runMigrationsForVersion(sqlite, targetVersion) {
1005
+ const currentVersion = await getSchemaVersion(sqlite);
1006
+ logger.info(`Current schema version: ${currentVersion}, target: ${targetVersion}`);
1007
+ // Run ensureSqliteSchema which handles all migrations
1008
+ await runSqliteMigrations(sqlite);
1009
+ }
1010
+ async function runSqliteMigrations(sqlite) {
1011
+ // All migrations are in separate files - just run them all
1012
+ await runAllMigrations(sqlite);
1013
+ }
1014
+ function execSqliteSchema(sqlite, options) {
1015
+ try {
1016
+ sqlite.exec(sqliteSchemaSql);
1016
1017
  }
1017
- // Migrations for maintenance_jobs table (v1.0.x)
1018
- const maintenanceJobsTableCheck = sqlite.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='maintenance_jobs'").get();
1019
- if (maintenanceJobsTableCheck) {
1020
- const maintenanceJobsInfo = sqlite.prepare("PRAGMA table_info(maintenance_jobs)").all();
1021
- const existingMaintenanceJobsColumns = new Set(maintenanceJobsInfo.map(col => col.name));
1022
- // Check if table has wrong schema (camelCase columns from bug in earlier version)
1023
- const hasCamelCaseColumns = existingMaintenanceJobsColumns.has('jobName') ||
1024
- existingMaintenanceJobsColumns.has('jobType') ||
1025
- existingMaintenanceJobsColumns.has('cronExpression');
1026
- if (hasCamelCaseColumns) {
1027
- // Table has incorrect camelCase schema - need to recreate it
1028
- logger.warn('Maintenance jobs table has incorrect schema (camelCase columns). Recreating...');
1029
- try {
1030
- // Drop the malformed table
1031
- sqlite.exec('DROP TABLE IF EXISTS maintenance_jobs');
1032
- // Recreate with correct schema - it will be created by the schema SQL
1033
- logger.info('Dropped malformed maintenance_jobs table. It will be recreated with correct schema.');
1034
- }
1035
- catch (error) {
1036
- logger.error('Failed to recreate maintenance_jobs table:', error);
1037
- }
1038
- }
1039
- else {
1040
- // Normal migrations for correct schema
1041
- const maintenanceJobsMigrations = [
1042
- { col: 'schedule', sql: 'ALTER TABLE maintenance_jobs DROP COLUMN schedule' },
1043
- { col: 'cron_expression', sql: 'ALTER TABLE maintenance_jobs ADD COLUMN cron_expression TEXT' },
1044
- { col: 'last_run_at', sql: 'ALTER TABLE maintenance_jobs ADD COLUMN last_run_at INTEGER' },
1045
- { col: 'last_run_duration', sql: 'ALTER TABLE maintenance_jobs ADD COLUMN last_run_duration INTEGER' },
1046
- { col: 'last_run_status', sql: 'ALTER TABLE maintenance_jobs ADD COLUMN last_run_status TEXT' },
1047
- { col: 'last_run_error', sql: 'ALTER TABLE maintenance_jobs ADD COLUMN last_run_error TEXT' },
1048
- { col: 'total_runs', sql: 'ALTER TABLE maintenance_jobs ADD COLUMN total_runs INTEGER DEFAULT 0' },
1049
- { col: 'success_count', sql: 'ALTER TABLE maintenance_jobs ADD COLUMN success_count INTEGER DEFAULT 0' },
1050
- { col: 'failure_count', sql: 'ALTER TABLE maintenance_jobs ADD COLUMN failure_count INTEGER DEFAULT 0' },
1051
- { col: 'job_config', sql: 'ALTER TABLE maintenance_jobs ADD COLUMN job_config TEXT' },
1052
- { col: 'next_run_at', sql: 'ALTER TABLE maintenance_jobs ADD COLUMN next_run_at INTEGER' },
1053
- { col: 'run_count', sql: 'ALTER TABLE maintenance_jobs DROP COLUMN run_count' },
1054
- ];
1055
- for (const migration of maintenanceJobsMigrations) {
1056
- // For DROP migrations, only run if column EXISTS
1057
- // For ADD migrations, only run if column does NOT exist
1058
- const shouldRun = migration.sql.startsWith('ALTER TABLE maintenance_jobs DROP COLUMN')
1059
- ? existingMaintenanceJobsColumns.has(migration.col)
1060
- : !existingMaintenanceJobsColumns.has(migration.col);
1061
- if (shouldRun) {
1062
- try {
1063
- sqlite.exec(migration.sql);
1064
- logger.info(`Migration: ${migration.col} on maintenance_jobs table`);
1065
- }
1066
- catch (error) {
1067
- const msg = error instanceof Error ? error.message : String(error);
1068
- if (msg.includes('duplicate column name') || msg.includes('no such column')) {
1069
- logger.debug(`Migration skipped for ${migration.col}: ${msg.includes('duplicate column name') ? 'column already exists' : 'column does not exist'}`);
1070
- }
1071
- else {
1072
- throw new Error(`Migration failed for column ${migration.col}: ${msg}`);
1073
- }
1074
- }
1075
- }
1076
- }
1018
+ catch (error) {
1019
+ const message = error instanceof Error ? error.message : String(error);
1020
+ const isRecoverable = message.includes('no such column') ||
1021
+ message.includes('has no column named');
1022
+ if (options.tolerant && isRecoverable) {
1023
+ logger.debug(`Deferred schema statement until after migrations: ${message}`);
1024
+ return;
1077
1025
  }
1026
+ throw error;
1078
1027
  }
1079
1028
  }
1080
1029
  export async function ensurePostgresSchema(pool) {