squish-memory 1.0.2 → 1.1.5

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 (341) hide show
  1. package/.env.example +130 -0
  2. package/CHANGELOG.md +55 -0
  3. package/README.md +150 -287
  4. package/config/hooks/claude-code-hooks.json +39 -0
  5. package/config/hooks/cursor-hooks.json +30 -0
  6. package/config/hooks/opencode-hooks.json +30 -0
  7. package/config/hooks/windsurf-hooks.json +30 -0
  8. package/config/mcp-mode-semantics.json +23 -21
  9. package/config/plugin-manifest.json +101 -152
  10. package/{plugin.json → config/plugin.json} +2 -2
  11. package/config/settings.json +52 -51
  12. package/{commands → core/commands}/init.md +39 -39
  13. package/dist/config.d.ts +28 -4
  14. package/dist/config.js +97 -29
  15. package/dist/core/adapters/config/claude-code.d.ts +45 -0
  16. package/dist/core/adapters/config/claude-code.js +113 -0
  17. package/dist/core/adapters/config/cursor.d.ts +26 -0
  18. package/dist/core/adapters/config/cursor.js +74 -0
  19. package/dist/core/adapters/config/opencode.d.ts +23 -0
  20. package/dist/core/adapters/config/opencode.js +73 -0
  21. package/dist/core/adapters/config/windsurf.d.ts +26 -0
  22. package/dist/core/adapters/config/windsurf.js +74 -0
  23. package/dist/core/adapters/index.d.ts +45 -0
  24. package/dist/core/adapters/index.js +84 -0
  25. package/dist/core/adapters/scripts/install-adapter.d.ts +19 -0
  26. package/dist/core/adapters/scripts/install-adapter.js +149 -0
  27. package/dist/core/adapters/timeline.d.ts +23 -0
  28. package/dist/core/adapters/timeline.js +88 -0
  29. package/dist/core/adapters/types.d.ts +157 -0
  30. package/dist/core/adapters/types.js +50 -0
  31. package/dist/{algorithms → core/algorithms}/analytics/token-estimator.d.ts +1 -1
  32. package/dist/{algorithms → core/algorithms}/analytics/token-estimator.js +3 -3
  33. package/dist/{algorithms → core/algorithms}/detection/semantic-ranker.d.ts +1 -1
  34. package/dist/{algorithms → core/algorithms}/detection/semantic-ranker.js +1 -1
  35. package/dist/{algorithms → core/algorithms}/detection/two-stage-detector.d.ts +1 -1
  36. package/dist/{algorithms → core/algorithms}/detection/two-stage-detector.js +7 -10
  37. package/dist/{algorithms → core/algorithms}/handlers/approve-merge.js +4 -4
  38. package/dist/{algorithms → core/algorithms}/handlers/detect-duplicates.js +3 -3
  39. package/dist/{algorithms → core/algorithms}/handlers/get-stats.js +3 -3
  40. package/dist/{algorithms → core/algorithms}/handlers/list-proposals.js +3 -3
  41. package/dist/{algorithms → core/algorithms}/handlers/preview-merge.js +3 -3
  42. package/dist/{algorithms → core/algorithms}/handlers/reject-merge.js +3 -3
  43. package/dist/{algorithms → core/algorithms}/handlers/reverse-merge.js +3 -3
  44. package/dist/core/algorithms/index.d.ts +21 -0
  45. package/dist/core/algorithms/index.js +26 -0
  46. package/dist/core/algorithms/operations/cache-maintenance.d.ts +12 -0
  47. package/dist/core/algorithms/operations/cache-maintenance.js +157 -0
  48. package/dist/{algorithms → core/algorithms}/safety/safety-checks.d.ts +1 -1
  49. package/dist/{algorithms → core/algorithms}/strategies/merge-strategies.d.ts +19 -1
  50. package/dist/{algorithms → core/algorithms}/strategies/merge-strategies.js +74 -123
  51. package/dist/core/algorithms/types.d.ts +133 -0
  52. package/dist/core/algorithms/types.js +5 -0
  53. package/dist/core/associations.d.ts +1 -2
  54. package/dist/core/associations.js +1 -2
  55. package/dist/core/autosave.d.ts +19 -0
  56. package/dist/core/autosave.js +16 -0
  57. package/dist/{commands → core/commands}/managed-sync.js +5 -5
  58. package/dist/core/commands/mcp-server.js +739 -0
  59. package/dist/core/context/agent-context.d.ts +106 -0
  60. package/dist/core/context/agent-context.js +274 -0
  61. package/dist/core/{context-paging.d.ts → context/context-paging.d.ts} +2 -12
  62. package/dist/core/{context-paging.js → context/context-paging.js} +19 -39
  63. package/dist/core/context/context-window.d.ts +40 -0
  64. package/dist/core/context/context-window.js +177 -0
  65. package/dist/core/context/context.js +22 -0
  66. package/dist/core/embeddings.d.ts +1 -1
  67. package/dist/core/embeddings.js +54 -2
  68. package/dist/core/error-handling.d.ts +63 -0
  69. package/dist/core/error-handling.js +173 -0
  70. package/dist/core/external-folder/index.d.ts +102 -0
  71. package/dist/core/external-folder/index.js +294 -0
  72. package/dist/core/hooks/agent-hooks.d.ts +74 -0
  73. package/dist/core/hooks/agent-hooks.js +244 -0
  74. package/dist/core/hooks/auto-tagger.d.ts +19 -0
  75. package/dist/core/hooks/auto-tagger.js +155 -0
  76. package/dist/core/hooks/capture-filter.d.ts +41 -0
  77. package/dist/core/hooks/capture-filter.js +128 -0
  78. package/dist/core/index.d.ts +6 -6
  79. package/dist/core/index.js +6 -6
  80. package/dist/core/{agent-memory.js → ingestion/agent-memory.js} +5 -7
  81. package/dist/core/{core-memory.js → ingestion/core-memory.js} +4 -4
  82. package/dist/core/ingestion/learnings.d.ts +57 -0
  83. package/dist/core/ingestion/learnings.js +202 -0
  84. package/dist/core/lib/db-client.d.ts +114 -0
  85. package/dist/core/lib/db-client.js +130 -0
  86. package/dist/core/lib/schemas.d.ts +129 -0
  87. package/dist/core/lib/schemas.js +87 -0
  88. package/dist/core/{utils.d.ts → lib/utils.d.ts} +1 -0
  89. package/dist/core/{utils.js → lib/utils.js} +31 -15
  90. package/dist/core/lib/validation.d.ts +38 -0
  91. package/dist/core/lib/validation.js +151 -0
  92. package/dist/core/lifecycle.d.ts +7 -0
  93. package/dist/core/lifecycle.js +140 -20
  94. package/dist/core/local-embeddings.d.ts +6 -1
  95. package/dist/core/local-embeddings.js +6 -15
  96. package/dist/core/logger.js +7 -1
  97. package/dist/core/mcp/tools.js +35 -3
  98. package/dist/core/memory/categorizer.js +1 -0
  99. package/dist/core/memory/conflict-detector.js +1 -1
  100. package/dist/core/memory/consolidation.d.ts +1 -10
  101. package/dist/core/memory/consolidation.js +2 -11
  102. package/dist/core/memory/context-collector.js +1 -1
  103. package/dist/core/memory/edit-workflow.js +1 -1
  104. package/dist/core/memory/entity-resolver.js +7 -7
  105. package/dist/core/memory/fact-extractor.js +12 -12
  106. package/dist/core/memory/feedback-tracker.js +1 -1
  107. package/dist/core/memory/hooks.d.ts +88 -0
  108. package/dist/core/memory/hooks.js +174 -0
  109. package/dist/core/memory/hybrid-retrieval.js +2 -2
  110. package/dist/core/memory/hybrid-search.d.ts +1 -6
  111. package/dist/core/memory/hybrid-search.js +70 -84
  112. package/dist/core/memory/importance.d.ts +8 -13
  113. package/dist/core/memory/importance.js +47 -74
  114. package/dist/core/memory/loader.d.ts +31 -0
  115. package/dist/core/memory/loader.js +141 -0
  116. package/dist/core/memory/markdown/markdown-storage.d.ts +72 -0
  117. package/dist/core/memory/markdown/markdown-storage.js +243 -0
  118. package/dist/core/memory/memories.d.ts +12 -4
  119. package/dist/core/memory/memories.js +192 -180
  120. package/dist/core/memory/memory-lifecycle.d.ts +8 -0
  121. package/dist/core/memory/memory-lifecycle.js +55 -0
  122. package/dist/core/memory/migrate.d.ts +21 -0
  123. package/dist/core/memory/migrate.js +134 -0
  124. package/dist/core/memory/normalization.d.ts +22 -0
  125. package/dist/core/memory/normalization.js +26 -0
  126. package/dist/core/memory/progressive-disclosure.js +1 -1
  127. package/dist/core/memory/query-rewriter.js +9 -9
  128. package/dist/core/memory/serialization.d.ts +4 -0
  129. package/dist/core/memory/serialization.js +49 -0
  130. package/dist/core/memory/stats.d.ts +5 -0
  131. package/dist/core/memory/stats.js +63 -12
  132. package/dist/core/memory/temporal-facts.js +21 -0
  133. package/dist/core/memory/write-gate.js +1 -1
  134. package/dist/core/obsidian-vault.d.ts +30 -0
  135. package/dist/core/obsidian-vault.js +94 -0
  136. package/dist/core/places/index.d.ts +14 -0
  137. package/dist/core/places/index.js +14 -0
  138. package/dist/core/places/memory-places.d.ts +68 -0
  139. package/dist/core/places/memory-places.js +261 -0
  140. package/dist/core/places/places.d.ts +88 -0
  141. package/dist/core/places/places.js +314 -0
  142. package/dist/core/places/rules.d.ts +74 -0
  143. package/dist/core/places/rules.js +240 -0
  144. package/dist/core/places/walking.d.ts +56 -0
  145. package/dist/core/places/walking.js +121 -0
  146. package/dist/core/projects.d.ts +5 -0
  147. package/dist/core/projects.js +39 -18
  148. package/dist/core/responses.d.ts +96 -0
  149. package/dist/core/responses.js +122 -0
  150. package/dist/core/scheduler/cron-scheduler.js +29 -7
  151. package/dist/core/scheduler/index.d.ts +1 -1
  152. package/dist/core/scheduler/index.js +1 -1
  153. package/dist/core/scheduler/job-runner.js +1 -1
  154. package/dist/core/search/conversations.js +40 -42
  155. package/dist/core/search/entities.js +6 -9
  156. package/dist/core/search/graph-boost.d.ts +7 -0
  157. package/dist/core/search/graph-boost.js +23 -0
  158. package/dist/core/search/qmd-search.js +4 -4
  159. package/dist/core/security/encrypt.d.ts +6 -0
  160. package/dist/core/security/encrypt.js +47 -0
  161. package/dist/core/{governance.d.ts → security/governance.d.ts} +6 -1
  162. package/dist/core/security/governance.js +79 -0
  163. package/dist/core/session/auto-load.js +6 -6
  164. package/dist/core/session/index.d.ts +1 -1
  165. package/dist/core/session/index.js +1 -1
  166. package/dist/core/session/self-iteration-job.d.ts +20 -0
  167. package/dist/core/session/self-iteration-job.js +282 -0
  168. package/dist/core/session/session-hooks.d.ts +18 -0
  169. package/dist/core/session/session-hooks.js +58 -0
  170. package/dist/core/session-hooks/self-iteration-job.js +35 -35
  171. package/dist/core/{cache.js → storage/cache.js} +2 -2
  172. package/dist/core/sync/qmd-sync.d.ts +1 -13
  173. package/dist/core/sync/qmd-sync.js +1 -13
  174. package/dist/core/toon.d.ts +43 -0
  175. package/dist/core/toon.js +160 -0
  176. package/dist/core/utils/memory-operations.js +1 -1
  177. package/dist/core/utils/vector-operations.d.ts +71 -0
  178. package/dist/core/utils/vector-operations.js +129 -0
  179. package/dist/db/adapter.d.ts +3 -3
  180. package/dist/db/adapter.js +99 -88
  181. package/dist/db/bootstrap.js +820 -522
  182. package/dist/{drizzle → db/drizzle}/schema-sqlite.d.ts +74 -25
  183. package/dist/{drizzle → db/drizzle}/schema-sqlite.js +91 -24
  184. package/dist/{drizzle → db/drizzle}/schema.d.ts +79 -32
  185. package/dist/{drizzle → db/drizzle}/schema.js +106 -35
  186. package/dist/db/drizzle.config.d.ts +3 -0
  187. package/dist/db/drizzle.config.js +12 -0
  188. package/dist/db/index.d.ts +1 -5
  189. package/dist/db/index.js +51 -8
  190. package/dist/db/neon.d.ts +8 -0
  191. package/dist/db/neon.js +20 -0
  192. package/dist/db/schema/index.d.ts +40 -0
  193. package/dist/db/schema/index.js +105 -0
  194. package/dist/db/schema/tables/context-sessions.d.ts +9 -0
  195. package/dist/db/schema/tables/context-sessions.js +37 -0
  196. package/dist/db/schema/tables/conversations.d.ts +9 -0
  197. package/dist/db/schema/tables/conversations.js +47 -0
  198. package/dist/db/schema/tables/core-memory.d.ts +9 -0
  199. package/dist/db/schema/tables/core-memory.js +41 -0
  200. package/dist/db/schema/tables/entities.d.ts +9 -0
  201. package/dist/db/schema/tables/entities.js +39 -0
  202. package/dist/db/schema/tables/entity-relations.d.ts +9 -0
  203. package/dist/db/schema/tables/entity-relations.js +31 -0
  204. package/dist/db/schema/tables/learnings.d.ts +9 -0
  205. package/dist/db/schema/tables/learnings.js +66 -0
  206. package/dist/db/schema/tables/memories.d.ts +9 -0
  207. package/dist/db/schema/tables/memories.js +161 -0
  208. package/dist/db/schema/tables/memory-associations.d.ts +9 -0
  209. package/dist/db/schema/tables/memory-associations.js +39 -0
  210. package/dist/db/schema/tables/memory-hash-cache.d.ts +9 -0
  211. package/dist/db/schema/tables/memory-hash-cache.js +29 -0
  212. package/dist/db/schema/tables/memory-merge-history.d.ts +9 -0
  213. package/dist/db/schema/tables/memory-merge-history.js +33 -0
  214. package/dist/db/schema/tables/memory-merge-proposals.d.ts +9 -0
  215. package/dist/db/schema/tables/memory-merge-proposals.js +39 -0
  216. package/dist/db/schema/tables/messages.d.ts +9 -0
  217. package/dist/db/schema/tables/messages.js +41 -0
  218. package/dist/db/schema/tables/namespaces.d.ts +9 -0
  219. package/dist/db/schema/tables/namespaces.js +37 -0
  220. package/dist/db/schema/tables/projects.d.ts +9 -0
  221. package/dist/db/schema/tables/projects.js +31 -0
  222. package/dist/db/schema/tables/users.d.ts +9 -0
  223. package/dist/db/schema/tables/users.js +27 -0
  224. package/dist/db/schema.d.ts +1 -1
  225. package/dist/db/schema.js +2 -2
  226. package/dist/db/supabase.d.ts +9 -0
  227. package/dist/db/supabase.js +24 -0
  228. package/dist/index.d.ts +2 -14
  229. package/dist/index.js +1320 -640
  230. package/dist/vendor/sql.js/sql-wasm.wasm +0 -0
  231. package/dist/webui/server.d.ts +5 -0
  232. package/dist/{api/web/web.js → webui/server.js} +511 -508
  233. package/generated/mcp/manifest.json +1 -1
  234. package/{.mcp.json → mcp.json.example} +1 -1
  235. package/package.json +159 -181
  236. package/scripts/README.md +60 -0
  237. package/scripts/copy-runtime-assets.mjs +26 -0
  238. package/scripts/generate-mcp.mjs +264 -264
  239. package/scripts/github-release.sh +4 -4
  240. package/scripts/install-claude-code.sh +85 -0
  241. package/scripts/install-cursor.sh +56 -0
  242. package/scripts/install-hooks.sh +73 -0
  243. package/scripts/install-interactive.mjs +357 -677
  244. package/scripts/install-opencode.sh +75 -0
  245. package/scripts/install-windsurf.sh +67 -0
  246. package/skills/squish-memory/SKILL.md +104 -114
  247. package/skills/squish-memory/{install.mjs → scripts/install.mjs} +2 -2
  248. package/skills/squish-memory/{install.sh → scripts/install.sh} +2 -2
  249. package/skills/squish-memory/write_skill.js +2 -0
  250. package/.claude-plugin/marketplace.json +0 -20
  251. package/.claude-plugin/plugin.json +0 -32
  252. package/.env.mcp.example +0 -60
  253. package/QUICK-START.md +0 -71
  254. package/bin/squish-add.mjs +0 -32
  255. package/bin/squish-rm.mjs +0 -21
  256. package/commands/observe.md +0 -5
  257. package/dist/api/web/index.d.ts +0 -3
  258. package/dist/api/web/index.js +0 -4
  259. package/dist/api/web/web-server.d.ts +0 -3
  260. package/dist/api/web/web-server.js +0 -6
  261. package/dist/api/web/web.d.ts +0 -4
  262. package/dist/commands/mcp-server.js +0 -393
  263. package/dist/core/context.js +0 -24
  264. package/dist/core/governance.js +0 -64
  265. package/dist/core/observations.d.ts +0 -26
  266. package/dist/core/observations.js +0 -110
  267. package/dist/core/requirements.d.ts +0 -20
  268. package/dist/core/requirements.js +0 -35
  269. package/hooks/hooks.json +0 -52
  270. package/hooks/post-tool-use.js +0 -26
  271. package/hooks/session-end.js +0 -28
  272. package/hooks/session-start.js +0 -33
  273. package/hooks/user-prompt-submit.js +0 -26
  274. package/hooks/utils.js +0 -153
  275. package/npx-installer.js +0 -208
  276. package/packages/plugin-claude-code/README.md +0 -73
  277. package/packages/plugin-claude-code/dist/plugin-wrapper.d.ts +0 -35
  278. package/packages/plugin-claude-code/dist/plugin-wrapper.js +0 -191
  279. package/packages/plugin-claude-code/package.json +0 -31
  280. package/packages/plugin-openclaw/README.md +0 -70
  281. package/packages/plugin-openclaw/dist/index.d.ts +0 -49
  282. package/packages/plugin-openclaw/dist/index.js +0 -262
  283. package/packages/plugin-openclaw/openclaw.plugin.json +0 -94
  284. package/packages/plugin-openclaw/package.json +0 -31
  285. package/packages/plugin-opencode/install.mjs +0 -217
  286. package/packages/plugin-opencode/package.json +0 -21
  287. package/scripts/db/check-db.mjs +0 -88
  288. package/scripts/db/fix-all-columns.mjs +0 -52
  289. package/scripts/db/fix-schema-all.mjs +0 -55
  290. package/scripts/db/fix-schema-full.mjs +0 -46
  291. package/scripts/db/fix-schema.mjs +0 -38
  292. package/scripts/db/init-db.mjs +0 -13
  293. package/scripts/db/recreate-db.mjs +0 -14
  294. package/scripts/install-mcp.mjs +0 -116
  295. package/scripts/install-web.sh +0 -120
  296. package/scripts/install.mjs +0 -340
  297. package/scripts/openclaw-bootstrap.mjs +0 -127
  298. package/scripts/package-release.sh +0 -71
  299. package/scripts/test/test-all-systems.mjs +0 -139
  300. package/scripts/test/test-memory-system.mjs +0 -139
  301. package/scripts/test/test-v0.5.0.mjs +0 -210
  302. package/skills/memory-guide/SKILL.md +0 -332
  303. package/skills/squish-cli/SKILL.md +0 -240
  304. package/skills/squish-mcp/SKILL.md +0 -355
  305. package/skills/squish-memory/claude-desktop.json +0 -12
  306. package/skills/squish-memory/openclaw.json +0 -13
  307. package/skills/squish-memory/opencode.json +0 -14
  308. package/skills/squish-memory/skill.json +0 -32
  309. /package/{commands → core/commands}/context-paging.md +0 -0
  310. /package/{commands → core/commands}/context-status.md +0 -0
  311. /package/{commands → core/commands}/context.md +0 -0
  312. /package/{commands → core/commands}/core-memory.md +0 -0
  313. /package/{commands → core/commands}/health.md +0 -0
  314. /package/{commands → core/commands}/merge.md +0 -0
  315. /package/{commands → core/commands}/recall.md +0 -0
  316. /package/{commands → core/commands}/remember.md +0 -0
  317. /package/{commands → core/commands}/search.md +0 -0
  318. /package/dist/{algorithms → core/algorithms}/detection/hash-filters.d.ts +0 -0
  319. /package/dist/{algorithms → core/algorithms}/detection/hash-filters.js +0 -0
  320. /package/dist/{algorithms → core/algorithms}/handlers/approve-merge.d.ts +0 -0
  321. /package/dist/{algorithms → core/algorithms}/handlers/detect-duplicates.d.ts +0 -0
  322. /package/dist/{algorithms → core/algorithms}/handlers/get-stats.d.ts +0 -0
  323. /package/dist/{algorithms → core/algorithms}/handlers/list-proposals.d.ts +0 -0
  324. /package/dist/{algorithms → core/algorithms}/handlers/preview-merge.d.ts +0 -0
  325. /package/dist/{algorithms → core/algorithms}/handlers/reject-merge.d.ts +0 -0
  326. /package/dist/{algorithms → core/algorithms}/handlers/reverse-merge.d.ts +0 -0
  327. /package/dist/{algorithms → core/algorithms}/safety/safety-checks.js +0 -0
  328. /package/dist/{algorithms → core/algorithms}/utils/response-builder.d.ts +0 -0
  329. /package/dist/{algorithms → core/algorithms}/utils/response-builder.js +0 -0
  330. /package/dist/{commands → core/commands}/managed-sync.d.ts +0 -0
  331. /package/dist/{commands → core/commands}/mcp-server.d.ts +0 -0
  332. /package/dist/core/{context.d.ts → context/context.d.ts} +0 -0
  333. /package/dist/core/{agent-memory.d.ts → ingestion/agent-memory.d.ts} +0 -0
  334. /package/dist/core/{core-memory.d.ts → ingestion/core-memory.d.ts} +0 -0
  335. /package/dist/core/{privacy.d.ts → security/privacy.d.ts} +0 -0
  336. /package/dist/core/{privacy.js → security/privacy.js} +0 -0
  337. /package/dist/core/{secret-detector.d.ts → security/secret-detector.d.ts} +0 -0
  338. /package/dist/core/{secret-detector.js → security/secret-detector.js} +0 -0
  339. /package/dist/core/{cache.d.ts → storage/cache.d.ts} +0 -0
  340. /package/dist/core/{database.d.ts → storage/database.d.ts} +0 -0
  341. /package/dist/core/{database.js → storage/database.js} +0 -0
@@ -6,572 +6,791 @@ import { getDataDir } from '../config.js';
6
6
  * SQLite uses INTEGER 0/1 for boolean values (no native boolean type)
7
7
  * PostgreSQL uses native BOOLEAN type
8
8
  */
9
- const sqliteSchemaSql = `
10
- PRAGMA foreign_keys = ON;
11
-
12
- CREATE TABLE IF NOT EXISTS users (
13
- id TEXT PRIMARY KEY,
14
- external_id TEXT UNIQUE,
15
- name TEXT,
16
- email TEXT,
17
- preferences TEXT,
18
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
19
- updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
20
- );
21
-
22
- CREATE TABLE IF NOT EXISTS projects (
23
- id TEXT PRIMARY KEY,
24
- name TEXT NOT NULL,
25
- path TEXT NOT NULL,
26
- description TEXT,
27
- metadata TEXT,
28
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
29
- updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
30
- );
31
-
32
- CREATE INDEX IF NOT EXISTS projects_path_idx ON projects(path);
33
-
34
- CREATE TABLE IF NOT EXISTS memories (
35
- id TEXT PRIMARY KEY,
36
- project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
37
- user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
38
- type TEXT NOT NULL,
39
- content TEXT NOT NULL,
40
- summary TEXT,
41
- embedding_json TEXT,
42
- embedding BLOB,
43
- source TEXT,
44
- confidence INTEGER DEFAULT 100,
45
- tags TEXT,
46
- metadata TEXT,
47
- is_private INTEGER DEFAULT 0,
48
- has_secrets INTEGER DEFAULT 0,
49
- relevance_score INTEGER DEFAULT 50,
50
- is_active INTEGER DEFAULT 1,
51
- expires_at INTEGER,
52
- access_count INTEGER DEFAULT 0,
53
- last_accessed_at INTEGER,
54
- is_merged INTEGER DEFAULT 0,
55
- merged_into_id TEXT,
56
- merged_at INTEGER,
57
- is_canonical INTEGER DEFAULT 0,
58
- merge_source_ids TEXT,
59
- is_mergeable INTEGER DEFAULT 1,
60
- merge_version INTEGER DEFAULT 1,
61
- importance_score INTEGER DEFAULT 50,
62
- importance_decay_rate INTEGER DEFAULT 30,
63
- last_importance_recalc INTEGER,
64
- consolidated_into TEXT,
65
- consolidated_at INTEGER,
66
- is_consolidated INTEGER DEFAULT 0,
67
- sector TEXT DEFAULT 'episodic',
68
- tier TEXT DEFAULT 'hot',
69
- context_status TEXT DEFAULT 'out-of-context',
70
- decay_rate INTEGER DEFAULT 30,
71
- coactivation_score INTEGER DEFAULT 0,
72
- last_decay_at INTEGER DEFAULT (strftime('%s','now')),
73
- agent_id TEXT,
74
- agent_role TEXT,
75
- visibility_scope TEXT DEFAULT 'private',
76
- is_protected INTEGER DEFAULT 0,
77
- is_pinned INTEGER DEFAULT 0,
78
- is_immutable INTEGER DEFAULT 0,
79
- write_scope TEXT,
80
- read_scope TEXT,
81
- triggered_by TEXT,
82
- capture_reason TEXT,
83
- last_used_at INTEGER,
84
- usage_count INTEGER DEFAULT 0,
85
- valid_from INTEGER,
86
- valid_to INTEGER,
87
- superseded_by TEXT,
88
- version INTEGER DEFAULT 1,
89
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
90
- updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
91
- );
92
-
93
- CREATE INDEX IF NOT EXISTS memories_project_idx ON memories(project_id);
94
- CREATE INDEX IF NOT EXISTS memories_type_idx ON memories(type);
95
- CREATE INDEX IF NOT EXISTS memories_created_idx ON memories(created_at);
96
- CREATE INDEX IF NOT EXISTS memories_tags_idx ON memories(tags);
97
-
98
- CREATE TABLE IF NOT EXISTS memory_associations (
99
- id TEXT PRIMARY KEY,
100
- from_memory_id TEXT NOT NULL,
101
- to_memory_id TEXT NOT NULL,
102
- association_type TEXT NOT NULL,
103
- weight REAL DEFAULT 1,
104
- coactivation_count INTEGER DEFAULT 1,
105
- metadata TEXT,
106
- last_coactivated_at INTEGER,
107
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
108
- UNIQUE(from_memory_id, to_memory_id)
109
- );
110
-
111
- CREATE TABLE IF NOT EXISTS conversations (
112
- id TEXT PRIMARY KEY,
113
- project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
114
- user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
115
- session_id TEXT NOT NULL,
116
- title TEXT,
117
- summary TEXT,
118
- message_count INTEGER DEFAULT 0,
119
- token_count INTEGER DEFAULT 0,
120
- started_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
121
- ended_at INTEGER,
122
- metadata TEXT,
123
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
124
- updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
125
- );
126
-
127
- CREATE INDEX IF NOT EXISTS conversations_project_idx ON conversations(project_id);
128
- CREATE INDEX IF NOT EXISTS conversations_session_idx ON conversations(session_id);
129
- CREATE INDEX IF NOT EXISTS conversations_started_idx ON conversations(started_at);
130
-
131
- CREATE TABLE IF NOT EXISTS messages (
132
- id TEXT PRIMARY KEY,
133
- conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
134
- role TEXT NOT NULL,
135
- content TEXT NOT NULL,
136
- embedding_json TEXT,
137
- token_count INTEGER,
138
- tool_calls TEXT,
139
- metadata TEXT,
140
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
141
- );
142
-
143
- CREATE INDEX IF NOT EXISTS messages_conversation_idx ON messages(conversation_id);
144
- CREATE INDEX IF NOT EXISTS messages_role_idx ON messages(role);
145
- CREATE INDEX IF NOT EXISTS messages_created_idx ON messages(created_at);
146
-
147
- CREATE TABLE IF NOT EXISTS observations (
148
- id TEXT PRIMARY KEY,
149
- project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
150
- conversation_id TEXT REFERENCES conversations(id) ON DELETE SET NULL,
151
- type TEXT NOT NULL,
152
- action TEXT NOT NULL,
153
- target TEXT,
154
- summary TEXT NOT NULL,
155
- details TEXT,
156
- embedding_json TEXT,
157
- category TEXT,
158
- importance INTEGER DEFAULT 50,
159
- metadata TEXT,
160
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
161
- );
162
-
163
- CREATE INDEX IF NOT EXISTS observations_project_idx ON observations(project_id);
164
- CREATE INDEX IF NOT EXISTS observations_type_idx ON observations(type);
165
- CREATE INDEX IF NOT EXISTS observations_action_idx ON observations(action);
166
- CREATE INDEX IF NOT EXISTS observations_created_idx ON observations(created_at);
167
-
168
- CREATE TABLE IF NOT EXISTS entities (
169
- id TEXT PRIMARY KEY,
170
- project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
171
- name TEXT NOT NULL,
172
- type TEXT NOT NULL,
173
- description TEXT,
174
- embedding_json TEXT,
175
- properties TEXT,
176
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
177
- updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
178
- );
179
-
180
- CREATE INDEX IF NOT EXISTS entities_project_idx ON entities(project_id);
181
- CREATE INDEX IF NOT EXISTS entities_type_idx ON entities(type);
182
- CREATE INDEX IF NOT EXISTS entities_name_idx ON entities(name);
183
-
184
- CREATE TABLE IF NOT EXISTS entity_relations (
185
- id TEXT PRIMARY KEY,
186
- from_entity_id TEXT NOT NULL REFERENCES entities(id) ON DELETE CASCADE,
187
- to_entity_id TEXT NOT NULL REFERENCES entities(id) ON DELETE CASCADE,
188
- type TEXT NOT NULL,
189
- weight INTEGER DEFAULT 1,
190
- properties TEXT,
191
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
192
- );
193
-
194
- CREATE INDEX IF NOT EXISTS relations_from_idx ON entity_relations(from_entity_id);
195
- CREATE INDEX IF NOT EXISTS relations_to_idx ON entity_relations(to_entity_id);
196
- CREATE INDEX IF NOT EXISTS relations_type_idx ON entity_relations(type);
197
-
198
- CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
199
- content,
200
- tags,
201
- content='memories',
202
- content_rowid='rowid'
203
- );
204
-
205
- CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
206
- INSERT INTO memories_fts(rowid, content, tags)
207
- VALUES (new.rowid, new.content, COALESCE(new.tags, ''));
208
- END;
209
-
210
- CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
211
- INSERT INTO memories_fts(memories_fts, rowid, content, tags)
212
- VALUES ('delete', old.rowid, old.content, COALESCE(old.tags, ''));
213
- END;
214
-
215
- CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
216
- INSERT INTO memories_fts(memories_fts, rowid, content, tags)
217
- VALUES ('delete', old.rowid, old.content, COALESCE(old.tags, ''));
218
- INSERT INTO memories_fts(rowid, content, tags)
219
- VALUES (new.rowid, new.content, COALESCE(new.tags, ''));
220
- END;
221
-
222
- CREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(
223
- content,
224
- content='messages',
225
- content_rowid='rowid'
226
- );
227
-
228
- CREATE TRIGGER IF NOT EXISTS messages_ai AFTER INSERT ON messages BEGIN
229
- INSERT INTO messages_fts(rowid, content)
230
- VALUES (new.rowid, new.content);
231
- END;
232
-
233
- CREATE TRIGGER IF NOT EXISTS messages_ad AFTER DELETE ON messages BEGIN
234
- INSERT INTO messages_fts(messages_fts, rowid, content)
235
- VALUES ('delete', old.rowid, old.content);
236
- END;
237
-
238
- CREATE TRIGGER IF NOT EXISTS messages_au AFTER UPDATE ON messages BEGIN
239
- INSERT INTO messages_fts(messages_fts, rowid, content)
240
- VALUES ('delete', old.rowid, old.content);
241
- INSERT INTO messages_fts(rowid, content)
242
- VALUES (new.rowid, new.content);
243
- END;
244
-
245
- CREATE TABLE IF NOT EXISTS core_memory (
246
- id TEXT PRIMARY KEY,
247
- project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
248
- user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
249
- section TEXT NOT NULL,
250
- content TEXT NOT NULL DEFAULT '',
251
- size_bytes INTEGER DEFAULT 0 NOT NULL,
252
- tokens_estimate INTEGER DEFAULT 0 NOT NULL,
253
- version INTEGER DEFAULT 1 NOT NULL,
254
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
255
- updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
256
- );
257
-
258
- CREATE INDEX IF NOT EXISTS core_memory_project_idx ON core_memory(project_id);
259
- CREATE INDEX IF NOT EXISTS core_memory_user_idx ON core_memory(user_id);
260
- CREATE INDEX IF NOT EXISTS core_memory_section_idx ON core_memory(section);
261
-
262
- CREATE TABLE IF NOT EXISTS context_sessions (
263
- id TEXT PRIMARY KEY,
264
- session_id TEXT NOT NULL UNIQUE,
265
- project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
266
- user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
267
- loaded_memory_ids TEXT,
268
- token_budget INTEGER DEFAULT 8000 NOT NULL,
269
- tokens_used INTEGER DEFAULT 0 NOT NULL,
270
- core_memory_tokens INTEGER DEFAULT 0 NOT NULL,
271
- loaded_memories_tokens INTEGER DEFAULT 0 NOT NULL,
272
- metadata TEXT,
273
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
274
- updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
275
- );
276
-
277
- CREATE INDEX IF NOT EXISTS context_sessions_session_idx ON context_sessions(session_id);
278
- CREATE INDEX IF NOT EXISTS context_sessions_project_idx ON context_sessions(project_id);
279
- CREATE INDEX IF NOT EXISTS context_sessions_created_idx ON context_sessions(created_at);
280
-
281
- -- v0.8.0: Memory Merge Tables
282
- CREATE TABLE IF NOT EXISTS memory_merge_proposals (
283
- id TEXT PRIMARY KEY,
284
- project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
285
- user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
286
- source_memory_ids TEXT NOT NULL,
287
- proposed_content TEXT NOT NULL,
288
- proposed_summary TEXT,
289
- proposed_tags TEXT,
290
- proposed_metadata TEXT,
291
- detection_method TEXT NOT NULL,
292
- similarity_score TEXT NOT NULL,
293
- confidence_level TEXT NOT NULL,
294
- merge_reason TEXT NOT NULL,
295
- conflict_warnings TEXT,
296
- status TEXT DEFAULT 'pending' NOT NULL,
297
- reviewed_at INTEGER,
298
- review_notes TEXT,
299
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
300
- expires_at INTEGER
301
- );
302
-
303
- CREATE INDEX IF NOT EXISTS memory_merge_proposals_project_status_idx ON memory_merge_proposals(project_id, status);
304
- CREATE INDEX IF NOT EXISTS memory_merge_proposals_created_at_idx ON memory_merge_proposals(created_at);
305
-
306
- CREATE TABLE IF NOT EXISTS memory_merge_history (
307
- id TEXT PRIMARY KEY,
308
- project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
309
- user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
310
- proposal_id TEXT REFERENCES memory_merge_proposals(id) ON DELETE SET NULL,
311
- source_memory_ids TEXT NOT NULL,
312
- canonical_memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
313
- source_memories_snapshot TEXT NOT NULL,
314
- merge_strategy TEXT NOT NULL,
315
- tokens_saved INTEGER,
316
- is_reversed INTEGER DEFAULT 0,
317
- reversed_at INTEGER,
318
- reversed_by TEXT,
319
- merged_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
320
- );
321
-
322
- CREATE TABLE IF NOT EXISTS memory_hash_cache (
323
- memory_id TEXT PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
324
- project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
325
- simhash TEXT,
326
- minhash TEXT,
327
- content_hash TEXT NOT NULL,
328
- last_updated INTEGER DEFAULT (strftime('%s','now')) NOT NULL
329
- );
330
-
331
- CREATE INDEX IF NOT EXISTS memory_hash_cache_project_id_idx ON memory_hash_cache(project_id);
332
- CREATE INDEX IF NOT EXISTS memory_hash_cache_simhash_idx ON memory_hash_cache(simhash);
333
-
334
- -- Namespaces table (v1.0.x) - Hierarchical organization
335
- CREATE TABLE IF NOT EXISTS namespaces (
336
- id TEXT PRIMARY KEY,
337
- project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
338
- name TEXT NOT NULL,
339
- path TEXT,
340
- description TEXT,
341
- parent_id TEXT REFERENCES namespaces(id) ON DELETE SET NULL,
342
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
343
- updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
344
- );
345
- CREATE INDEX IF NOT EXISTS namespaces_project_idx ON namespaces(project_id);
346
- CREATE INDEX IF NOT EXISTS namespaces_parent_idx ON namespaces(parent_id);
347
-
348
- -- Maintenance jobs table (v1.0.x) - Cron scheduler
349
- CREATE TABLE IF NOT EXISTS maintenance_jobs (
350
- id TEXT PRIMARY KEY,
351
- job_name TEXT NOT NULL UNIQUE,
352
- job_type TEXT NOT NULL,
353
- cron_expression TEXT,
354
- enabled INTEGER DEFAULT 1 NOT NULL,
355
- last_run_at INTEGER,
356
- last_run_duration INTEGER,
357
- last_run_status TEXT,
358
- last_run_error TEXT,
359
- total_runs INTEGER DEFAULT 0,
360
- success_count INTEGER DEFAULT 0,
361
- failure_count INTEGER DEFAULT 0,
362
- job_config TEXT,
363
- next_run_at INTEGER,
364
- created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
365
- updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
366
- );
367
- CREATE INDEX IF NOT EXISTS maintenance_jobs_name_idx ON maintenance_jobs(job_name);
368
- CREATE INDEX IF NOT EXISTS maintenance_jobs_next_run_idx ON maintenance_jobs(next_run_at);
369
- CREATE INDEX IF NOT EXISTS maintenance_jobs_type_idx ON maintenance_jobs(job_type);
370
- CREATE INDEX IF NOT EXISTS maintenance_jobs_enabled_idx ON maintenance_jobs(enabled);
9
+ const sqliteSchemaSql = `
10
+ PRAGMA foreign_keys = ON;
11
+
12
+ CREATE TABLE IF NOT EXISTS users (
13
+ id TEXT PRIMARY KEY,
14
+ external_id TEXT UNIQUE,
15
+ name TEXT,
16
+ email TEXT,
17
+ preferences TEXT,
18
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
19
+ updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
20
+ );
21
+
22
+ CREATE TABLE IF NOT EXISTS projects (
23
+ id TEXT PRIMARY KEY,
24
+ name TEXT NOT NULL,
25
+ path TEXT NOT NULL,
26
+ description TEXT,
27
+ metadata TEXT,
28
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
29
+ updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
30
+ );
31
+
32
+ CREATE INDEX IF NOT EXISTS projects_path_idx ON projects(path);
33
+
34
+ CREATE TABLE IF NOT EXISTS memories (
35
+ id TEXT PRIMARY KEY,
36
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
37
+ user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
38
+ type TEXT NOT NULL,
39
+ content TEXT NOT NULL,
40
+ summary TEXT,
41
+ embedding_json TEXT,
42
+ embedding BLOB,
43
+ source TEXT,
44
+ confidence INTEGER DEFAULT 50,
45
+ confidence_level TEXT DEFAULT 'speculative',
46
+ tags TEXT,
47
+ metadata TEXT,
48
+ is_private INTEGER DEFAULT 0,
49
+ has_secrets INTEGER DEFAULT 0,
50
+ relevance_score INTEGER DEFAULT 50,
51
+ is_active INTEGER DEFAULT 1,
52
+ expires_at INTEGER,
53
+ access_count INTEGER DEFAULT 0,
54
+ last_accessed_at INTEGER,
55
+ is_merged INTEGER DEFAULT 0,
56
+ merged_into_id TEXT,
57
+ 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')),
74
+ agent_id TEXT,
75
+ agent_role TEXT,
76
+ visibility_scope TEXT DEFAULT 'private',
77
+ is_protected INTEGER DEFAULT 0,
78
+ is_pinned INTEGER DEFAULT 0,
79
+ is_immutable INTEGER DEFAULT 0,
80
+ write_scope TEXT,
81
+ read_scope TEXT,
82
+ triggered_by TEXT,
83
+ capture_reason TEXT,
84
+ 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,
90
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
91
+ updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
92
+ );
93
+
94
+ CREATE INDEX IF NOT EXISTS memories_project_idx ON memories(project_id);
95
+ CREATE INDEX IF NOT EXISTS memories_type_idx ON memories(type);
96
+ CREATE INDEX IF NOT EXISTS memories_created_idx ON memories(created_at);
97
+ CREATE INDEX IF NOT EXISTS memories_tags_idx ON memories(tags);
98
+
99
+ CREATE TABLE IF NOT EXISTS memory_associations (
100
+ id TEXT PRIMARY KEY,
101
+ from_memory_id TEXT NOT NULL,
102
+ to_memory_id TEXT NOT NULL,
103
+ association_type TEXT NOT NULL,
104
+ weight REAL DEFAULT 1,
105
+ coactivation_count INTEGER DEFAULT 1,
106
+ metadata TEXT,
107
+ last_coactivated_at INTEGER,
108
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
109
+ UNIQUE(from_memory_id, to_memory_id)
110
+ );
111
+
112
+ -- Composite index for graph traversal (v1.1.0)
113
+ CREATE INDEX IF NOT EXISTS associations_graph_traversal_idx ON memory_associations(from_memory_id, to_memory_id, weight, association_type);
114
+
115
+ CREATE TABLE IF NOT EXISTS conversations (
116
+ id TEXT PRIMARY KEY,
117
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
118
+ user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
119
+ session_id TEXT NOT NULL,
120
+ title TEXT,
121
+ summary TEXT,
122
+ message_count INTEGER DEFAULT 0,
123
+ token_count INTEGER DEFAULT 0,
124
+ started_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
125
+ ended_at INTEGER,
126
+ metadata TEXT,
127
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
128
+ updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
129
+ );
130
+
131
+ CREATE INDEX IF NOT EXISTS conversations_project_idx ON conversations(project_id);
132
+ CREATE INDEX IF NOT EXISTS conversations_session_idx ON conversations(session_id);
133
+ CREATE INDEX IF NOT EXISTS conversations_started_idx ON conversations(started_at);
134
+
135
+ CREATE TABLE IF NOT EXISTS messages (
136
+ id TEXT PRIMARY KEY,
137
+ conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
138
+ role TEXT NOT NULL,
139
+ content TEXT NOT NULL,
140
+ embedding_json TEXT,
141
+ token_count INTEGER,
142
+ tool_calls TEXT,
143
+ metadata TEXT,
144
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
145
+ );
146
+
147
+ CREATE INDEX IF NOT EXISTS messages_conversation_idx ON messages(conversation_id);
148
+ CREATE INDEX IF NOT EXISTS messages_role_idx ON messages(role);
149
+ CREATE INDEX IF NOT EXISTS messages_created_idx ON messages(created_at);
150
+
151
+ -- Learnings table (renamed from observations)
152
+ CREATE TABLE IF NOT EXISTS learnings (
153
+ id TEXT PRIMARY KEY,
154
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
155
+ conversation_id TEXT REFERENCES conversations(id) ON DELETE SET NULL,
156
+ type TEXT NOT NULL,
157
+ action TEXT NOT NULL,
158
+ target TEXT,
159
+ summary TEXT NOT NULL,
160
+ details TEXT,
161
+ embedding_json TEXT,
162
+ embedding BLOB,
163
+ memory_id TEXT REFERENCES memories(id) ON DELETE SET NULL,
164
+ folder_path TEXT,
165
+ project_path TEXT,
166
+ is_private INTEGER DEFAULT 0,
167
+ has_secrets INTEGER DEFAULT 0,
168
+ relevance_score INTEGER DEFAULT 50,
169
+ category TEXT,
170
+ importance INTEGER DEFAULT 50,
171
+ metadata TEXT,
172
+ is_imported INTEGER DEFAULT 0,
173
+ -- UAM: Agent integration columns
174
+ agent_id TEXT,
175
+ tool_name TEXT,
176
+ session_id TEXT,
177
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
178
+ );
179
+
180
+ CREATE INDEX IF NOT EXISTS learnings_project_idx ON learnings(project_id);
181
+ CREATE INDEX IF NOT EXISTS learnings_type_idx ON learnings(type);
182
+ CREATE INDEX IF NOT EXISTS learnings_action_idx ON learnings(action);
183
+ CREATE INDEX IF NOT EXISTS observations_created_idx ON observations(created_at);
184
+
185
+ CREATE TABLE IF NOT EXISTS entities (
186
+ id TEXT PRIMARY KEY,
187
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
188
+ name TEXT NOT NULL,
189
+ type TEXT NOT NULL,
190
+ description TEXT,
191
+ embedding_json TEXT,
192
+ properties TEXT,
193
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
194
+ updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
195
+ );
196
+
197
+ CREATE INDEX IF NOT EXISTS entities_project_idx ON entities(project_id);
198
+ CREATE INDEX IF NOT EXISTS entities_type_idx ON entities(type);
199
+ CREATE INDEX IF NOT EXISTS entities_name_idx ON entities(name);
200
+
201
+ CREATE TABLE IF NOT EXISTS entity_relations (
202
+ id TEXT PRIMARY KEY,
203
+ from_entity_id TEXT NOT NULL REFERENCES entities(id) ON DELETE CASCADE,
204
+ to_entity_id TEXT NOT NULL REFERENCES entities(id) ON DELETE CASCADE,
205
+ type TEXT NOT NULL,
206
+ weight INTEGER DEFAULT 1,
207
+ properties TEXT,
208
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
209
+ );
210
+
211
+ CREATE INDEX IF NOT EXISTS relations_from_idx ON entity_relations(from_entity_id);
212
+ CREATE INDEX IF NOT EXISTS relations_to_idx ON entity_relations(to_entity_id);
213
+ CREATE INDEX IF NOT EXISTS relations_type_idx ON entity_relations(type);
214
+
215
+ CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
216
+ content,
217
+ tags,
218
+ content='memories',
219
+ content_rowid='rowid'
220
+ );
221
+
222
+ CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
223
+ INSERT INTO memories_fts(rowid, content, tags)
224
+ VALUES (new.rowid, new.content, COALESCE(new.tags, ''));
225
+ END;
226
+
227
+ CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
228
+ INSERT INTO memories_fts(memories_fts, rowid, content, tags)
229
+ VALUES ('delete', old.rowid, old.content, COALESCE(old.tags, ''));
230
+ END;
231
+
232
+ CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
233
+ INSERT INTO memories_fts(memories_fts, rowid, content, tags)
234
+ VALUES ('delete', old.rowid, old.content, COALESCE(old.tags, ''));
235
+ INSERT INTO memories_fts(rowid, content, tags)
236
+ VALUES (new.rowid, new.content, COALESCE(new.tags, ''));
237
+ END;
238
+
239
+ CREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5(
240
+ content,
241
+ content='messages',
242
+ content_rowid='rowid'
243
+ );
244
+
245
+ CREATE TRIGGER IF NOT EXISTS messages_ai AFTER INSERT ON messages BEGIN
246
+ INSERT INTO messages_fts(rowid, content)
247
+ VALUES (new.rowid, new.content);
248
+ END;
249
+
250
+ CREATE TRIGGER IF NOT EXISTS messages_ad AFTER DELETE ON messages BEGIN
251
+ INSERT INTO messages_fts(messages_fts, rowid, content)
252
+ VALUES ('delete', old.rowid, old.content);
253
+ END;
254
+
255
+ CREATE TRIGGER IF NOT EXISTS messages_au AFTER UPDATE ON messages BEGIN
256
+ INSERT INTO messages_fts(messages_fts, rowid, content)
257
+ VALUES ('delete', old.rowid, old.content);
258
+ INSERT INTO messages_fts(rowid, content)
259
+ VALUES (new.rowid, new.content);
260
+ END;
261
+
262
+ CREATE TABLE IF NOT EXISTS core_memory (
263
+ id TEXT PRIMARY KEY,
264
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
265
+ user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
266
+ section TEXT NOT NULL,
267
+ content TEXT NOT NULL DEFAULT '',
268
+ size_bytes INTEGER DEFAULT 0 NOT NULL,
269
+ tokens_estimate INTEGER DEFAULT 0 NOT NULL,
270
+ version INTEGER DEFAULT 1 NOT NULL,
271
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
272
+ updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
273
+ );
274
+
275
+ CREATE INDEX IF NOT EXISTS core_memory_project_idx ON core_memory(project_id);
276
+ CREATE INDEX IF NOT EXISTS core_memory_user_idx ON core_memory(user_id);
277
+ CREATE INDEX IF NOT EXISTS core_memory_section_idx ON core_memory(section);
278
+
279
+ CREATE TABLE IF NOT EXISTS context_sessions (
280
+ id TEXT PRIMARY KEY,
281
+ session_id TEXT NOT NULL UNIQUE,
282
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
283
+ user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
284
+ loaded_memory_ids TEXT,
285
+ token_budget INTEGER DEFAULT 8000 NOT NULL,
286
+ tokens_used INTEGER DEFAULT 0 NOT NULL,
287
+ core_memory_tokens INTEGER DEFAULT 0 NOT NULL,
288
+ loaded_memories_tokens INTEGER DEFAULT 0 NOT NULL,
289
+ metadata TEXT,
290
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
291
+ updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
292
+ );
293
+
294
+ CREATE INDEX IF NOT EXISTS context_sessions_session_idx ON context_sessions(session_id);
295
+ CREATE INDEX IF NOT EXISTS context_sessions_project_idx ON context_sessions(project_id);
296
+ CREATE INDEX IF NOT EXISTS context_sessions_created_idx ON context_sessions(created_at);
297
+
298
+ -- v0.8.0: Memory Merge Tables
299
+ CREATE TABLE IF NOT EXISTS memory_merge_proposals (
300
+ id TEXT PRIMARY KEY,
301
+ project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
302
+ user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
303
+ source_memory_ids TEXT NOT NULL,
304
+ proposed_content TEXT NOT NULL,
305
+ proposed_summary TEXT,
306
+ proposed_tags TEXT,
307
+ proposed_metadata TEXT,
308
+ detection_method TEXT NOT NULL,
309
+ similarity_score TEXT NOT NULL,
310
+ confidence_level TEXT NOT NULL,
311
+ merge_reason TEXT NOT NULL,
312
+ conflict_warnings TEXT,
313
+ status TEXT DEFAULT 'pending' NOT NULL,
314
+ reviewed_at INTEGER,
315
+ review_notes TEXT,
316
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
317
+ expires_at INTEGER
318
+ );
319
+
320
+ CREATE INDEX IF NOT EXISTS memory_merge_proposals_project_status_idx ON memory_merge_proposals(project_id, status);
321
+ CREATE INDEX IF NOT EXISTS memory_merge_proposals_created_at_idx ON memory_merge_proposals(created_at);
322
+
323
+ CREATE TABLE IF NOT EXISTS memory_merge_history (
324
+ id TEXT PRIMARY KEY,
325
+ project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
326
+ user_id TEXT REFERENCES users(id) ON DELETE SET NULL,
327
+ proposal_id TEXT REFERENCES memory_merge_proposals(id) ON DELETE SET NULL,
328
+ source_memory_ids TEXT NOT NULL,
329
+ canonical_memory_id TEXT NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
330
+ source_memories_snapshot TEXT NOT NULL,
331
+ merge_strategy TEXT NOT NULL,
332
+ tokens_saved INTEGER,
333
+ is_reversed INTEGER DEFAULT 0,
334
+ reversed_at INTEGER,
335
+ reversed_by TEXT,
336
+ merged_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
337
+ );
338
+
339
+ CREATE TABLE IF NOT EXISTS memory_hash_cache (
340
+ memory_id TEXT PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
341
+ project_id TEXT NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
342
+ simhash TEXT,
343
+ minhash TEXT,
344
+ content_hash TEXT NOT NULL,
345
+ last_updated INTEGER DEFAULT (strftime('%s','now')) NOT NULL
346
+ );
347
+
348
+ CREATE INDEX IF NOT EXISTS memory_hash_cache_project_id_idx ON memory_hash_cache(project_id);
349
+ CREATE INDEX IF NOT EXISTS memory_hash_cache_simhash_idx ON memory_hash_cache(simhash);
350
+
351
+ -- Namespaces table (v1.0.x) - Hierarchical organization
352
+ CREATE TABLE IF NOT EXISTS namespaces (
353
+ id TEXT PRIMARY KEY,
354
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
355
+ name TEXT NOT NULL,
356
+ path TEXT,
357
+ description TEXT,
358
+ parent_id TEXT REFERENCES namespaces(id) ON DELETE SET NULL,
359
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
360
+ updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
361
+ );
362
+ CREATE INDEX IF NOT EXISTS namespaces_project_idx ON namespaces(project_id);
363
+ CREATE INDEX IF NOT EXISTS namespaces_parent_idx ON namespaces(parent_id);
364
+
365
+ -- Maintenance jobs table (v1.0.x) - Cron scheduler
366
+ CREATE TABLE IF NOT EXISTS maintenance_jobs (
367
+ id TEXT PRIMARY KEY,
368
+ job_name TEXT NOT NULL UNIQUE,
369
+ job_type TEXT NOT NULL,
370
+ cron_expression TEXT,
371
+ enabled INTEGER DEFAULT 1 NOT NULL,
372
+ last_run_at INTEGER,
373
+ last_run_duration INTEGER,
374
+ last_run_status TEXT,
375
+ last_run_error TEXT,
376
+ total_runs INTEGER DEFAULT 0,
377
+ success_count INTEGER DEFAULT 0,
378
+ failure_count INTEGER DEFAULT 0,
379
+ job_config TEXT,
380
+ next_run_at INTEGER,
381
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
382
+ updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
383
+ );
384
+ CREATE INDEX IF NOT EXISTS maintenance_jobs_name_idx ON maintenance_jobs(job_name);
385
+ CREATE INDEX IF NOT EXISTS maintenance_jobs_next_run_idx ON maintenance_jobs(next_run_at);
386
+ CREATE INDEX IF NOT EXISTS maintenance_jobs_type_idx ON maintenance_jobs(job_type);
387
+ CREATE INDEX IF NOT EXISTS maintenance_jobs_enabled_idx ON maintenance_jobs(enabled);
388
+
389
+ -- Places table (v1.1.5) - Spatial memory organization
390
+ CREATE TABLE IF NOT EXISTS places (
391
+ id TEXT PRIMARY KEY,
392
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE NOT NULL,
393
+ name TEXT NOT NULL,
394
+ place_type TEXT NOT NULL,
395
+ parent_id TEXT REFERENCES places(id) ON DELETE SET NULL,
396
+ loci_index INTEGER DEFAULT 0,
397
+ position_x INTEGER DEFAULT 0,
398
+ position_y INTEGER DEFAULT 0,
399
+ description TEXT,
400
+ purpose TEXT,
401
+ memory_count INTEGER DEFAULT 0,
402
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
403
+ updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
404
+ );
405
+ CREATE INDEX IF NOT EXISTS places_project_idx ON places(project_id);
406
+ CREATE INDEX IF NOT EXISTS places_type_idx ON places(place_type);
407
+ 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);
409
+
410
+ -- Memory-Place assignments
411
+ CREATE TABLE IF NOT EXISTS memory_places (
412
+ id TEXT PRIMARY KEY,
413
+ memory_id TEXT REFERENCES memories(id) ON DELETE CASCADE NOT NULL,
414
+ place_id TEXT REFERENCES places(id) ON DELETE CASCADE NOT NULL,
415
+ is_manual INTEGER DEFAULT 0,
416
+ rule_id TEXT,
417
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
418
+ );
419
+ CREATE INDEX IF NOT EXISTS memory_places_memory_idx ON memory_places(memory_id);
420
+ CREATE INDEX IF NOT EXISTS memory_places_place_idx ON memory_places(place_id);
421
+
422
+ -- Place auto-assignment rules
423
+ CREATE TABLE IF NOT EXISTS place_rules (
424
+ id TEXT PRIMARY KEY,
425
+ project_id TEXT REFERENCES projects(id) ON DELETE CASCADE NOT NULL,
426
+ name TEXT NOT NULL,
427
+ place_type TEXT NOT NULL,
428
+ match_tool TEXT,
429
+ match_keyword TEXT,
430
+ match_tag TEXT,
431
+ match_memory_type TEXT,
432
+ priority INTEGER DEFAULT 0,
433
+ enabled INTEGER DEFAULT 1,
434
+ created_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL,
435
+ updated_at INTEGER DEFAULT (strftime('%s','now')) NOT NULL
436
+ );
437
+ CREATE INDEX IF NOT EXISTS place_rules_project_idx ON place_rules(project_id);
438
+ CREATE INDEX IF NOT EXISTS place_rules_type_idx ON place_rules(place_type);
371
439
  `;
372
440
  const postgresStatements = [
373
441
  `CREATE EXTENSION IF NOT EXISTS pgcrypto;`,
374
442
  `CREATE EXTENSION IF NOT EXISTS vector;`,
375
443
  `CREATE EXTENSION IF NOT EXISTS pg_trgm;`,
376
- `CREATE TABLE IF NOT EXISTS users (
377
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
378
- external_id TEXT UNIQUE,
379
- name TEXT,
380
- email TEXT,
381
- preferences JSONB,
382
- created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
383
- updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
444
+ `CREATE TABLE IF NOT EXISTS users (
445
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
446
+ external_id TEXT UNIQUE,
447
+ name TEXT,
448
+ email TEXT,
449
+ preferences JSONB,
450
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
451
+ updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
384
452
  );`,
385
- `CREATE TABLE IF NOT EXISTS projects (
386
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
387
- name TEXT NOT NULL,
388
- path TEXT NOT NULL,
389
- description TEXT,
390
- metadata JSONB,
391
- created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
392
- updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
453
+ `CREATE TABLE IF NOT EXISTS projects (
454
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
455
+ name TEXT NOT NULL,
456
+ path TEXT NOT NULL,
457
+ description TEXT,
458
+ metadata JSONB,
459
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
460
+ updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
393
461
  );`,
394
462
  `CREATE INDEX IF NOT EXISTS projects_path_idx ON projects(path);`,
395
- `CREATE TABLE IF NOT EXISTS memories (
396
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
397
- project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
398
- user_id UUID REFERENCES users(id) ON DELETE SET NULL,
399
- type TEXT NOT NULL,
400
- content TEXT NOT NULL,
401
- summary TEXT,
402
- embedding vector(1536),
403
- source TEXT,
404
- confidence INTEGER DEFAULT 100,
405
- tags TEXT[],
406
- metadata JSONB,
407
- is_active BOOLEAN DEFAULT TRUE,
408
- expires_at TIMESTAMPTZ,
409
- access_count INTEGER DEFAULT 0,
410
- last_accessed_at TIMESTAMPTZ,
411
- created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
412
- updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
413
- );`,
463
+ `CREATE TABLE IF NOT EXISTS memories (
464
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
465
+ project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
466
+ user_id UUID REFERENCES users(id) ON DELETE SET NULL,
467
+ type TEXT NOT NULL,
468
+ content TEXT NOT NULL,
469
+ summary TEXT,
470
+ embedding_json TEXT,
471
+ embedding vector(1536),
472
+ source TEXT,
473
+ confidence INTEGER DEFAULT 50,
474
+ confidence_level TEXT DEFAULT 'speculative',
475
+ tags TEXT[],
476
+ metadata JSONB,
477
+ is_private BOOLEAN DEFAULT FALSE,
478
+ has_secrets BOOLEAN DEFAULT FALSE,
479
+ relevance_score INTEGER DEFAULT 50,
480
+ is_active BOOLEAN DEFAULT TRUE,
481
+ is_merged BOOLEAN DEFAULT FALSE,
482
+ merged_into_id UUID,
483
+ merged_at TIMESTAMPTZ,
484
+ is_canonical BOOLEAN DEFAULT TRUE,
485
+ merge_source_ids TEXT[],
486
+ is_mergeable BOOLEAN DEFAULT TRUE,
487
+ merge_version INTEGER DEFAULT 1,
488
+ importance_score INTEGER DEFAULT 50,
489
+ importance_decay_rate INTEGER DEFAULT 30,
490
+ last_importance_recalc TIMESTAMPTZ,
491
+ consolidated_into UUID,
492
+ consolidated_at TIMESTAMPTZ,
493
+ is_consolidated BOOLEAN DEFAULT FALSE,
494
+ sector TEXT DEFAULT 'episodic',
495
+ tier TEXT DEFAULT 'hot',
496
+ status TEXT DEFAULT 'active',
497
+ context_status TEXT DEFAULT 'out-of-context',
498
+ decay_rate INTEGER DEFAULT 30,
499
+ coactivation_score INTEGER DEFAULT 0,
500
+ last_decay_at TIMESTAMPTZ,
501
+ agent_id TEXT,
502
+ agent_role TEXT,
503
+ visibility_scope TEXT DEFAULT 'private',
504
+ is_protected BOOLEAN DEFAULT FALSE,
505
+ is_pinned BOOLEAN DEFAULT FALSE,
506
+ is_immutable BOOLEAN DEFAULT FALSE,
507
+ write_scope TEXT[],
508
+ read_scope TEXT[],
509
+ triggered_by TEXT,
510
+ capture_reason TEXT,
511
+ last_used_at TIMESTAMPTZ,
512
+ usage_count INTEGER DEFAULT 0,
513
+ tokens_estimate INTEGER DEFAULT 0,
514
+ valid_from TIMESTAMPTZ,
515
+ valid_to TIMESTAMPTZ,
516
+ recorded_at TIMESTAMPTZ DEFAULT NOW(),
517
+ superseded_by UUID,
518
+ version INTEGER DEFAULT 1,
519
+ expires_at TIMESTAMPTZ,
520
+ access_count INTEGER DEFAULT 0,
521
+ last_accessed_at TIMESTAMPTZ,
522
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
523
+ updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
524
+ );`,
414
525
  `CREATE INDEX IF NOT EXISTS memories_project_idx ON memories(project_id);`,
415
526
  `CREATE INDEX IF NOT EXISTS memories_type_idx ON memories(type);`,
416
527
  `CREATE INDEX IF NOT EXISTS memories_created_idx ON memories(created_at);`,
417
528
  `CREATE INDEX IF NOT EXISTS memories_tags_idx ON memories USING GIN(tags);`,
418
529
  `CREATE INDEX IF NOT EXISTS memories_content_trgm_idx ON memories USING GIN (content gin_trgm_ops);`,
419
- `CREATE TABLE IF NOT EXISTS conversations (
420
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
421
- project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
422
- user_id UUID REFERENCES users(id) ON DELETE SET NULL,
423
- session_id TEXT NOT NULL,
424
- title TEXT,
425
- summary TEXT,
426
- message_count INTEGER DEFAULT 0,
427
- token_count INTEGER DEFAULT 0,
428
- started_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
429
- ended_at TIMESTAMPTZ,
430
- metadata JSONB,
431
- created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
432
- updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
530
+ `CREATE TABLE IF NOT EXISTS conversations (
531
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
532
+ project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
533
+ user_id UUID REFERENCES users(id) ON DELETE SET NULL,
534
+ session_id TEXT NOT NULL,
535
+ title TEXT,
536
+ summary TEXT,
537
+ message_count INTEGER DEFAULT 0,
538
+ token_count INTEGER DEFAULT 0,
539
+ started_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
540
+ ended_at TIMESTAMPTZ,
541
+ metadata JSONB,
542
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
543
+ updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
433
544
  );`,
434
545
  `CREATE INDEX IF NOT EXISTS conversations_project_idx ON conversations(project_id);`,
435
546
  `CREATE INDEX IF NOT EXISTS conversations_session_idx ON conversations(session_id);`,
436
547
  `CREATE INDEX IF NOT EXISTS conversations_started_idx ON conversations(started_at);`,
437
- `CREATE TABLE IF NOT EXISTS messages (
438
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
439
- conversation_id UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
440
- role TEXT NOT NULL,
441
- content TEXT NOT NULL,
442
- embedding vector(1536),
443
- token_count INTEGER,
444
- tool_calls JSONB,
445
- metadata JSONB,
446
- created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
548
+ `CREATE TABLE IF NOT EXISTS messages (
549
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
550
+ conversation_id UUID NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
551
+ role TEXT NOT NULL,
552
+ content TEXT NOT NULL,
553
+ embedding vector(1536),
554
+ token_count INTEGER,
555
+ tool_calls JSONB,
556
+ metadata JSONB,
557
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
447
558
  );`,
448
559
  `CREATE INDEX IF NOT EXISTS messages_conversation_idx ON messages(conversation_id);`,
449
560
  `CREATE INDEX IF NOT EXISTS messages_role_idx ON messages(role);`,
450
561
  `CREATE INDEX IF NOT EXISTS messages_created_idx ON messages(created_at);`,
451
562
  `CREATE INDEX IF NOT EXISTS messages_content_trgm_idx ON messages USING GIN (content gin_trgm_ops);`,
452
- `CREATE TABLE IF NOT EXISTS observations (
453
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
454
- project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
455
- conversation_id UUID REFERENCES conversations(id) ON DELETE SET NULL,
456
- type TEXT NOT NULL,
457
- action TEXT NOT NULL,
458
- target TEXT,
459
- summary TEXT NOT NULL,
460
- details JSONB,
461
- embedding vector(1536),
462
- category TEXT,
463
- importance INTEGER DEFAULT 50,
464
- metadata JSONB,
465
- created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
563
+ // Learnings table (renamed from observations)
564
+ `CREATE TABLE IF NOT EXISTS learnings (
565
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
566
+ project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
567
+ conversation_id UUID REFERENCES conversations(id) ON DELETE SET NULL,
568
+ type TEXT NOT NULL,
569
+ action TEXT NOT NULL,
570
+ target TEXT,
571
+ summary TEXT NOT NULL,
572
+ details JSONB,
573
+ embedding vector(1536),
574
+ memory_id UUID REFERENCES memories(id) ON DELETE SET NULL,
575
+ category TEXT,
576
+ importance INTEGER DEFAULT 50,
577
+ metadata JSONB,
578
+ is_imported BOOLEAN DEFAULT FALSE,
579
+ -- UAM: Agent integration columns
580
+ agent_id TEXT,
581
+ tool_name TEXT,
582
+ session_id TEXT,
583
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
466
584
  );`,
467
- `CREATE INDEX IF NOT EXISTS observations_project_idx ON observations(project_id);`,
468
- `CREATE INDEX IF NOT EXISTS observations_type_idx ON observations(type);`,
469
- `CREATE INDEX IF NOT EXISTS observations_action_idx ON observations(action);`,
470
- `CREATE INDEX IF NOT EXISTS observations_created_idx ON observations(created_at);`,
471
- `CREATE TABLE IF NOT EXISTS entities (
472
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
473
- project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
474
- name TEXT NOT NULL,
475
- type TEXT NOT NULL,
476
- description TEXT,
477
- embedding vector(1536),
478
- properties JSONB,
479
- created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
480
- updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
585
+ `CREATE INDEX IF NOT EXISTS learnings_project_idx ON learnings(project_id);`,
586
+ `CREATE INDEX IF NOT EXISTS learnings_type_idx ON learnings(type);`,
587
+ `CREATE INDEX IF NOT EXISTS learnings_action_idx ON learnings(action);`,
588
+ `CREATE TABLE IF NOT EXISTS entities (
589
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
590
+ project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
591
+ name TEXT NOT NULL,
592
+ type TEXT NOT NULL,
593
+ description TEXT,
594
+ embedding vector(1536),
595
+ properties JSONB,
596
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
597
+ updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
481
598
  );`,
482
599
  `CREATE INDEX IF NOT EXISTS entities_project_idx ON entities(project_id);`,
483
600
  `CREATE INDEX IF NOT EXISTS entities_type_idx ON entities(type);`,
484
601
  `CREATE INDEX IF NOT EXISTS entities_name_idx ON entities(name);`,
485
- `CREATE TABLE IF NOT EXISTS entity_relations (
486
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
487
- from_entity_id UUID NOT NULL REFERENCES entities(id) ON DELETE CASCADE,
488
- to_entity_id UUID NOT NULL REFERENCES entities(id) ON DELETE CASCADE,
489
- type TEXT NOT NULL,
490
- weight INTEGER DEFAULT 1,
491
- properties JSONB,
492
- created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
602
+ `CREATE TABLE IF NOT EXISTS entity_relations (
603
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
604
+ from_entity_id UUID NOT NULL REFERENCES entities(id) ON DELETE CASCADE,
605
+ to_entity_id UUID NOT NULL REFERENCES entities(id) ON DELETE CASCADE,
606
+ type TEXT NOT NULL,
607
+ weight INTEGER DEFAULT 1,
608
+ properties JSONB,
609
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
493
610
  );`,
494
611
  `CREATE INDEX IF NOT EXISTS relations_from_idx ON entity_relations(from_entity_id);`,
495
612
  `CREATE INDEX IF NOT EXISTS relations_to_idx ON entity_relations(to_entity_id);`,
496
613
  `CREATE INDEX IF NOT EXISTS relations_type_idx ON entity_relations(type);`,
497
- `CREATE TABLE IF NOT EXISTS core_memory (
498
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
499
- project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
500
- user_id UUID REFERENCES users(id) ON DELETE SET NULL,
501
- section TEXT NOT NULL,
502
- content TEXT NOT NULL DEFAULT '',
503
- size_bytes INTEGER DEFAULT 0 NOT NULL,
504
- version INTEGER DEFAULT 1 NOT NULL,
505
- created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
506
- updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
614
+ `CREATE TABLE IF NOT EXISTS core_memory (
615
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
616
+ project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
617
+ user_id UUID REFERENCES users(id) ON DELETE SET NULL,
618
+ section TEXT NOT NULL,
619
+ content TEXT NOT NULL DEFAULT '',
620
+ size_bytes INTEGER DEFAULT 0 NOT NULL,
621
+ version INTEGER DEFAULT 1 NOT NULL,
622
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
623
+ updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
507
624
  );`,
508
625
  `CREATE INDEX IF NOT EXISTS core_memory_project_idx ON core_memory(project_id);`,
509
626
  `CREATE INDEX IF NOT EXISTS core_memory_user_idx ON core_memory(user_id);`,
510
627
  `CREATE INDEX IF NOT EXISTS core_memory_section_idx ON core_memory(section);`,
511
- `CREATE TABLE IF NOT EXISTS context_sessions (
512
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
513
- session_id TEXT NOT NULL UNIQUE,
514
- project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
515
- user_id UUID REFERENCES users(id) ON DELETE SET NULL,
516
- loaded_memory_ids JSONB,
517
- token_budget INTEGER DEFAULT 8000 NOT NULL,
518
- tokens_used INTEGER DEFAULT 0 NOT NULL,
519
- core_memory_tokens INTEGER DEFAULT 0 NOT NULL,
520
- loaded_memories_tokens INTEGER DEFAULT 0 NOT NULL,
521
- metadata JSONB,
522
- created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
523
- updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
628
+ `CREATE TABLE IF NOT EXISTS context_sessions (
629
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
630
+ session_id TEXT NOT NULL UNIQUE,
631
+ project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
632
+ user_id UUID REFERENCES users(id) ON DELETE SET NULL,
633
+ loaded_memory_ids JSONB,
634
+ token_budget INTEGER DEFAULT 8000 NOT NULL,
635
+ tokens_used INTEGER DEFAULT 0 NOT NULL,
636
+ core_memory_tokens INTEGER DEFAULT 0 NOT NULL,
637
+ loaded_memories_tokens INTEGER DEFAULT 0 NOT NULL,
638
+ metadata JSONB,
639
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
640
+ updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
524
641
  );`,
525
642
  `CREATE INDEX IF NOT EXISTS context_sessions_session_idx ON context_sessions(session_id);`,
526
643
  `CREATE INDEX IF NOT EXISTS context_sessions_project_idx ON context_sessions(project_id);`,
527
644
  `CREATE INDEX IF NOT EXISTS context_sessions_created_idx ON context_sessions(created_at);`,
528
- `CREATE TABLE IF NOT EXISTS memory_merge_proposals (
529
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
530
- project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
531
- user_id UUID REFERENCES users(id) ON DELETE SET NULL,
532
- source_memory_ids TEXT NOT NULL,
533
- proposed_content TEXT NOT NULL,
534
- proposed_summary TEXT,
535
- proposed_tags TEXT[],
536
- proposed_metadata JSONB,
537
- detection_method TEXT NOT NULL,
538
- similarity_score TEXT NOT NULL,
539
- confidence_level TEXT NOT NULL,
540
- merge_reason TEXT NOT NULL,
541
- conflict_warnings JSONB,
542
- status TEXT DEFAULT 'pending' NOT NULL,
543
- reviewed_at TIMESTAMPTZ,
544
- review_notes TEXT,
545
- created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
546
- expires_at TIMESTAMPTZ
645
+ `CREATE TABLE IF NOT EXISTS memory_merge_proposals (
646
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
647
+ project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
648
+ user_id UUID REFERENCES users(id) ON DELETE SET NULL,
649
+ source_memory_ids TEXT NOT NULL,
650
+ proposed_content TEXT NOT NULL,
651
+ proposed_summary TEXT,
652
+ proposed_tags TEXT[],
653
+ proposed_metadata JSONB,
654
+ detection_method TEXT NOT NULL,
655
+ similarity_score TEXT NOT NULL,
656
+ confidence_level TEXT NOT NULL,
657
+ merge_reason TEXT NOT NULL,
658
+ conflict_warnings JSONB,
659
+ status TEXT DEFAULT 'pending' NOT NULL,
660
+ reviewed_at TIMESTAMPTZ,
661
+ review_notes TEXT,
662
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
663
+ expires_at TIMESTAMPTZ
547
664
  );`,
548
665
  `CREATE INDEX IF NOT EXISTS memory_merge_proposals_project_status_idx ON memory_merge_proposals(project_id, status);`,
549
666
  `CREATE INDEX IF NOT EXISTS memory_merge_proposals_created_at_idx ON memory_merge_proposals(created_at);`,
550
- `CREATE TABLE IF NOT EXISTS memory_merge_history (
551
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
552
- project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
553
- user_id UUID REFERENCES users(id) ON DELETE SET NULL,
554
- proposal_id UUID REFERENCES memory_merge_proposals(id) ON DELETE SET NULL,
555
- source_memory_ids TEXT NOT NULL,
556
- canonical_memory_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
557
- source_memories_snapshot JSONB NOT NULL,
558
- merge_strategy TEXT NOT NULL,
559
- tokens_saved INTEGER,
560
- is_reversed BOOLEAN DEFAULT FALSE,
561
- reversed_at TIMESTAMPTZ,
562
- reversed_by UUID,
563
- merged_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
667
+ `CREATE TABLE IF NOT EXISTS memory_merge_history (
668
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
669
+ project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
670
+ user_id UUID REFERENCES users(id) ON DELETE SET NULL,
671
+ proposal_id UUID REFERENCES memory_merge_proposals(id) ON DELETE SET NULL,
672
+ source_memory_ids TEXT NOT NULL,
673
+ canonical_memory_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
674
+ source_memories_snapshot JSONB NOT NULL,
675
+ merge_strategy TEXT NOT NULL,
676
+ tokens_saved INTEGER,
677
+ is_reversed BOOLEAN DEFAULT FALSE,
678
+ reversed_at TIMESTAMPTZ,
679
+ reversed_by UUID,
680
+ merged_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
564
681
  );`,
565
- `CREATE TABLE IF NOT EXISTS memory_hash_cache (
566
- memory_id UUID PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
567
- project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
568
- simhash TEXT,
569
- minhash TEXT,
570
- content_hash TEXT NOT NULL,
571
- last_updated TIMESTAMPTZ DEFAULT NOW() NOT NULL
682
+ `CREATE TABLE IF NOT EXISTS memory_hash_cache (
683
+ memory_id UUID PRIMARY KEY REFERENCES memories(id) ON DELETE CASCADE,
684
+ project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
685
+ simhash TEXT,
686
+ minhash TEXT,
687
+ content_hash TEXT NOT NULL,
688
+ last_updated TIMESTAMPTZ DEFAULT NOW() NOT NULL
572
689
  );`,
573
690
  `CREATE INDEX IF NOT EXISTS memory_hash_cache_project_id_idx ON memory_hash_cache(project_id);`,
574
- `CREATE INDEX IF NOT EXISTS memory_hash_cache_simhash_idx ON memory_hash_cache(simhash);`
691
+ `CREATE INDEX IF NOT EXISTS memory_hash_cache_simhash_idx ON memory_hash_cache(simhash);`,
692
+ // memory_associations table (v1.1.0+)
693
+ `CREATE TABLE IF NOT EXISTS memory_associations (
694
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
695
+ from_memory_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
696
+ to_memory_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
697
+ association_type TEXT NOT NULL,
698
+ weight REAL DEFAULT 1,
699
+ coactivation_count INTEGER DEFAULT 1,
700
+ metadata TEXT,
701
+ last_coactivated_at TIMESTAMPTZ,
702
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
703
+ UNIQUE(from_memory_id, to_memory_id)
704
+ );`,
705
+ `CREATE INDEX IF NOT EXISTS associations_graph_traversal_idx ON memory_associations(from_memory_id, to_memory_id, weight, association_type);`,
706
+ // namespaces table
707
+ `CREATE TABLE IF NOT EXISTS namespaces (
708
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
709
+ project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
710
+ name TEXT NOT NULL,
711
+ path TEXT NOT NULL,
712
+ description TEXT,
713
+ parent_id UUID REFERENCES namespaces(id) ON DELETE SET NULL,
714
+ metadata TEXT,
715
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
716
+ updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
717
+ );`,
718
+ `CREATE INDEX IF NOT EXISTS namespaces_project_idx ON namespaces(project_id);`,
719
+ `CREATE INDEX IF NOT EXISTS namespaces_parent_idx ON namespaces(parent_id);`,
720
+ // maintenance_jobs table
721
+ `CREATE TABLE IF NOT EXISTS maintenance_jobs (
722
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
723
+ project_id UUID REFERENCES projects(id) ON DELETE CASCADE,
724
+ job_name TEXT NOT NULL,
725
+ job_type TEXT NOT NULL,
726
+ description TEXT,
727
+ enabled BOOLEAN DEFAULT TRUE,
728
+ cron_expression TEXT,
729
+ interval_ms INTEGER,
730
+ next_run_at TIMESTAMPTZ,
731
+ last_run_at TIMESTAMPTZ,
732
+ last_run_duration INTEGER,
733
+ last_run_status TEXT,
734
+ last_run_error TEXT,
735
+ total_runs INTEGER DEFAULT 0,
736
+ success_count INTEGER DEFAULT 0,
737
+ failure_count INTEGER DEFAULT 0,
738
+ job_config TEXT,
739
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
740
+ updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
741
+ );`,
742
+ `CREATE INDEX IF NOT EXISTS maintenance_jobs_name_idx ON maintenance_jobs(job_name);`,
743
+ `CREATE INDEX IF NOT EXISTS maintenance_jobs_next_run_idx ON maintenance_jobs(next_run_at);`,
744
+ `CREATE INDEX IF NOT EXISTS maintenance_jobs_type_idx ON maintenance_jobs(job_type);`,
745
+ `CREATE INDEX IF NOT EXISTS maintenance_jobs_enabled_idx ON maintenance_jobs(enabled);`,
746
+ // places table (v1.1.5) - Spatial memory organization
747
+ `CREATE TABLE IF NOT EXISTS places (
748
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
749
+ project_id UUID REFERENCES projects(id) ON DELETE CASCADE NOT NULL,
750
+ name TEXT NOT NULL,
751
+ place_type TEXT NOT NULL,
752
+ parent_id UUID REFERENCES places(id) ON DELETE SET NULL,
753
+ loci_index INTEGER DEFAULT 0,
754
+ position_x INTEGER DEFAULT 0,
755
+ position_y INTEGER DEFAULT 0,
756
+ description TEXT,
757
+ purpose TEXT,
758
+ memory_count INTEGER DEFAULT 0,
759
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
760
+ updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
761
+ );`,
762
+ `CREATE INDEX IF NOT EXISTS places_project_idx ON places(project_id);`,
763
+ `CREATE INDEX IF NOT EXISTS places_type_idx ON places(place_type);`,
764
+ `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);`,
766
+ // memory_places table
767
+ `CREATE TABLE IF NOT EXISTS memory_places (
768
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
769
+ memory_id UUID REFERENCES memories(id) ON DELETE CASCADE NOT NULL,
770
+ place_id UUID REFERENCES places(id) ON DELETE CASCADE NOT NULL,
771
+ is_manual BOOLEAN DEFAULT FALSE,
772
+ rule_id UUID,
773
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
774
+ );`,
775
+ `CREATE INDEX IF NOT EXISTS memory_places_memory_idx ON memory_places(memory_id);`,
776
+ `CREATE INDEX IF NOT EXISTS memory_places_place_idx ON memory_places(place_id);`,
777
+ // place_rules table
778
+ `CREATE TABLE IF NOT EXISTS place_rules (
779
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
780
+ project_id UUID REFERENCES projects(id) ON DELETE CASCADE NOT NULL,
781
+ name TEXT NOT NULL,
782
+ place_type TEXT NOT NULL,
783
+ match_tool TEXT,
784
+ match_keyword TEXT,
785
+ match_tag TEXT,
786
+ match_memory_type TEXT,
787
+ priority INTEGER DEFAULT 0,
788
+ enabled BOOLEAN DEFAULT TRUE,
789
+ created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
790
+ updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
791
+ );`,
792
+ `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);`
575
794
  ];
576
795
  /**
577
796
  * Ensure the data directory exists (.squish folder in project root)
@@ -637,7 +856,7 @@ async function runSqliteMigrations(sqlite) {
637
856
  { col: 'retrieval_priority', sql: 'ALTER TABLE memories ADD COLUMN retrieval_priority INTEGER DEFAULT 50' },
638
857
  // Data governance (v0.9.0)
639
858
  { col: 'recorded_at', sql: 'ALTER TABLE memories ADD COLUMN recorded_at INTEGER DEFAULT (strftime(\'%s\',\'now\'))' },
640
- { col: 'confidence', sql: 'ALTER TABLE memories ADD COLUMN confidence INTEGER DEFAULT 100' },
859
+ { col: 'confidence', sql: 'ALTER TABLE memories ADD COLUMN confidence INTEGER DEFAULT 50' },
641
860
  { col: 'valid_from', sql: 'ALTER TABLE memories ADD COLUMN valid_from INTEGER' },
642
861
  { col: 'valid_to', sql: 'ALTER TABLE memories ADD COLUMN valid_to INTEGER' },
643
862
  { col: 'superseded_by', sql: 'ALTER TABLE memories ADD COLUMN superseded_by TEXT' },
@@ -666,8 +885,21 @@ async function runSqliteMigrations(sqlite) {
666
885
  // Namespace support (v1.0.x)
667
886
  { col: 'namespace_id', sql: 'ALTER TABLE memories ADD COLUMN namespace_id TEXT REFERENCES namespaces(id) ON DELETE SET NULL' },
668
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' },
669
891
  // Token tracking (v1.0.x)
670
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' }
671
903
  ];
672
904
  // Get existing columns for memories table
673
905
  const tableInfo = sqlite.prepare("PRAGMA table_info(memories)").all();
@@ -716,6 +948,72 @@ async function runSqliteMigrations(sqlite) {
716
948
  }
717
949
  }
718
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)) {
981
+ try {
982
+ sqlite.exec(migration.sql);
983
+ logger.info(`Migration: Added column ${migration.col} to learnings table`);
984
+ }
985
+ catch (error) {
986
+ 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}`);
992
+ }
993
+ }
994
+ }
995
+ }
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
+ }
1016
+ }
719
1017
  // Migrations for maintenance_jobs table (v1.0.x)
720
1018
  const maintenanceJobsTableCheck = sqlite.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='maintenance_jobs'").get();
721
1019
  if (maintenanceJobsTableCheck) {