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,1032 @@
1
+ import { sqliteTable, text, integer, blob, index, primaryKey } from 'drizzle-orm/sqlite-core';
2
+ import { relations } from 'drizzle-orm';
3
+ import { sql } from 'drizzle-orm';
4
+
5
+ // Core Tables - SQLite compatible version
6
+ // ============================================================================
7
+
8
+ /**
9
+ * Users - represents Claude Code users
10
+ */
11
+ export const users = sqliteTable('users', {
12
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
13
+ externalId: text('external_id').unique(), // Claude user ID if available
14
+ name: text('name'),
15
+ email: text('email'),
16
+ preferences: text('preferences').$type<Record<string, unknown>>(),
17
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
18
+ updatedAt: integer('updated_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
19
+ });
20
+
21
+ /**
22
+ * Projects - workspaces that memories are scoped to
23
+ */
24
+ export const projects = sqliteTable('projects', {
25
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
26
+ name: text('name').notNull(),
27
+ path: text('path').notNull(),
28
+ description: text('description'),
29
+ metadata: text('metadata').$type<Record<string, unknown>>(),
30
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
31
+ updatedAt: integer('updated_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
32
+ }, (table) => [
33
+ index('projects_path_idx').on(table.path),
34
+ ]);
35
+
36
+ /**
37
+ * Memories - core memory storage
38
+ */
39
+ export const memories = sqliteTable(
40
+ 'memories',
41
+ {
42
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
43
+ projectId: text('project_id').references(() => projects.id, { onDelete: 'cascade' }),
44
+ userId: text('user_id').references(() => users.id, { onDelete: 'set null' }),
45
+
46
+ // Content
47
+ type: text('type').notNull().$type<'observation' | 'fact' | 'decision' | 'context' | 'preference'>(),
48
+ content: text('content').notNull(),
49
+ summary: text('summary'),
50
+
51
+ // Embeddings stored as JSON string (not for semantic search in SQLite)
52
+ embeddingJson: text('embedding_json'),
53
+
54
+ // v0.2.0: Vector embedding for local search
55
+ embedding: blob('embedding'),
56
+
57
+ // Metadata
58
+ source: text('source'),
59
+ confidence: integer('confidence').default(50), // 0-100 confidence score (default: speculative)
60
+ confidenceLevel: text('confidence_level').$type<'certain' | 'speculative' | 'outdated'>().default('speculative'), // Iteration 3: Confidence flags (default: speculative)
61
+ tags: text('tags').$type<string[]>(),
62
+ metadata: text('metadata').$type<Record<string, unknown>>(),
63
+
64
+ // v0.2.0: Privacy and relevance
65
+ isPrivate: integer('is_private', { mode: 'boolean' }).default(false),
66
+ hasSecrets: integer('has_secrets', { mode: 'boolean' }).default(false),
67
+ relevanceScore: integer('relevance_score').default(50), // 0-100
68
+
69
+ // Lifecycle
70
+ isActive: integer('is_active', { mode: 'boolean' }).default(true),
71
+ expiresAt: integer('expires_at', { mode: 'timestamp' }),
72
+ accessCount: integer('access_count').default(0),
73
+ lastAccessedAt: integer('last_accessed_at', { mode: 'timestamp' }),
74
+
75
+ // Merge tracking
76
+ isMerged: integer('is_merged', { mode: 'boolean' }).default(false),
77
+ mergedIntoId: text('merged_into_id').references((): any => (memories as any).id),
78
+ mergedAt: integer('merged_at', { mode: 'timestamp' }),
79
+ isCanonical: integer('is_canonical', { mode: 'boolean' }).default(false),
80
+ mergeSourceIds: text('merge_source_ids').$type<string[]>(),
81
+ isMergeable: integer('is_mergeable', { mode: 'boolean' }).default(true),
82
+ mergeVersion: integer('merge_version').default(1),
83
+
84
+ // v0.4.2: Namespace support
85
+ namespaceId: text('namespace_id').references(() => namespaces.id, { onDelete: 'set null' }),
86
+ namespacePath: text('namespace_path'),
87
+
88
+ // v1.1.5: Places support (spatial memory organization)
89
+ placeId: text('place_id').references(() => places.id, { onDelete: 'set null' }),
90
+ placeSortOrder: integer('place_sort_order'),
91
+
92
+ // v0.4.3: Layer support
93
+ hasL0Abstract: integer('has_l0_abstract', { mode: 'boolean' }).default(false),
94
+ hasL1Overview: integer('has_l1_overview', { mode: 'boolean' }).default(false),
95
+ lastLayerUpdate: integer('last_layer_update', { mode: 'timestamp' }),
96
+
97
+ // v0.8.0: Importance Scoring
98
+ importanceScore: integer('importance_score').default(50), // 0-100
99
+ importanceDecayRate: integer('importance_decay_rate').default(30), // days half-life
100
+ lastImportanceRecalc: integer('last_importance_recalc', { mode: 'timestamp' }),
101
+
102
+ // v0.10.0: Echo/Fizzle Tracking - Retrieval Priority
103
+ retrievalPriority: integer('retrieval_priority').default(50), // 0-100, adjusted by feedback
104
+
105
+ // v1.0.x: Token tracking
106
+ tokensEstimate: integer('tokens_estimate').default(0).notNull(),
107
+
108
+ // v0.8.0: Consolidation tracking
109
+ consolidatedInto: text('consolidated_into').references((): any => (memories as any).id),
110
+ consolidatedAt: integer('consolidated_at', { mode: 'timestamp' }),
111
+ isConsolidated: integer('is_consolidated', { mode: 'boolean' }).default(false),
112
+
113
+ // v0.3.0: Memory Lifecycle Management
114
+ sector: text('sector').$type<'episodic' | 'semantic' | 'procedural' | 'autobiographical' | 'working'>().default('episodic'),
115
+ tier: text('tier').$type<'hot' | 'cold'>().default('hot'),
116
+ status: text('status').notNull().default('active'),
117
+ encrypted_content: text('encrypted_content'),
118
+ encryption_nonce: text('encryption_nonce'),
119
+ is_encrypted: integer('is_encrypted', { mode: 'boolean' }).default(false),
120
+
121
+ // v0.5.0: Context Status - Track whether memory is in active context or archived
122
+ contextStatus: text('context_status').$type<'in-context' | 'out-of-context' | 'archived'>().default('out-of-context'),
123
+
124
+ // Per-memory decay rate (integer percentage, e.g., 30 = 30% decay per cycle)
125
+ decayRate: integer('decay_rate').default(30),
126
+ coactivationScore: integer('coactivation_score').default(0),
127
+ lastDecayAt: integer('last_decay_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`),
128
+
129
+ // v0.3.0: Agent-Aware Memory
130
+ agentId: text('agent_id'),
131
+ agentRole: text('agent_role'),
132
+ visibilityScope: text('visibility_scope').$type<'private' | 'project' | 'team' | 'global'>().default('private'),
133
+
134
+ // v0.3.0: Memory Governance
135
+ isProtected: integer('is_protected', { mode: 'boolean' }).default(false),
136
+ isPinned: integer('is_pinned', { mode: 'boolean' }).default(false),
137
+ isImmutable: integer('is_immutable', { mode: 'boolean' }).default(false),
138
+ writeScope: text('write_scope').$type<string[]>(),
139
+ readScope: text('read_scope').$type<string[]>(),
140
+
141
+ // v0.3.0: Provenance
142
+ triggeredBy: text('triggered_by'),
143
+ captureReason: text('capture_reason'),
144
+ lastUsedAt: integer('last_used_at', { mode: 'timestamp' }),
145
+ usageCount: integer('usage_count').default(0),
146
+
147
+ // v0.3.0: Temporal Facts
148
+ validFrom: integer('valid_from', { mode: 'timestamp' }),
149
+ validTo: integer('valid_to', { mode: 'timestamp' }),
150
+ recordedAt: integer('recorded_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(), // When agent learned/stored the fact
151
+ supersededBy: text('superseded_by').references((): any => (memories as any).id),
152
+ version: integer('version').default(1),
153
+
154
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
155
+ updatedAt: integer('updated_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
156
+ },
157
+ (table): any => [
158
+ index('memories_project_idx').on(table.projectId),
159
+ index('memories_type_idx').on(table.type),
160
+ index('memories_created_idx').on(table.createdAt),
161
+ index('memories_tags_idx').on(table.tags),
162
+ index('memories_relevance_idx').on(table.relevanceScore),
163
+ index('memories_private_idx').on(table.isPrivate),
164
+ index('memories_merged_idx').on(table.isMerged),
165
+ index('memories_canonical_idx').on(table.isCanonical),
166
+ index('memories_sector_idx').on(table.sector),
167
+ index('memories_tier_idx').on(table.tier),
168
+ index('memories_agent_idx').on(table.agentId),
169
+ index('memories_visibility_idx').on(table.visibilityScope),
170
+ index('memories_protected_idx').on(table.isProtected),
171
+ index('memories_pinned_idx').on(table.isPinned),
172
+ index('memories_valid_from_idx').on(table.validFrom),
173
+ index('memories_valid_to_idx').on(table.validTo),
174
+ index('memories_context_status_idx').on(table.contextStatus),
175
+
176
+ // v0.8.0: Importance scoring indexes
177
+ index('memories_importance_idx').on(table.importanceScore),
178
+ index('memories_consolidated_idx').on(table.isConsolidated),
179
+ index('memories_consolidation_query_idx').on(
180
+ table.projectId,
181
+ table.isConsolidated,
182
+ table.importanceScore
183
+ ),
184
+
185
+ // v0.5.0: Context status composite index for efficient filtering
186
+ index('memories_context_query_idx').on(
187
+ table.projectId,
188
+ table.contextStatus,
189
+ table.tier
190
+ ),
191
+
192
+ // v0.4.2: Composite indexes for performance optimization
193
+ // Duplicate detection query optimization
194
+ index('memories_duplicate_detection_idx').on(
195
+ table.projectId,
196
+ table.isMerged,
197
+ table.isMergeable,
198
+ table.isActive
199
+ ),
200
+ // Eviction query optimization
201
+ index('memories_eviction_idx').on(
202
+ table.projectId,
203
+ table.tier,
204
+ table.relevanceScore,
205
+ table.createdAt
206
+ ),
207
+ // Decay operations optimization
208
+ index('memories_decay_idx').on(
209
+ table.sector,
210
+ table.lastDecayAt,
211
+ table.isProtected
212
+ ),
213
+ // Temporal query optimization
214
+ index('memories_temporal_idx').on(
215
+ table.projectId,
216
+ table.validFrom,
217
+ table.validTo
218
+ ),
219
+ // Agent-aware retrieval optimization
220
+ index('memories_agent_visibility_idx').on(
221
+ table.agentId,
222
+ table.visibilityScope,
223
+ table.isActive
224
+ ),
225
+ ],
226
+ ) as any;
227
+
228
+ /**
229
+ * Conversations - chat session tracking
230
+ */
231
+ export const conversations = sqliteTable('conversations', {
232
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
233
+ projectId: text('project_id').references(() => projects.id, { onDelete: 'cascade' }),
234
+ userId: text('user_id').references(() => users.id, { onDelete: 'set null' }),
235
+
236
+ sessionId: text('session_id').notNull(),
237
+ title: text('title'),
238
+ summary: text('summary'),
239
+
240
+ messageCount: integer('message_count').default(0),
241
+ tokenCount: integer('token_count').default(0),
242
+
243
+ startedAt: integer('started_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
244
+ endedAt: integer('ended_at', { mode: 'timestamp' }),
245
+
246
+ metadata: text('metadata').$type<Record<string, unknown>>(),
247
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
248
+ updatedAt: integer('updated_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
249
+ }, (table) => [
250
+ index('conversations_project_idx').on(table.projectId),
251
+ index('conversations_session_idx').on(table.sessionId),
252
+ index('conversations_started_idx').on(table.startedAt),
253
+ ]);
254
+
255
+ /**
256
+ * Messages - individual messages in conversations
257
+ */
258
+ export const messages = sqliteTable('messages', {
259
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
260
+ conversationId: text('conversation_id').notNull().references(() => conversations.id, { onDelete: 'cascade' }),
261
+
262
+ role: text('role').notNull().$type<'user' | 'assistant'>(),
263
+ content: text('content').notNull(),
264
+
265
+ embeddingJson: text('embedding_json'),
266
+ tokenCount: integer('token_count'),
267
+ toolCalls: text('tool_calls').$type<unknown[]>(),
268
+ metadata: text('metadata').$type<Record<string, unknown>>(),
269
+
270
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
271
+ }, (table) => [
272
+ index('messages_conversation_idx').on(table.conversationId),
273
+ index('messages_role_idx').on(table.role),
274
+ index('messages_created_idx').on(table.createdAt),
275
+ ]);
276
+
277
+ /**
278
+ * Learnings - agent learnings: success, failure, fix, insight
279
+ */
280
+ export const learnings = sqliteTable('learnings', {
281
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
282
+ projectId: text('project_id').references(() => projects.id, { onDelete: 'cascade' }),
283
+ conversationId: text('conversation_id').references(() => conversations.id, { onDelete: 'set null' }),
284
+
285
+ // Learning type: success, failure, fix, insight
286
+ type: text('type').notNull().$type<'success' | 'failure' | 'fix' | 'insight'>(),
287
+ action: text('action').notNull(),
288
+ target: text('target'),
289
+ summary: text('summary').notNull(),
290
+ details: text('details').$type<Record<string, unknown>>(),
291
+
292
+ // Embeddings
293
+ embeddingJson: text('embedding_json'),
294
+ embedding: blob('embedding'),
295
+
296
+ // Optional link to a memory (for bidirectional linking)
297
+ memoryId: text('memory_id').references(() => memories.id, { onDelete: 'set null' }),
298
+
299
+ // Folder-scoped
300
+ folderPath: text('folder_path'),
301
+ projectPath: text('project_path'),
302
+
303
+ // Privacy and relevance
304
+ isPrivate: integer('is_private', { mode: 'boolean' }).default(false),
305
+ hasSecrets: integer('has_secrets', { mode: 'boolean' }).default(false),
306
+ relevanceScore: integer('relevance_score').default(50),
307
+
308
+ category: text('category'),
309
+ importance: integer('importance').default(50),
310
+ metadata: text('metadata').$type<Record<string, unknown>>(),
311
+
312
+ // Migration tracking
313
+ isImported: integer('is_imported', { mode: 'boolean' }).default(false),
314
+
315
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
316
+ }, (table) => [
317
+ index('learnings_project_idx').on(table.projectId),
318
+ index('learnings_type_idx').on(table.type),
319
+ index('learnings_action_idx').on(table.action),
320
+ index('learnings_created_idx').on(table.createdAt),
321
+ index('learnings_folder_idx').on(table.folderPath),
322
+ index('learnings_relevance_idx').on(table.relevanceScore),
323
+ index('learnings_private_idx').on(table.isPrivate),
324
+ index('learnings_memory_idx').on(table.memoryId),
325
+ ]);
326
+
327
+ /**
328
+ * Agent Preferences - learned agent preferences from learnings
329
+ * Enables agents to evolve and remember preferences over time
330
+ */
331
+ export const agentPreferences = sqliteTable('agent_preferences', {
332
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
333
+ projectId: text('project_id').references(() => projects.id, { onDelete: 'cascade' }).notNull(),
334
+
335
+ key: text('key').notNull(), // e.g., "prefer_bun", "prefer_typescript"
336
+ value: text('value').notNull(), // e.g., "bun", "true"
337
+
338
+ sourceMemoryId: text('source_memory_id').references(() => memories.id, { onDelete: 'set null' }),
339
+ confidence: text('confidence').default('0.5'), // 0.00 to 1.00
340
+ usageCount: integer('usage_count').default(1),
341
+
342
+ lastUpdated: integer('last_updated', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
343
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
344
+ }, (table) => [
345
+ index('agent_preferences_project_idx').on(table.projectId),
346
+ index('agent_preferences_key_idx').on(table.key),
347
+ ]);
348
+
349
+ /**
350
+ * Entities - named entities in the codebase
351
+ */
352
+ export const entities = sqliteTable('entities', {
353
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
354
+ projectId: text('project_id').references(() => projects.id, { onDelete: 'cascade' }),
355
+
356
+ name: text('name').notNull(),
357
+ type: text('type').notNull(),
358
+ description: text('description'),
359
+
360
+ embeddingJson: text('embedding_json'),
361
+ properties: text('properties').$type<Record<string, unknown>>(),
362
+
363
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
364
+ updatedAt: integer('updated_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
365
+ }, (table) => [
366
+ index('entities_project_idx').on(table.projectId),
367
+ index('entities_type_idx').on(table.type),
368
+ index('entities_name_idx').on(table.name),
369
+ ]);
370
+
371
+ /**
372
+ * Namespaces - Hierarchical folder-like namespaces for memory organization
373
+ */
374
+ export const namespaces: any = sqliteTable('namespaces', {
375
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
376
+ projectId: text('project_id').references(() => projects.id, { onDelete: 'cascade' }),
377
+
378
+ name: text('name').notNull(),
379
+ parentId: text('parent_id').references(() => namespaces.id, { onDelete: 'set null' }),
380
+ type: text('type'),
381
+ description: text('description'),
382
+
383
+ path: text('path'),
384
+
385
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
386
+ updatedAt: integer('updated_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
387
+ }, (table) => [
388
+ index('namespaces_project_idx').on(table.projectId),
389
+ index('namespaces_parent_idx').on(table.parentId),
390
+ ]);
391
+
392
+ /**
393
+ * Places - Spatial memory organization
394
+ */
395
+ export const places: any = sqliteTable('places', {
396
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
397
+ projectId: text('project_id').references(() => projects.id, { onDelete: 'cascade' }).notNull(),
398
+
399
+ name: text('name').notNull(),
400
+ placeType: text('place_type').notNull(),
401
+ parentId: text('parent_id').references(() => places.id, { onDelete: 'set null' }),
402
+
403
+ sortOrder: integer('sort_order').default(0),
404
+ positionX: integer('position_x').default(0),
405
+ positionY: integer('position_y').default(0),
406
+ description: text('description'),
407
+ purpose: text('purpose'),
408
+ memoryCount: integer('memory_count').default(0),
409
+
410
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
411
+ updatedAt: integer('updated_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
412
+ }, (table) => [
413
+ index('places_project_idx').on(table.projectId),
414
+ index('places_type_idx').on(table.placeType),
415
+ index('places_parent_idx').on(table.parentId),
416
+ index('places_sort_order_idx').on(table.projectId, table.sortOrder),
417
+ ]);
418
+
419
+ /**
420
+ * Memory-Place assignments
421
+ */
422
+ export const memoryPlaces: any = sqliteTable('memory_places', {
423
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
424
+ memoryId: text('memory_id').references(() => memories.id, { onDelete: 'cascade' }).notNull(),
425
+ placeId: text('place_id').references(() => places.id, { onDelete: 'cascade' }).notNull(),
426
+ isManual: integer('is_manual').default(0),
427
+ ruleId: text('rule_id'),
428
+
429
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
430
+ }, (table) => [
431
+ index('memory_places_memory_idx').on(table.memoryId),
432
+ index('memory_places_place_idx').on(table.placeId),
433
+ ]);
434
+
435
+ /**
436
+ * Place auto-assignment rules
437
+ */
438
+ export const placeRules: any = sqliteTable('place_rules', {
439
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
440
+ projectId: text('project_id').references(() => projects.id, { onDelete: 'cascade' }).notNull(),
441
+
442
+ name: text('name').notNull(),
443
+ placeType: text('place_type').notNull(),
444
+
445
+ matchTool: text('match_tool'),
446
+ matchKeyword: text('match_keyword'),
447
+ matchTag: text('match_tag'),
448
+ matchMemoryType: text('match_memory_type'),
449
+
450
+ priority: integer('priority').default(0),
451
+ enabled: integer('enabled').default(1),
452
+
453
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
454
+ updatedAt: integer('updated_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
455
+ }, (table) => [
456
+ index('place_rules_project_idx').on(table.projectId),
457
+ index('place_rules_type_idx').on(table.placeType),
458
+ ]);
459
+
460
+ /**
461
+ * Memory Layers - Tiered L0/L1/L2 summaries for token-efficient retrieval
462
+ */
463
+ export const memoryLayers = sqliteTable('memory_layers', {
464
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
465
+ memoryId: text('memory_id').references(() => memories.id, { onDelete: 'cascade' }),
466
+
467
+ layerType: text('layer_type').notNull().$type<'l0_abstract' | 'l1_overview' | 'l2_full'>(),
468
+ content: text('content').notNull(),
469
+ tokenCount: integer('token_count').default(0),
470
+
471
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
472
+ }, (table) => [
473
+ index('memory_layers_memory_idx').on(table.memoryId),
474
+ index('memory_layers_type_idx').on(table.layerType),
475
+ ]);
476
+
477
+ // Progressive Disclosure & Context Paging Tables
478
+ // ============================================================================
479
+
480
+ /**
481
+ * Lightweight memory indices for progressive disclosure - previews and metadata
482
+ * used for quick filtering before loading full memories
483
+ */
484
+ export const lightweightMemoryIndices = sqliteTable('lightweight_memory_indices', {
485
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
486
+ memoryId: text('memory_id').references(() => memories.id, { onDelete: 'cascade' }),
487
+
488
+ // Hash for quick comparison
489
+ contentHash: text('content_hash').notNull(),
490
+ contentPreview: text('content_preview').notNull(),
491
+ keyTerms: text('key_terms').$type<string[]>(),
492
+
493
+ // Categorization
494
+ category: text('category').notNull(),
495
+ importanceScore: integer('importance_score').notNull(),
496
+
497
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
498
+ }, (table) => [
499
+ index('lightweight_indices_memory_idx').on(table.memoryId),
500
+ index('lightweight_indices_category_idx').on(table.category),
501
+ index('lightweight_indices_importance_idx').on(table.importanceScore),
502
+ ]);
503
+
504
+ /**
505
+ * Context paging sessions for tracking loaded/preloaded memories
506
+ * Agent-controlled memory loading system
507
+ */
508
+ export const contextPagingSessions = sqliteTable('context_paging_sessions', {
509
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
510
+ sessionId: text('session_id').notNull().unique(),
511
+ projectId: text('project_id').references(() => projects.id, { onDelete: 'cascade' }),
512
+ userId: text('user_id').references(() => users.id, { onDelete: 'set null' }),
513
+
514
+ // Loaded memories (actively in context)
515
+ loadedMemoryIds: text('loaded_memory_ids').$type<string[]>().default([]),
516
+
517
+ // Preload candidates (ready to load if needed)
518
+ preloadCandidateIds: text('preload_candidate_ids').$type<string[]>().default([]),
519
+
520
+ // Token tracking
521
+ tokenBudget: integer('token_budget').default(8000).notNull(),
522
+ tokensUsed: integer('tokens_used').default(0).notNull(),
523
+ loadedMemoriesTokens: integer('loaded_memories_tokens').default(0).notNull(),
524
+
525
+ // Session metadata
526
+ metadata: text('metadata').$type<Record<string, unknown>>(),
527
+
528
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
529
+ updatedAt: integer('updated_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
530
+ }, (table) => [
531
+ index('context_paging_session_idx').on(table.sessionId),
532
+ index('context_paging_project_idx').on(table.projectId),
533
+ index('context_paging_created_idx').on(table.createdAt),
534
+ ]);
535
+
536
+ // Memory Merging Tables
537
+ // ============================================================================
538
+
539
+ /**
540
+ * Memory Merge Proposals - tracks suggested merges before user approval
541
+ */
542
+ export const memoryMergeProposals = sqliteTable('memory_merge_proposals', {
543
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
544
+ projectId: text('project_id').notNull().references(() => projects.id, { onDelete: 'cascade' }),
545
+ userId: text('user_id').references(() => users.id, { onDelete: 'set null' }),
546
+
547
+ sourceMemoryIds: text('source_memory_ids').$type<string[]>().notNull(),
548
+ proposedContent: text('proposed_content').notNull(),
549
+ proposedSummary: text('proposed_summary'),
550
+ proposedTags: text('proposed_tags').$type<string[]>(),
551
+ proposedMetadata: text('proposed_metadata').$type<Record<string, unknown>>(),
552
+
553
+ detectionMethod: text('detection_method').notNull().$type<'simhash' | 'minhash' | 'embedding'>(),
554
+ similarityScore: text('similarity_score').notNull(),
555
+ confidenceLevel: text('confidence_level').notNull().$type<'high' | 'medium' | 'low'>(),
556
+
557
+ mergeReason: text('merge_reason').notNull(),
558
+ conflictWarnings: text('conflict_warnings').$type<string[]>(),
559
+
560
+ status: text('status').$type<'pending' | 'approved' | 'rejected' | 'expired'>().default('pending').notNull(),
561
+ reviewedAt: integer('reviewed_at', { mode: 'timestamp' }),
562
+ reviewNotes: text('review_notes'),
563
+
564
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
565
+ expiresAt: integer('expires_at', { mode: 'timestamp' }),
566
+ }, (table) => [
567
+ index('memory_merge_proposals_project_status_idx').on(table.projectId, table.status),
568
+ index('memory_merge_proposals_created_at_idx').on(table.createdAt),
569
+ ]);
570
+
571
+ /**
572
+ * Memory Merge History - audit trail of completed merges
573
+ */
574
+ export const memoryMergeHistory = sqliteTable('memory_merge_history', {
575
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
576
+ projectId: text('project_id').notNull().references(() => projects.id, { onDelete: 'cascade' }),
577
+ userId: text('user_id').references(() => users.id, { onDelete: 'set null' }),
578
+
579
+ proposalId: text('proposal_id').references(() => memoryMergeProposals.id, { onDelete: 'set null' }),
580
+ sourceMemoryIds: text('source_memory_ids').$type<string[]>().notNull(),
581
+ canonicalMemoryId: text('canonical_memory_id').notNull().references(() => memories.id, { onDelete: 'cascade' }),
582
+
583
+ sourceMemoriesSnapshot: text('source_memories_snapshot').$type<Record<string, unknown>[]>().notNull(),
584
+
585
+ mergeStrategy: text('merge_strategy').notNull().$type<'union' | 'latest' | 'voting' | 'custom'>(),
586
+ tokensSaved: integer('tokens_saved'),
587
+
588
+ isReversed: integer('is_reversed', { mode: 'boolean' }).default(false),
589
+ reversedAt: integer('reversed_at', { mode: 'timestamp' }),
590
+ reversedBy: text('reversed_by'),
591
+
592
+ mergedAt: integer('merged_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
593
+ });
594
+
595
+ /**
596
+ * Memory Hash Cache - cached hash signatures for efficient duplicate detection
597
+ */
598
+ export const memoryHashCache = sqliteTable('memory_hash_cache', {
599
+ memoryId: text('memory_id').primaryKey().references(() => memories.id, { onDelete: 'cascade' }),
600
+ projectId: text('project_id').notNull().references(() => projects.id, { onDelete: 'cascade' }),
601
+
602
+ simhash: text('simhash'),
603
+ minhash: text('minhash').$type<number[]>(),
604
+
605
+ contentHash: text('content_hash').notNull(),
606
+ lastUpdated: integer('last_updated', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
607
+ }, (table) => [
608
+ index('memory_hash_cache_project_id_idx').on(table.projectId),
609
+ index('memory_hash_cache_simhash_idx').on(table.simhash),
610
+ ]);
611
+
612
+ /**
613
+ * Entity Relations - relationships between entities
614
+ */
615
+ export const entityRelations = sqliteTable('entity_relations', {
616
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
617
+ fromEntityId: text('from_entity_id').notNull().references(() => entities.id, { onDelete: 'cascade' }),
618
+ toEntityId: text('to_entity_id').notNull().references(() => entities.id, { onDelete: 'cascade' }),
619
+
620
+ type: text('type').notNull(),
621
+ weight: integer('weight').default(1),
622
+ properties: text('properties').$type<Record<string, unknown>>(),
623
+
624
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
625
+ }, (table) => [
626
+ index('relations_from_idx').on(table.fromEntityId),
627
+ index('relations_to_idx').on(table.toEntityId),
628
+ index('relations_type_idx').on(table.type),
629
+ ]);
630
+
631
+ // v0.3.0: Lifecycle Features - Associations, Summarization, Snapshots
632
+ // ============================================================================
633
+
634
+ /**
635
+ * Memory Associations - waypoint graph for co-activation tracking
636
+ */
637
+ export const memoryAssociations = sqliteTable('memory_associations', {
638
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
639
+ fromMemoryId: text('from_memory_id').notNull().references(() => memories.id, { onDelete: 'cascade' }),
640
+ toMemoryId: text('to_memory_id').notNull().references(() => memories.id, { onDelete: 'cascade' }),
641
+ associationType: text('association_type').notNull().$type<'co_occurred' | 'supersedes' | 'contradicts' | 'supports' | 'relates_to'>(),
642
+ weight: integer('weight').default(1),
643
+ coactivationCount: integer('coactivation_count').default(0),
644
+ metadata: text('metadata').$type<Record<string, unknown>>(),
645
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
646
+ lastCoactivatedAt: integer('last_coactivated_at', { mode: 'timestamp' }),
647
+ }, (table) => [
648
+ index('memory_associations_from_idx').on(table.fromMemoryId),
649
+ index('memory_associations_to_idx').on(table.toMemoryId),
650
+ index('memory_associations_type_idx').on(table.associationType),
651
+ index('memory_associations_weight_idx').on(table.weight),
652
+ // v0.4.2: Composite index for graph traversal optimization
653
+ index('memory_associations_graph_traversal_idx').on(
654
+ table.fromMemoryId,
655
+ table.toMemoryId,
656
+ table.weight,
657
+ table.associationType
658
+ ),
659
+ ]);
660
+
661
+ /**
662
+ * Session Summaries - incremental and rolling session summaries
663
+ */
664
+ export const sessionSummaries = sqliteTable('session_summaries', {
665
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
666
+ conversationId: text('conversation_id').notNull().references(() => conversations.id, { onDelete: 'cascade' }),
667
+ projectId: text('project_id').references(() => projects.id, { onDelete: 'cascade' }),
668
+ summaryType: text('summary_type').notNull().$type<'incremental' | 'rolling' | 'final'>(),
669
+ content: text('content').notNull(),
670
+ compressedFrom: integer('compressed_from'),
671
+ tokensSaved: integer('tokens_saved'),
672
+ embedding: blob('embedding'),
673
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
674
+ }, (table) => [
675
+ index('session_summaries_conversation_idx').on(table.conversationId),
676
+ index('session_summaries_project_idx').on(table.projectId),
677
+ index('session_summaries_type_idx').on(table.summaryType),
678
+ index('session_summaries_created_idx').on(table.createdAt),
679
+ ]);
680
+
681
+ /**
682
+ * Memory Snapshots - before/after diffs for auditability
683
+ */
684
+ export const memorySnapshots = sqliteTable('memory_snapshots', {
685
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
686
+ memoryId: text('memory_id').notNull().references(() => memories.id, { onDelete: 'cascade' }),
687
+ snapshotType: text('snapshot_type').notNull().$type<'before_update' | 'after_update' | 'periodic'>(),
688
+ content: text('content').notNull(),
689
+ metadata: text('metadata').$type<Record<string, unknown>>(),
690
+ diff: text('diff').$type<Record<string, unknown>>(),
691
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
692
+ }, (table) => [
693
+ index('memory_snapshots_memory_idx').on(table.memoryId),
694
+ index('memory_snapshots_type_idx').on(table.snapshotType),
695
+ index('memory_snapshots_created_idx').on(table.createdAt),
696
+ ]);
697
+
698
+ /**
699
+ * Core Memory - Always-in-context memory (Tier 1)
700
+ * Small, persistent, always-visible memory block (< 2KB total)
701
+ */
702
+ export const coreMemory = sqliteTable('core_memory', {
703
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
704
+ projectId: text('project_id').references(() => projects.id, { onDelete: 'cascade' }),
705
+ userId: text('user_id').references(() => users.id, { onDelete: 'set null' }),
706
+
707
+ // Core memory sections
708
+ section: text('section').notNull().$type<'persona' | 'user_info' | 'project_context' | 'working_notes'>(),
709
+ content: text('content').notNull().default(''),
710
+ sizeBytes: integer('size_bytes').default(0).notNull(),
711
+ tokensEstimate: integer('tokens_estimate').default(0).notNull(),
712
+
713
+ // Version tracking
714
+ version: integer('version').default(1).notNull(),
715
+
716
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
717
+ updatedAt: integer('updated_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
718
+ }, (table) => [
719
+ index('core_memory_project_idx').on(table.projectId),
720
+ index('core_memory_user_idx').on(table.userId),
721
+ index('core_memory_section_idx').on(table.section),
722
+ ]);
723
+
724
+ /**
725
+ * Context Sessions - Track loaded memories and context window usage
726
+ */
727
+ export const contextSessions = sqliteTable('context_sessions', {
728
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
729
+ sessionId: text('session_id').notNull().unique(),
730
+ projectId: text('project_id').references(() => projects.id, { onDelete: 'cascade' }),
731
+ userId: text('user_id').references(() => users.id, { onDelete: 'set null' }),
732
+
733
+ // Loaded memories (paging system)
734
+ loadedMemoryIds: text('loaded_memory_ids').$type<string[]>().default([]),
735
+
736
+ // Token tracking
737
+ tokenBudget: integer('token_budget').default(8000).notNull(),
738
+ tokensUsed: integer('tokens_used').default(0).notNull(),
739
+ coreMemoryTokens: integer('core_memory_tokens').default(0).notNull(),
740
+ loadedMemoriesTokens: integer('loaded_memories_tokens').default(0).notNull(),
741
+
742
+ // Session metadata
743
+ metadata: text('metadata').$type<Record<string, unknown>>(),
744
+
745
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
746
+ updatedAt: integer('updated_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
747
+ }, (table) => [
748
+ index('context_sessions_session_idx').on(table.sessionId),
749
+ index('context_sessions_project_idx').on(table.projectId),
750
+ index('context_sessions_created_idx').on(table.createdAt),
751
+ ]);
752
+
753
+ // Types
754
+ // ============================================================================
755
+
756
+ export type User = typeof users.$inferSelect;
757
+ export type NewUser = typeof users.$inferInsert;
758
+
759
+ export type Project = typeof projects.$inferSelect;
760
+ export type NewProject = typeof projects.$inferInsert;
761
+
762
+ export type Memory = typeof memories.$inferSelect;
763
+ export type NewMemory = typeof memories.$inferInsert;
764
+
765
+ export type Conversation = typeof conversations.$inferSelect;
766
+ export type NewConversation = typeof conversations.$inferInsert;
767
+
768
+ export type Message = typeof messages.$inferSelect;
769
+ export type NewMessage = typeof messages.$inferInsert;
770
+
771
+ export type Learning = typeof learnings.$inferSelect;
772
+ export type NewLearning = typeof learnings.$inferInsert;
773
+
774
+ export type AgentPreference = typeof agentPreferences.$inferSelect;
775
+ export type NewAgentPreference = typeof agentPreferences.$inferInsert;
776
+
777
+ export type Entity = typeof entities.$inferSelect;
778
+ export type NewEntity = typeof entities.$inferInsert;
779
+
780
+ export type EntityRelation = typeof entityRelations.$inferSelect;
781
+ export type NewEntityRelation = typeof entityRelations.$inferInsert;
782
+
783
+ export type MemoryMergeProposal = typeof memoryMergeProposals.$inferSelect;
784
+ export type NewMemoryMergeProposal = typeof memoryMergeProposals.$inferInsert;
785
+
786
+ export type MemoryMergeHistory = typeof memoryMergeHistory.$inferSelect;
787
+ export type NewMemoryMergeHistory = typeof memoryMergeHistory.$inferInsert;
788
+
789
+ export type MemoryHashCache = typeof memoryHashCache.$inferSelect;
790
+ export type NewMemoryHashCache = typeof memoryHashCache.$inferInsert;
791
+
792
+ export type MemoryAssociation = typeof memoryAssociations.$inferSelect;
793
+ export type NewMemoryAssociation = typeof memoryAssociations.$inferInsert;
794
+
795
+ export type SessionSummary = typeof sessionSummaries.$inferSelect;
796
+ export type NewSessionSummary = typeof sessionSummaries.$inferInsert;
797
+
798
+ export type MemorySnapshot = typeof memorySnapshots.$inferSelect;
799
+ export type NewMemorySnapshot = typeof memorySnapshots.$inferInsert;
800
+
801
+ export type CoreMemory = typeof coreMemory.$inferSelect;
802
+ export type NewCoreMemory = typeof coreMemory.$inferInsert;
803
+
804
+ export type ContextSession = typeof contextSessions.$inferSelect;
805
+ export type NewContextSession = typeof contextSessions.$inferInsert;
806
+
807
+ // v0.10.0: Echo/Fizzle Tracking & Scheduled Maintenance
808
+ // ============================================================================
809
+
810
+ export const memoryFeedback = sqliteTable('memory_feedback', {
811
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
812
+ memoryId: text('memory_id').notNull().references(() => memories.id, { onDelete: 'cascade' }),
813
+ sessionId: text('session_id').notNull(),
814
+ conversationId: text('conversation_id').references(() => conversations.id, { onDelete: 'set null' }),
815
+ wasInjected: integer('was_injected', { mode: 'boolean' }).default(false),
816
+ wasReferenced: integer('was_referenced', { mode: 'boolean' }).default(false),
817
+ referenceCount: integer('reference_count').default(0),
818
+ retrievalPriorityDelta: integer('retrieval_priority_delta').default(0),
819
+ injectedAt: integer('injected_at', { mode: 'timestamp' }),
820
+ referencedAt: integer('referenced_at', { mode: 'timestamp' }),
821
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
822
+ }, (table) => [
823
+ index('memory_feedback_memory_idx').on(table.memoryId),
824
+ index('memory_feedback_session_idx').on(table.sessionId),
825
+ index('memory_feedback_referenced_idx').on(table.wasReferenced),
826
+ index('memory_feedback_conversation_idx').on(table.conversationId),
827
+ ]);
828
+
829
+ export const maintenanceJobs = sqliteTable('maintenance_jobs', {
830
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
831
+ jobName: text('job_name').notNull().unique(),
832
+ jobType: text('job_type').notNull().$type<'nightly' | 'weekly' | 'hourly'>(),
833
+ cronExpression: text('cron_expression'),
834
+ enabled: integer('enabled', { mode: 'boolean' }).default(true),
835
+ lastRunAt: integer('last_run_at', { mode: 'timestamp' }),
836
+ nextRunAt: integer('next_run_at', { mode: 'timestamp' }),
837
+ lastRunDuration: integer('last_run_duration'),
838
+ lastRunStatus: text('last_run_status').$type<'success' | 'failed' | 'skipped'>(),
839
+ lastRunError: text('last_run_error'),
840
+ totalRuns: integer('total_runs').default(0),
841
+ successCount: integer('success_count').default(0),
842
+ failureCount: integer('failure_count').default(0),
843
+ jobConfig: text('job_config').$type<Record<string, unknown>>(),
844
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
845
+ updatedAt: integer('updated_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
846
+ }, (table) => [
847
+ index('maintenance_jobs_name_idx').on(table.jobName),
848
+ index('maintenance_jobs_next_run_idx').on(table.nextRunAt),
849
+ index('maintenance_jobs_type_idx').on(table.jobType),
850
+ index('maintenance_jobs_enabled_idx').on(table.enabled),
851
+ ]);
852
+
853
+ export const maintenanceJobHistory = sqliteTable('maintenance_job_history', {
854
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
855
+ jobId: text('job_id').notNull().references(() => maintenanceJobs.id, { onDelete: 'cascade' }),
856
+ startedAt: integer('started_at', { mode: 'timestamp' }).notNull(),
857
+ completedAt: integer('completed_at', { mode: 'timestamp' }),
858
+ duration: integer('duration'),
859
+ status: text('status').notNull().$type<'success' | 'failed' | 'skipped'>(),
860
+ error: text('error'),
861
+ recordsProcessed: integer('records_processed').default(0),
862
+ resultSummary: text('result_summary').$type<Record<string, unknown>>(),
863
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
864
+ }, (table) => [
865
+ index('maintenance_job_history_job_idx').on(table.jobId),
866
+ index('maintenance_job_history_started_idx').on(table.startedAt),
867
+ index('maintenance_job_history_status_idx').on(table.status),
868
+ ]);
869
+
870
+ export type MemoryFeedback = typeof memoryFeedback.$inferSelect;
871
+ export type NewMemoryFeedback = typeof memoryFeedback.$inferInsert;
872
+
873
+ export type MaintenanceJob = typeof maintenanceJobs.$inferSelect;
874
+ export type NewMaintenanceJob = typeof maintenanceJobs.$inferInsert;
875
+
876
+ export type MaintenanceJobHistory = typeof maintenanceJobHistory.$inferSelect;
877
+ export type NewMaintenanceJobHistory = typeof maintenanceJobHistory.$inferInsert;
878
+
879
+ export type LightweightMemoryIndex = typeof lightweightMemoryIndices.$inferSelect;
880
+ export type NewLightweightMemoryIndex = typeof lightweightMemoryIndices.$inferInsert;
881
+
882
+ export type ContextPagingSession = typeof contextPagingSessions.$inferSelect;
883
+ export type NewContextPagingSession = typeof contextPagingSessions.$inferInsert;
884
+
885
+ // Memory Editing Tables (SQLite)
886
+ // ============================================================================
887
+
888
+ export const memoryEditProposals = sqliteTable('memory_edit_proposals', {
889
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
890
+ projectId: text('project_id').notNull().references(() => projects.id, { onDelete: 'cascade' }),
891
+ userId: text('user_id').references(() => users.id, { onDelete: 'set null' }),
892
+
893
+ memoryId: text('memory_id').notNull().references(() => memories.id, { onDelete: 'cascade' }),
894
+
895
+ currentContent: text('current_content').notNull(),
896
+ proposedContent: text('proposed_content').notNull(),
897
+
898
+ reason: text('reason').notNull(),
899
+ conflictWarnings: text('conflict_warnings').$type<string[]>(),
900
+ status: text('status').$type<'pending' | 'approved' | 'rejected' | 'expired'>().default('pending').notNull(),
901
+
902
+ version: integer('version').default(1).notNull(),
903
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
904
+ reviewedAt: integer('reviewed_at', { mode: 'timestamp' }),
905
+ reviewNotes: text('review_notes'),
906
+ }, (table) => [
907
+ index('memory_edit_proposals_memory_idx').on(table.memoryId),
908
+ index('memory_edit_proposals_status_idx').on(table.status),
909
+ index('memory_edit_proposals_created_at_idx').on(table.createdAt),
910
+ ]);
911
+
912
+ export type MemoryEditProposal = typeof memoryEditProposals.$inferSelect;
913
+ export type NewMemoryEditProposal = typeof memoryEditProposals.$inferInsert;
914
+
915
+ export type SearchTrace = typeof searchTraces.$inferSelect;
916
+
917
+ // Phase 3: Retrieval Tracing - Search Traces table
918
+ // ============================================================================
919
+
920
+ /**
921
+ * Search Traces - Stores retrieval logs for debugging and performance analysis
922
+ */
923
+ export const searchTraces = sqliteTable('search_traces', {
924
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
925
+ sessionId: text('session_id').notNull(),
926
+ query: text('query').notNull(),
927
+ timestamp: integer('timestamp', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
928
+
929
+ // Search pipeline stages (JSONB stored as text for SQLite)
930
+ queryRewrite: text('query_rewrite').$type<string | null>(),
931
+ candidateRetrieval: text('candidate_retrieval').$type<string | null>(),
932
+ entityFiltering: text('entity_filtering').$type<string | null>(),
933
+ hybridScoring: text('hybrid_scoring').$type<string | null>(),
934
+ reranking: text('reranking').$type<string | null>(),
935
+
936
+ // Final results
937
+ resultCount: integer('result_count').default(0),
938
+ topResults: text('top_results').$type<string | null>(),
939
+
940
+ // Performance metrics
941
+ totalDurationMs: integer('total_duration_ms').default(0),
942
+ metadata: text('metadata').$type<string | null>(),
943
+ }, (table) => [
944
+ index('search_traces_session_idx').on(table.sessionId),
945
+ index('search_traces_timestamp_idx').on(table.timestamp),
946
+ ]);
947
+
948
+ // Belief Systems - Derived Beliefs from Memory
949
+ // ============================================================================
950
+
951
+ /**
952
+ * Beliefs - Derived semantic beliefs extracted from memories
953
+ * Represents inferred decisions, preferences, constraints, failure causes
954
+ */
955
+ export const beliefs = sqliteTable('beliefs', {
956
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
957
+ projectId: text('project_id').references(() => projects.id, { onDelete: 'cascade' }),
958
+
959
+ // Belief identification
960
+ beliefType: text('belief_type').notNull().$type<BeliefType>(),
961
+ statement: text('statement').notNull(),
962
+ normalizedKey: text('normalized_key').notNull(),
963
+
964
+ // Confidence and decay
965
+ confidence: integer('confidence').default(50), // 0-100
966
+ beliefDecayRate: integer('belief_decay_rate').default(30), // days half-life
967
+ lastConfirmedAt: integer('last_confirmed_at', { mode: 'timestamp' }),
968
+ sourceCount: integer('source_count').default(1),
969
+
970
+ // Status
971
+ status: text('status').$type<BeliefStatus>().default('active'),
972
+
973
+ // Context and evidence
974
+ reason: text('reason'),
975
+ context: text('context'),
976
+ evidenceSummary: text('evidence_summary'),
977
+
978
+ // Metadata (stores edges, derivation info)
979
+ metadata: text('metadata').$type<Record<string, unknown>>(),
980
+
981
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
982
+ updatedAt: integer('updated_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
983
+ }, (table) => [
984
+ index('beliefs_project_idx').on(table.projectId),
985
+ index('beliefs_type_idx').on(table.beliefType),
986
+ index('beliefs_status_idx').on(table.status),
987
+ index('beliefs_confidence_idx').on(table.confidence),
988
+ index('beliefs_normalized_key_idx').on(table.normalizedKey),
989
+ ]);
990
+
991
+ /**
992
+ * Belief Memory Sources - Links beliefs to source memories
993
+ */
994
+ export const beliefMemorySources = sqliteTable('belief_memory_sources', {
995
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
996
+ beliefId: text('belief_id').references(() => beliefs.id, { onDelete: 'cascade' }).notNull(),
997
+ memoryId: text('memory_id').references(() => memories.id, { onDelete: 'cascade' }).notNull(),
998
+
999
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
1000
+ }, (table) => [
1001
+ index('belief_sources_belief_idx').on(table.beliefId),
1002
+ index('belief_sources_memory_idx').on(table.memoryId),
1003
+ ]);
1004
+
1005
+ /**
1006
+ * Belief Edges - Relationships between beliefs
1007
+ */
1008
+ export const beliefEdges = sqliteTable('belief_edges', {
1009
+ id: text('id').primaryKey().$default(() => crypto.randomUUID()),
1010
+ fromBeliefId: text('from_belief_id').references(() => beliefs.id, { onDelete: 'cascade' }).notNull(),
1011
+ toBeliefId: text('to_belief_id').references(() => beliefs.id, { onDelete: 'cascade' }).notNull(),
1012
+
1013
+ edgeType: text('edge_type').notNull().$type<BeliefEdgeType>(),
1014
+ metadata: text('metadata').$type<Record<string, unknown>>(),
1015
+
1016
+ createdAt: integer('created_at', { mode: 'timestamp' }).default(sql`CURRENT_TIMESTAMP`).notNull(),
1017
+ }, (table) => [
1018
+ index('belief_edges_from_idx').on(table.fromBeliefId),
1019
+ index('belief_edges_to_idx').on(table.toBeliefId),
1020
+ ]);
1021
+
1022
+ // Belief Types (re-exported for schema)
1023
+ export type BeliefType = 'decision' | 'preference' | 'failure_cause' | 'constraint' | 'state_change' | 'dispute';
1024
+ export type BeliefStatus = 'active' | 'superseded' | 'disputed';
1025
+ export type BeliefEdgeType = 'causes' | 'supports' | 'rejects' | 'supersedes' | 'depends_on';
1026
+
1027
+ export type Belief = typeof beliefs.$inferSelect;
1028
+ export type NewBelief = typeof beliefs.$inferInsert;
1029
+ export type BeliefMemorySource = typeof beliefMemorySources.$inferSelect;
1030
+ export type NewBeliefMemorySource = typeof beliefMemorySources.$inferInsert;
1031
+ export type BeliefEdge = typeof beliefEdges.$inferSelect;
1032
+ export type NewBeliefEdge = typeof beliefEdges.$inferInsert;