specmem-hardwicksoftware 3.5.99

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 (1473) hide show
  1. package/CHANGELOG.md +299 -0
  2. package/LICENSE.md +6406 -0
  3. package/README.md +539 -0
  4. package/bin/AegisTheme.cjs +1022 -0
  5. package/bin/AnsiRenderer.cjs +1055 -0
  6. package/bin/BoxRenderer.cjs +605 -0
  7. package/bin/ClaudeLiveScreen.cjs +1299 -0
  8. package/bin/DashboardModules.cjs +733 -0
  9. package/bin/LiveScreenCapture.cjs +1012 -0
  10. package/bin/MemoryBrowserScreen.cjs +1595 -0
  11. package/bin/TabManager.cjs +1414 -0
  12. package/bin/checkAgentStatus-fix.patch +30 -0
  13. package/bin/mcp-socket-client.cjs +462 -0
  14. package/bin/screen-utils.cjs +106 -0
  15. package/bin/specmem-autoclaude.cjs +663 -0
  16. package/bin/specmem-cleanup.cjs +421 -0
  17. package/bin/specmem-cli.cjs +794 -0
  18. package/bin/specmem-console-teamcomms-class.cjs +428 -0
  19. package/bin/specmem-console.cjs +8104 -0
  20. package/bin/specmem-statusbar.cjs +530 -0
  21. package/bootstrap.cjs +5065 -0
  22. package/claude-hooks/agent-chooser-hook.js +179 -0
  23. package/claude-hooks/agent-chooser-inject.js +121 -0
  24. package/claude-hooks/agent-loading-hook.js +990 -0
  25. package/claude-hooks/agent-output-fader.cjs +542 -0
  26. package/claude-hooks/agent-output-interceptor.js +193 -0
  27. package/claude-hooks/agent-type-matcher.js +419 -0
  28. package/claude-hooks/auto-bypass.py +74 -0
  29. package/claude-hooks/background-completion-silencer.js +134 -0
  30. package/claude-hooks/bash-auto-background.js +182 -0
  31. package/claude-hooks/build-cedict-dictionary.mjs +167 -0
  32. package/claude-hooks/bullshit-radar.cjs +323 -0
  33. package/claude-hooks/cedict-codes.json +270 -0
  34. package/claude-hooks/cedict-extracted.json +22632 -0
  35. package/claude-hooks/claude-watchdog.sh +401 -0
  36. package/claude-hooks/context-dedup.cjs +144 -0
  37. package/claude-hooks/context-yeeter.cjs +244 -0
  38. package/claude-hooks/debug-suffix.cjs +15 -0
  39. package/claude-hooks/debug2.cjs +7 -0
  40. package/claude-hooks/drilldown-enforcer.js +242 -0
  41. package/claude-hooks/english-morphology-standalone.cjs +149 -0
  42. package/claude-hooks/english-morphology.cjs +152 -0
  43. package/claude-hooks/extract-translations.mjs +193 -0
  44. package/claude-hooks/file-claim-enforcer.cjs +293 -0
  45. package/claude-hooks/file-claim-enforcer.js +293 -0
  46. package/claude-hooks/find-collisions.cjs +39 -0
  47. package/claude-hooks/fix-abbreviations.cjs +60 -0
  48. package/claude-hooks/fix-collisions.cjs +60 -0
  49. package/claude-hooks/fix-decompressor.cjs +79 -0
  50. package/claude-hooks/fix-suffixes.cjs +66 -0
  51. package/claude-hooks/grammar-engine.cjs +159 -0
  52. package/claude-hooks/input-aware-improver.js +231 -0
  53. package/claude-hooks/is-agent.cjs +64 -0
  54. package/claude-hooks/mega-test.cjs +213 -0
  55. package/claude-hooks/merge-dictionaries.mjs +207 -0
  56. package/claude-hooks/merged-codes.cjs +22675 -0
  57. package/claude-hooks/merged-codes.json +22676 -0
  58. package/claude-hooks/output-cleaner.cjs +388 -0
  59. package/claude-hooks/post-write-memory-hook.cjs +430 -0
  60. package/claude-hooks/quick-test.cjs +24 -0
  61. package/claude-hooks/quick-test2.cjs +24 -0
  62. package/claude-hooks/remove-bad-codes.cjs +23 -0
  63. package/claude-hooks/search-reminder-hook.js +90 -0
  64. package/claude-hooks/semantic-test.cjs +93 -0
  65. package/claude-hooks/settings.json +445 -0
  66. package/claude-hooks/smart-context-hook.cjs +547 -0
  67. package/claude-hooks/smart-context-hook.js +539 -0
  68. package/claude-hooks/smart-search-interceptor.js +364 -0
  69. package/claude-hooks/socket-connect-helper.cjs +235 -0
  70. package/claude-hooks/specmem/sockets/session-start.lock +1 -0
  71. package/claude-hooks/specmem-context-hook.cjs +357 -0
  72. package/claude-hooks/specmem-context-hook.js +357 -0
  73. package/claude-hooks/specmem-drilldown-hook.cjs +480 -0
  74. package/claude-hooks/specmem-drilldown-hook.js +480 -0
  75. package/claude-hooks/specmem-drilldown-setter.js +210 -0
  76. package/claude-hooks/specmem-paths.cjs +213 -0
  77. package/claude-hooks/specmem-precompact.js +183 -0
  78. package/claude-hooks/specmem-session-init.sh +33 -0
  79. package/claude-hooks/specmem-session-start.cjs +498 -0
  80. package/claude-hooks/specmem-stop-hook.cjs +73 -0
  81. package/claude-hooks/specmem-stop-hook.js +5 -0
  82. package/claude-hooks/specmem-team-comms.cjs +434 -0
  83. package/claude-hooks/specmem-team-member-inject.js +271 -0
  84. package/claude-hooks/specmem-unified-hook.py +670 -0
  85. package/claude-hooks/subagent-loading-hook.js +194 -0
  86. package/claude-hooks/sysprompt-squisher.cjs +167 -0
  87. package/claude-hooks/task-progress-hook.js +204 -0
  88. package/claude-hooks/team-comms-enforcer.cjs +585 -0
  89. package/claude-hooks/test-accuracy.cjs +27 -0
  90. package/claude-hooks/test-big.cjs +28 -0
  91. package/claude-hooks/test-inflectors.cjs +39 -0
  92. package/claude-hooks/test-pluralize.cjs +37 -0
  93. package/claude-hooks/test-quick.cjs +8 -0
  94. package/claude-hooks/test-wink.cjs +20 -0
  95. package/claude-hooks/token-compressor.cjs +940 -0
  96. package/claude-hooks/use-code-pointers.cjs +279 -0
  97. package/commands/COMMAND_TOOL_MAP.md +299 -0
  98. package/commands/specmem-agents.md +412 -0
  99. package/commands/specmem-autoclaude.md +295 -0
  100. package/commands/specmem-changes.md +247 -0
  101. package/commands/specmem-code.md +103 -0
  102. package/commands/specmem-configteammembercomms.md +322 -0
  103. package/commands/specmem-drilldown.md +208 -0
  104. package/commands/specmem-find.md +195 -0
  105. package/commands/specmem-getdashboard.md +243 -0
  106. package/commands/specmem-hooks.md +219 -0
  107. package/commands/specmem-pointers.md +149 -0
  108. package/commands/specmem-progress.md +287 -0
  109. package/commands/specmem-remember.md +123 -0
  110. package/commands/specmem-service.md +349 -0
  111. package/commands/specmem-stats.md +189 -0
  112. package/commands/specmem-team-member.md +409 -0
  113. package/commands/specmem-webdev.md +583 -0
  114. package/commands/specmem.md +363 -0
  115. package/dist/autoStart/index.d.ts +214 -0
  116. package/dist/autoStart/index.d.ts.map +1 -0
  117. package/dist/autoStart/index.js +883 -0
  118. package/dist/autoStart/index.js.map +1 -0
  119. package/dist/claude-sessions/contextRestorationParser.d.ts +74 -0
  120. package/dist/claude-sessions/contextRestorationParser.d.ts.map +1 -0
  121. package/dist/claude-sessions/contextRestorationParser.js +570 -0
  122. package/dist/claude-sessions/contextRestorationParser.js.map +1 -0
  123. package/dist/claude-sessions/index.d.ts +13 -0
  124. package/dist/claude-sessions/index.d.ts.map +1 -0
  125. package/dist/claude-sessions/index.js +11 -0
  126. package/dist/claude-sessions/index.js.map +1 -0
  127. package/dist/claude-sessions/sessionIntegration.d.ts +48 -0
  128. package/dist/claude-sessions/sessionIntegration.d.ts.map +1 -0
  129. package/dist/claude-sessions/sessionIntegration.js +146 -0
  130. package/dist/claude-sessions/sessionIntegration.js.map +1 -0
  131. package/dist/claude-sessions/sessionParser.d.ts +293 -0
  132. package/dist/claude-sessions/sessionParser.d.ts.map +1 -0
  133. package/dist/claude-sessions/sessionParser.js +1028 -0
  134. package/dist/claude-sessions/sessionParser.js.map +1 -0
  135. package/dist/claude-sessions/sessionWatcher.d.ts +139 -0
  136. package/dist/claude-sessions/sessionWatcher.d.ts.map +1 -0
  137. package/dist/claude-sessions/sessionWatcher.js +722 -0
  138. package/dist/claude-sessions/sessionWatcher.js.map +1 -0
  139. package/dist/cli/deploy-to-claude.d.ts +56 -0
  140. package/dist/cli/deploy-to-claude.d.ts.map +1 -0
  141. package/dist/cli/deploy-to-claude.js +576 -0
  142. package/dist/cli/deploy-to-claude.js.map +1 -0
  143. package/dist/code-explanations/explainCode.d.ts +86 -0
  144. package/dist/code-explanations/explainCode.d.ts.map +1 -0
  145. package/dist/code-explanations/explainCode.js +286 -0
  146. package/dist/code-explanations/explainCode.js.map +1 -0
  147. package/dist/code-explanations/feedback.d.ts +87 -0
  148. package/dist/code-explanations/feedback.d.ts.map +1 -0
  149. package/dist/code-explanations/feedback.js +212 -0
  150. package/dist/code-explanations/feedback.js.map +1 -0
  151. package/dist/code-explanations/getRelatedCode.d.ts +80 -0
  152. package/dist/code-explanations/getRelatedCode.d.ts.map +1 -0
  153. package/dist/code-explanations/getRelatedCode.js +262 -0
  154. package/dist/code-explanations/getRelatedCode.js.map +1 -0
  155. package/dist/code-explanations/index.d.ts +284 -0
  156. package/dist/code-explanations/index.d.ts.map +1 -0
  157. package/dist/code-explanations/index.js +249 -0
  158. package/dist/code-explanations/index.js.map +1 -0
  159. package/dist/code-explanations/linkCodeToPrompt.d.ts +79 -0
  160. package/dist/code-explanations/linkCodeToPrompt.d.ts.map +1 -0
  161. package/dist/code-explanations/linkCodeToPrompt.js +213 -0
  162. package/dist/code-explanations/linkCodeToPrompt.js.map +1 -0
  163. package/dist/code-explanations/recallExplanation.d.ts +88 -0
  164. package/dist/code-explanations/recallExplanation.d.ts.map +1 -0
  165. package/dist/code-explanations/recallExplanation.js +218 -0
  166. package/dist/code-explanations/recallExplanation.js.map +1 -0
  167. package/dist/code-explanations/schema.d.ts +32 -0
  168. package/dist/code-explanations/schema.d.ts.map +1 -0
  169. package/dist/code-explanations/schema.js +221 -0
  170. package/dist/code-explanations/schema.js.map +1 -0
  171. package/dist/code-explanations/semanticSearch.d.ts +75 -0
  172. package/dist/code-explanations/semanticSearch.d.ts.map +1 -0
  173. package/dist/code-explanations/semanticSearch.js +203 -0
  174. package/dist/code-explanations/semanticSearch.js.map +1 -0
  175. package/dist/code-explanations/types.d.ts +328 -0
  176. package/dist/code-explanations/types.d.ts.map +1 -0
  177. package/dist/code-explanations/types.js +122 -0
  178. package/dist/code-explanations/types.js.map +1 -0
  179. package/dist/codebase/codeAnalyzer.d.ts +272 -0
  180. package/dist/codebase/codeAnalyzer.d.ts.map +1 -0
  181. package/dist/codebase/codeAnalyzer.js +1353 -0
  182. package/dist/codebase/codeAnalyzer.js.map +1 -0
  183. package/dist/codebase/codebaseIndexer.d.ts +360 -0
  184. package/dist/codebase/codebaseIndexer.d.ts.map +1 -0
  185. package/dist/codebase/codebaseIndexer.js +1735 -0
  186. package/dist/codebase/codebaseIndexer.js.map +1 -0
  187. package/dist/codebase/codebaseTools.d.ts +853 -0
  188. package/dist/codebase/codebaseTools.d.ts.map +1 -0
  189. package/dist/codebase/codebaseTools.js +1279 -0
  190. package/dist/codebase/codebaseTools.js.map +1 -0
  191. package/dist/codebase/exclusions.d.ts +111 -0
  192. package/dist/codebase/exclusions.d.ts.map +1 -0
  193. package/dist/codebase/exclusions.js +771 -0
  194. package/dist/codebase/exclusions.js.map +1 -0
  195. package/dist/codebase/fileWatcher.d.ts +135 -0
  196. package/dist/codebase/fileWatcher.d.ts.map +1 -0
  197. package/dist/codebase/fileWatcher.js +309 -0
  198. package/dist/codebase/fileWatcher.js.map +1 -0
  199. package/dist/codebase/index.d.ts +33 -0
  200. package/dist/codebase/index.d.ts.map +1 -0
  201. package/dist/codebase/index.js +77 -0
  202. package/dist/codebase/index.js.map +1 -0
  203. package/dist/codebase/ingestion.d.ts +177 -0
  204. package/dist/codebase/ingestion.d.ts.map +1 -0
  205. package/dist/codebase/ingestion.js +690 -0
  206. package/dist/codebase/ingestion.js.map +1 -0
  207. package/dist/codebase/languageDetection.d.ts +75 -0
  208. package/dist/codebase/languageDetection.d.ts.map +1 -0
  209. package/dist/codebase/languageDetection.js +768 -0
  210. package/dist/codebase/languageDetection.js.map +1 -0
  211. package/dist/commands/codebaseCommands.d.ts +101 -0
  212. package/dist/commands/codebaseCommands.d.ts.map +1 -0
  213. package/dist/commands/codebaseCommands.js +911 -0
  214. package/dist/commands/codebaseCommands.js.map +1 -0
  215. package/dist/commands/commandHandler.d.ts +126 -0
  216. package/dist/commands/commandHandler.d.ts.map +1 -0
  217. package/dist/commands/commandHandler.js +296 -0
  218. package/dist/commands/commandHandler.js.map +1 -0
  219. package/dist/commands/commandLoader.d.ts +103 -0
  220. package/dist/commands/commandLoader.d.ts.map +1 -0
  221. package/dist/commands/commandLoader.js +223 -0
  222. package/dist/commands/commandLoader.js.map +1 -0
  223. package/dist/commands/contextCommands.d.ts +83 -0
  224. package/dist/commands/contextCommands.d.ts.map +1 -0
  225. package/dist/commands/contextCommands.js +512 -0
  226. package/dist/commands/contextCommands.js.map +1 -0
  227. package/dist/commands/index.d.ts +24 -0
  228. package/dist/commands/index.d.ts.map +1 -0
  229. package/dist/commands/index.js +28 -0
  230. package/dist/commands/index.js.map +1 -0
  231. package/dist/commands/mcpResources.d.ts +50 -0
  232. package/dist/commands/mcpResources.d.ts.map +1 -0
  233. package/dist/commands/mcpResources.js +372 -0
  234. package/dist/commands/mcpResources.js.map +1 -0
  235. package/dist/commands/memoryCommands.d.ts +74 -0
  236. package/dist/commands/memoryCommands.d.ts.map +1 -0
  237. package/dist/commands/memoryCommands.js +609 -0
  238. package/dist/commands/memoryCommands.js.map +1 -0
  239. package/dist/commands/promptCommands.d.ts +91 -0
  240. package/dist/commands/promptCommands.d.ts.map +1 -0
  241. package/dist/commands/promptCommands.js +801 -0
  242. package/dist/commands/promptCommands.js.map +1 -0
  243. package/dist/commands/teamMemberCommands.d.ts +21 -0
  244. package/dist/commands/teamMemberCommands.d.ts.map +1 -0
  245. package/dist/commands/teamMemberCommands.js +137 -0
  246. package/dist/commands/teamMemberCommands.js.map +1 -0
  247. package/dist/comms/fileCommsTransport.d.ts +91 -0
  248. package/dist/comms/fileCommsTransport.d.ts.map +1 -0
  249. package/dist/comms/fileCommsTransport.js +244 -0
  250. package/dist/comms/fileCommsTransport.js.map +1 -0
  251. package/dist/comms/index.d.ts +7 -0
  252. package/dist/comms/index.d.ts.map +1 -0
  253. package/dist/comms/index.js +7 -0
  254. package/dist/comms/index.js.map +1 -0
  255. package/dist/config/apiKeyDetection.d.ts +41 -0
  256. package/dist/config/apiKeyDetection.d.ts.map +1 -0
  257. package/dist/config/apiKeyDetection.js +211 -0
  258. package/dist/config/apiKeyDetection.js.map +1 -0
  259. package/dist/config/autoConfig.d.ts +188 -0
  260. package/dist/config/autoConfig.d.ts.map +1 -0
  261. package/dist/config/autoConfig.js +850 -0
  262. package/dist/config/autoConfig.js.map +1 -0
  263. package/dist/config/configSync.d.ts +119 -0
  264. package/dist/config/configSync.d.ts.map +1 -0
  265. package/dist/config/configSync.js +878 -0
  266. package/dist/config/configSync.js.map +1 -0
  267. package/dist/config/embeddingTimeouts.d.ts +145 -0
  268. package/dist/config/embeddingTimeouts.d.ts.map +1 -0
  269. package/dist/config/embeddingTimeouts.js +255 -0
  270. package/dist/config/embeddingTimeouts.js.map +1 -0
  271. package/dist/config/index.d.ts +5 -0
  272. package/dist/config/index.d.ts.map +1 -0
  273. package/dist/config/index.js +7 -0
  274. package/dist/config/index.js.map +1 -0
  275. package/dist/config/languageConfig.d.ts +68 -0
  276. package/dist/config/languageConfig.d.ts.map +1 -0
  277. package/dist/config/languageConfig.js +473 -0
  278. package/dist/config/languageConfig.js.map +1 -0
  279. package/dist/config/password.d.ts +145 -0
  280. package/dist/config/password.d.ts.map +1 -0
  281. package/dist/config/password.js +428 -0
  282. package/dist/config/password.js.map +1 -0
  283. package/dist/config.d.ts +338 -0
  284. package/dist/config.d.ts.map +1 -0
  285. package/dist/config.js +1177 -0
  286. package/dist/config.js.map +1 -0
  287. package/dist/consolidation.d.ts +44 -0
  288. package/dist/consolidation.d.ts.map +1 -0
  289. package/dist/consolidation.js +447 -0
  290. package/dist/consolidation.js.map +1 -0
  291. package/dist/constants.d.ts +371 -0
  292. package/dist/constants.d.ts.map +1 -0
  293. package/dist/constants.js +552 -0
  294. package/dist/constants.js.map +1 -0
  295. package/dist/coordination/TeamMemberRegistry.d.ts +192 -0
  296. package/dist/coordination/TeamMemberRegistry.d.ts.map +1 -0
  297. package/dist/coordination/TeamMemberRegistry.js +415 -0
  298. package/dist/coordination/TeamMemberRegistry.js.map +1 -0
  299. package/dist/coordination/events.d.ts +369 -0
  300. package/dist/coordination/events.d.ts.map +1 -0
  301. package/dist/coordination/events.js +232 -0
  302. package/dist/coordination/events.js.map +1 -0
  303. package/dist/coordination/handlers.d.ts +116 -0
  304. package/dist/coordination/handlers.d.ts.map +1 -0
  305. package/dist/coordination/handlers.js +400 -0
  306. package/dist/coordination/handlers.js.map +1 -0
  307. package/dist/coordination/index.d.ts +14 -0
  308. package/dist/coordination/index.d.ts.map +1 -0
  309. package/dist/coordination/index.js +31 -0
  310. package/dist/coordination/index.js.map +1 -0
  311. package/dist/coordination/integration.d.ts +260 -0
  312. package/dist/coordination/integration.d.ts.map +1 -0
  313. package/dist/coordination/integration.js +472 -0
  314. package/dist/coordination/integration.js.map +1 -0
  315. package/dist/coordination/server.d.ts +266 -0
  316. package/dist/coordination/server.d.ts.map +1 -0
  317. package/dist/coordination/server.js +995 -0
  318. package/dist/coordination/server.js.map +1 -0
  319. package/dist/coordination/serviceProvider.d.ts +70 -0
  320. package/dist/coordination/serviceProvider.d.ts.map +1 -0
  321. package/dist/coordination/serviceProvider.js +273 -0
  322. package/dist/coordination/serviceProvider.js.map +1 -0
  323. package/dist/dashboard/api/claudeControl.d.ts +44 -0
  324. package/dist/dashboard/api/claudeControl.d.ts.map +1 -0
  325. package/dist/dashboard/api/claudeControl.js +650 -0
  326. package/dist/dashboard/api/claudeControl.js.map +1 -0
  327. package/dist/dashboard/api/claudeHistory.d.ts +4 -0
  328. package/dist/dashboard/api/claudeHistory.d.ts.map +1 -0
  329. package/dist/dashboard/api/claudeHistory.js +319 -0
  330. package/dist/dashboard/api/claudeHistory.js.map +1 -0
  331. package/dist/dashboard/api/dataExport.d.ts +23 -0
  332. package/dist/dashboard/api/dataExport.d.ts.map +1 -0
  333. package/dist/dashboard/api/dataExport.js +509 -0
  334. package/dist/dashboard/api/dataExport.js.map +1 -0
  335. package/dist/dashboard/api/fileManager.d.ts +39 -0
  336. package/dist/dashboard/api/fileManager.d.ts.map +1 -0
  337. package/dist/dashboard/api/fileManager.js +814 -0
  338. package/dist/dashboard/api/fileManager.js.map +1 -0
  339. package/dist/dashboard/api/hooks.d.ts +16 -0
  340. package/dist/dashboard/api/hooks.d.ts.map +1 -0
  341. package/dist/dashboard/api/hooks.js +342 -0
  342. package/dist/dashboard/api/hooks.js.map +1 -0
  343. package/dist/dashboard/api/hotReload.d.ts +14 -0
  344. package/dist/dashboard/api/hotReload.d.ts.map +1 -0
  345. package/dist/dashboard/api/hotReload.js +219 -0
  346. package/dist/dashboard/api/hotReload.js.map +1 -0
  347. package/dist/dashboard/api/liveSessionStream.d.ts +19 -0
  348. package/dist/dashboard/api/liveSessionStream.d.ts.map +1 -0
  349. package/dist/dashboard/api/liveSessionStream.js +430 -0
  350. package/dist/dashboard/api/liveSessionStream.js.map +1 -0
  351. package/dist/dashboard/api/memoryRecall.d.ts +20 -0
  352. package/dist/dashboard/api/memoryRecall.d.ts.map +1 -0
  353. package/dist/dashboard/api/memoryRecall.js +524 -0
  354. package/dist/dashboard/api/memoryRecall.js.map +1 -0
  355. package/dist/dashboard/api/promptSend.d.ts +33 -0
  356. package/dist/dashboard/api/promptSend.d.ts.map +1 -0
  357. package/dist/dashboard/api/promptSend.js +544 -0
  358. package/dist/dashboard/api/promptSend.js.map +1 -0
  359. package/dist/dashboard/api/settings.d.ts +10 -0
  360. package/dist/dashboard/api/settings.d.ts.map +1 -0
  361. package/dist/dashboard/api/settings.js +656 -0
  362. package/dist/dashboard/api/settings.js.map +1 -0
  363. package/dist/dashboard/api/setup.d.ts +21 -0
  364. package/dist/dashboard/api/setup.d.ts.map +1 -0
  365. package/dist/dashboard/api/setup.js +663 -0
  366. package/dist/dashboard/api/setup.js.map +1 -0
  367. package/dist/dashboard/api/specmemTools.d.ts +14 -0
  368. package/dist/dashboard/api/specmemTools.d.ts.map +1 -0
  369. package/dist/dashboard/api/specmemTools.js +1059 -0
  370. package/dist/dashboard/api/specmemTools.js.map +1 -0
  371. package/dist/dashboard/api/taskTeamMembers.d.ts +8 -0
  372. package/dist/dashboard/api/taskTeamMembers.d.ts.map +1 -0
  373. package/dist/dashboard/api/taskTeamMembers.js +136 -0
  374. package/dist/dashboard/api/taskTeamMembers.js.map +1 -0
  375. package/dist/dashboard/api/teamMemberDeploy.d.ts +15 -0
  376. package/dist/dashboard/api/teamMemberDeploy.d.ts.map +1 -0
  377. package/dist/dashboard/api/teamMemberDeploy.js +421 -0
  378. package/dist/dashboard/api/teamMemberDeploy.js.map +1 -0
  379. package/dist/dashboard/api/teamMemberHistory.d.ts +38 -0
  380. package/dist/dashboard/api/teamMemberHistory.d.ts.map +1 -0
  381. package/dist/dashboard/api/teamMemberHistory.js +583 -0
  382. package/dist/dashboard/api/teamMemberHistory.js.map +1 -0
  383. package/dist/dashboard/api/terminal.d.ts +12 -0
  384. package/dist/dashboard/api/terminal.d.ts.map +1 -0
  385. package/dist/dashboard/api/terminal.js +344 -0
  386. package/dist/dashboard/api/terminal.js.map +1 -0
  387. package/dist/dashboard/api/terminalInject.d.ts +17 -0
  388. package/dist/dashboard/api/terminalInject.d.ts.map +1 -0
  389. package/dist/dashboard/api/terminalInject.js +322 -0
  390. package/dist/dashboard/api/terminalInject.js.map +1 -0
  391. package/dist/dashboard/api/terminalStream.d.ts +12 -0
  392. package/dist/dashboard/api/terminalStream.d.ts.map +1 -0
  393. package/dist/dashboard/api/terminalStream.js +482 -0
  394. package/dist/dashboard/api/terminalStream.js.map +1 -0
  395. package/dist/dashboard/index.d.ts +7 -0
  396. package/dist/dashboard/index.d.ts.map +1 -0
  397. package/dist/dashboard/index.js +7 -0
  398. package/dist/dashboard/index.js.map +1 -0
  399. package/dist/dashboard/ptyStreamer.d.ts +173 -0
  400. package/dist/dashboard/ptyStreamer.d.ts.map +1 -0
  401. package/dist/dashboard/ptyStreamer.js +661 -0
  402. package/dist/dashboard/ptyStreamer.js.map +1 -0
  403. package/dist/dashboard/public/DASHBOARD-README.md +378 -0
  404. package/dist/dashboard/public/INTEGRATION-GUIDE.md +395 -0
  405. package/dist/dashboard/public/codebase-config.html +1247 -0
  406. package/dist/dashboard/public/dashboard-v2.html +1942 -0
  407. package/dist/dashboard/public/data-export.html +819 -0
  408. package/dist/dashboard/public/example-page.html +164 -0
  409. package/dist/dashboard/public/file-explorer.html +1023 -0
  410. package/dist/dashboard/public/hooks.html +1103 -0
  411. package/dist/dashboard/public/index-improvements.css +499 -0
  412. package/dist/dashboard/public/index.html +5534 -0
  413. package/dist/dashboard/public/memory-controls.html +1959 -0
  414. package/dist/dashboard/public/memory-recall.html +1495 -0
  415. package/dist/dashboard/public/previews/skeleton-memory-graph.html +361 -0
  416. package/dist/dashboard/public/previews/skeleton-memory-list.html +366 -0
  417. package/dist/dashboard/public/previews/skeleton-search-results.html +609 -0
  418. package/dist/dashboard/public/previews/skeleton-stats-dashboard.html +556 -0
  419. package/dist/dashboard/public/prompt-console.html +2763 -0
  420. package/dist/dashboard/public/react-dist/assets/index-CkjobT5B.js +871 -0
  421. package/dist/dashboard/public/react-dist/assets/index-iRclxMst.css +1 -0
  422. package/dist/dashboard/public/react-dist/index.html +16 -0
  423. package/dist/dashboard/public/shared-header.js +325 -0
  424. package/dist/dashboard/public/shared-language-selector.js +626 -0
  425. package/dist/dashboard/public/shared-logger.js +66 -0
  426. package/dist/dashboard/public/shared-nav.js +325 -0
  427. package/dist/dashboard/public/shared-theme-blue.css +331 -0
  428. package/dist/dashboard/public/shared-theme.css +813 -0
  429. package/dist/dashboard/public/shared-toast.js +415 -0
  430. package/dist/dashboard/public/team-member-history.html +1291 -0
  431. package/dist/dashboard/public/team-member-spy.html +1199 -0
  432. package/dist/dashboard/public/team-members.html +3756 -0
  433. package/dist/dashboard/public/terminal-output.html +1013 -0
  434. package/dist/dashboard/public/terminal.html +372 -0
  435. package/dist/dashboard/sessionStore.d.ts +86 -0
  436. package/dist/dashboard/sessionStore.d.ts.map +1 -0
  437. package/dist/dashboard/sessionStore.js +262 -0
  438. package/dist/dashboard/sessionStore.js.map +1 -0
  439. package/dist/dashboard/standalone.d.ts +27 -0
  440. package/dist/dashboard/standalone.d.ts.map +1 -0
  441. package/dist/dashboard/standalone.js +380 -0
  442. package/dist/dashboard/standalone.js.map +1 -0
  443. package/dist/dashboard/webServer.d.ts +390 -0
  444. package/dist/dashboard/webServer.d.ts.map +1 -0
  445. package/dist/dashboard/webServer.js +4297 -0
  446. package/dist/dashboard/webServer.js.map +1 -0
  447. package/dist/dashboard/websocket/teamMemberStream.d.ts +87 -0
  448. package/dist/dashboard/websocket/teamMemberStream.d.ts.map +1 -0
  449. package/dist/dashboard/websocket/teamMemberStream.js +366 -0
  450. package/dist/dashboard/websocket/teamMemberStream.js.map +1 -0
  451. package/dist/dashboard/websocket/terminalStream.d.ts +130 -0
  452. package/dist/dashboard/websocket/terminalStream.d.ts.map +1 -0
  453. package/dist/dashboard/websocket/terminalStream.js +456 -0
  454. package/dist/dashboard/websocket/terminalStream.js.map +1 -0
  455. package/dist/database/embeddedPostgres.d.ts +187 -0
  456. package/dist/database/embeddedPostgres.d.ts.map +1 -0
  457. package/dist/database/embeddedPostgres.js +763 -0
  458. package/dist/database/embeddedPostgres.js.map +1 -0
  459. package/dist/database/index.d.ts +12 -0
  460. package/dist/database/index.d.ts.map +1 -0
  461. package/dist/database/index.js +20 -0
  462. package/dist/database/index.js.map +1 -0
  463. package/dist/database/initEmbeddedPostgres.d.ts +124 -0
  464. package/dist/database/initEmbeddedPostgres.d.ts.map +1 -0
  465. package/dist/database/initEmbeddedPostgres.js +855 -0
  466. package/dist/database/initEmbeddedPostgres.js.map +1 -0
  467. package/dist/database.d.ts +256 -0
  468. package/dist/database.d.ts.map +1 -0
  469. package/dist/database.js +1209 -0
  470. package/dist/database.js.map +1 -0
  471. package/dist/db/apiDataManager.d.ts +334 -0
  472. package/dist/db/apiDataManager.d.ts.map +1 -0
  473. package/dist/db/apiDataManager.js +631 -0
  474. package/dist/db/apiDataManager.js.map +1 -0
  475. package/dist/db/batchOperations.d.ts +154 -0
  476. package/dist/db/batchOperations.d.ts.map +1 -0
  477. package/dist/db/batchOperations.js +564 -0
  478. package/dist/db/batchOperations.js.map +1 -0
  479. package/dist/db/bigBrainMigrations.d.ts +48 -0
  480. package/dist/db/bigBrainMigrations.d.ts.map +1 -0
  481. package/dist/db/bigBrainMigrations.js +4266 -0
  482. package/dist/db/bigBrainMigrations.js.map +1 -0
  483. package/dist/db/connectionPoolGoBrrr.d.ts +94 -0
  484. package/dist/db/connectionPoolGoBrrr.d.ts.map +1 -0
  485. package/dist/db/connectionPoolGoBrrr.js +548 -0
  486. package/dist/db/connectionPoolGoBrrr.js.map +1 -0
  487. package/dist/db/dashboardQueries.d.ts +182 -0
  488. package/dist/db/dashboardQueries.d.ts.map +1 -0
  489. package/dist/db/dashboardQueries.js +821 -0
  490. package/dist/db/dashboardQueries.js.map +1 -0
  491. package/dist/db/deploymentBootstrap.d.ts +43 -0
  492. package/dist/db/deploymentBootstrap.d.ts.map +1 -0
  493. package/dist/db/deploymentBootstrap.js +329 -0
  494. package/dist/db/deploymentBootstrap.js.map +1 -0
  495. package/dist/db/dimensionService.d.ts +140 -0
  496. package/dist/db/dimensionService.d.ts.map +1 -0
  497. package/dist/db/dimensionService.js +261 -0
  498. package/dist/db/dimensionService.js.map +1 -0
  499. package/dist/db/embeddingOverflow.d.ts +69 -0
  500. package/dist/db/embeddingOverflow.d.ts.map +1 -0
  501. package/dist/db/embeddingOverflow.js +332 -0
  502. package/dist/db/embeddingOverflow.js.map +1 -0
  503. package/dist/db/embeddingOverflow.sql +221 -0
  504. package/dist/db/findThatShit.d.ts +145 -0
  505. package/dist/db/findThatShit.d.ts.map +1 -0
  506. package/dist/db/findThatShit.js +782 -0
  507. package/dist/db/findThatShit.js.map +1 -0
  508. package/dist/db/hotPathManager.d.ts +187 -0
  509. package/dist/db/hotPathManager.d.ts.map +1 -0
  510. package/dist/db/hotPathManager.js +504 -0
  511. package/dist/db/hotPathManager.js.map +1 -0
  512. package/dist/db/index.d.ts +85 -0
  513. package/dist/db/index.d.ts.map +1 -0
  514. package/dist/db/index.js +219 -0
  515. package/dist/db/index.js.map +1 -0
  516. package/dist/db/memoryDrilldown.sql +99 -0
  517. package/dist/db/migrate.d.ts +3 -0
  518. package/dist/db/migrate.d.ts.map +1 -0
  519. package/dist/db/migrate.js +97 -0
  520. package/dist/db/migrate.js.map +1 -0
  521. package/dist/db/migrateJsonToPostgres.d.ts +43 -0
  522. package/dist/db/migrateJsonToPostgres.d.ts.map +1 -0
  523. package/dist/db/migrateJsonToPostgres.js +465 -0
  524. package/dist/db/migrateJsonToPostgres.js.map +1 -0
  525. package/dist/db/nukeFromOrbit.d.ts +63 -0
  526. package/dist/db/nukeFromOrbit.d.ts.map +1 -0
  527. package/dist/db/nukeFromOrbit.js +499 -0
  528. package/dist/db/nukeFromOrbit.js.map +1 -0
  529. package/dist/db/processedTraining.sql +60 -0
  530. package/dist/db/projectNamespacing.d.ts +258 -0
  531. package/dist/db/projectNamespacing.d.ts.map +1 -0
  532. package/dist/db/projectNamespacing.js +920 -0
  533. package/dist/db/projectNamespacing.js.map +1 -0
  534. package/dist/db/projectNamespacing.sql +374 -0
  535. package/dist/db/projectSchemaInit.sql +271 -0
  536. package/dist/db/spatialMemory.d.ts +296 -0
  537. package/dist/db/spatialMemory.d.ts.map +1 -0
  538. package/dist/db/spatialMemory.js +818 -0
  539. package/dist/db/spatialMemory.js.map +1 -0
  540. package/dist/db/streamingQuery.d.ts +143 -0
  541. package/dist/db/streamingQuery.d.ts.map +1 -0
  542. package/dist/db/streamingQuery.js +350 -0
  543. package/dist/db/streamingQuery.js.map +1 -0
  544. package/dist/db/teamComms.sql +224 -0
  545. package/dist/db/yeetStuffInDb.d.ts +72 -0
  546. package/dist/db/yeetStuffInDb.d.ts.map +1 -0
  547. package/dist/db/yeetStuffInDb.js +473 -0
  548. package/dist/db/yeetStuffInDb.js.map +1 -0
  549. package/dist/embedding-providers/index.d.ts +10 -0
  550. package/dist/embedding-providers/index.d.ts.map +1 -0
  551. package/dist/embedding-providers/index.js +12 -0
  552. package/dist/embedding-providers/index.js.map +1 -0
  553. package/dist/embeddings/projectionLayer.d.ts +114 -0
  554. package/dist/embeddings/projectionLayer.d.ts.map +1 -0
  555. package/dist/embeddings/projectionLayer.js +345 -0
  556. package/dist/embeddings/projectionLayer.js.map +1 -0
  557. package/dist/events/Publisher.d.ts +193 -0
  558. package/dist/events/Publisher.d.ts.map +1 -0
  559. package/dist/events/Publisher.js +439 -0
  560. package/dist/events/Publisher.js.map +1 -0
  561. package/dist/events/config.d.ts +139 -0
  562. package/dist/events/config.d.ts.map +1 -0
  563. package/dist/events/config.js +266 -0
  564. package/dist/events/config.js.map +1 -0
  565. package/dist/events/index.d.ts +19 -0
  566. package/dist/events/index.d.ts.map +1 -0
  567. package/dist/events/index.js +31 -0
  568. package/dist/events/index.js.map +1 -0
  569. package/dist/events/integration.d.ts +206 -0
  570. package/dist/events/integration.d.ts.map +1 -0
  571. package/dist/events/integration.js +348 -0
  572. package/dist/events/integration.js.map +1 -0
  573. package/dist/events/metrics.d.ts +147 -0
  574. package/dist/events/metrics.d.ts.map +1 -0
  575. package/dist/events/metrics.js +343 -0
  576. package/dist/events/metrics.js.map +1 -0
  577. package/dist/hooks/cli.d.ts +28 -0
  578. package/dist/hooks/cli.d.ts.map +1 -0
  579. package/dist/hooks/cli.js +118 -0
  580. package/dist/hooks/cli.js.map +1 -0
  581. package/dist/hooks/contextInjectionHook.d.ts +60 -0
  582. package/dist/hooks/contextInjectionHook.d.ts.map +1 -0
  583. package/dist/hooks/contextInjectionHook.js +294 -0
  584. package/dist/hooks/contextInjectionHook.js.map +1 -0
  585. package/dist/hooks/drilldownHook.d.ts +125 -0
  586. package/dist/hooks/drilldownHook.d.ts.map +1 -0
  587. package/dist/hooks/drilldownHook.js +181 -0
  588. package/dist/hooks/drilldownHook.js.map +1 -0
  589. package/dist/hooks/hookManager.d.ts +180 -0
  590. package/dist/hooks/hookManager.d.ts.map +1 -0
  591. package/dist/hooks/hookManager.js +782 -0
  592. package/dist/hooks/hookManager.js.map +1 -0
  593. package/dist/hooks/index.d.ts +62 -0
  594. package/dist/hooks/index.d.ts.map +1 -0
  595. package/dist/hooks/index.js +66 -0
  596. package/dist/hooks/index.js.map +1 -0
  597. package/dist/hooks/lowContextHook.d.ts +71 -0
  598. package/dist/hooks/lowContextHook.d.ts.map +1 -0
  599. package/dist/hooks/lowContextHook.js +258 -0
  600. package/dist/hooks/lowContextHook.js.map +1 -0
  601. package/dist/hooks/simpleContextHook.d.ts +65 -0
  602. package/dist/hooks/simpleContextHook.d.ts.map +1 -0
  603. package/dist/hooks/simpleContextHook.js +194 -0
  604. package/dist/hooks/simpleContextHook.js.map +1 -0
  605. package/dist/hooks/teamFramingCli.d.ts +56 -0
  606. package/dist/hooks/teamFramingCli.d.ts.map +1 -0
  607. package/dist/hooks/teamFramingCli.js +264 -0
  608. package/dist/hooks/teamFramingCli.js.map +1 -0
  609. package/dist/hooks/teamMemberPrepromptHook.d.ts +150 -0
  610. package/dist/hooks/teamMemberPrepromptHook.d.ts.map +1 -0
  611. package/dist/hooks/teamMemberPrepromptHook.js +308 -0
  612. package/dist/hooks/teamMemberPrepromptHook.js.map +1 -0
  613. package/dist/index.d.ts +42 -0
  614. package/dist/index.d.ts.map +1 -0
  615. package/dist/index.js +4433 -0
  616. package/dist/index.js.map +1 -0
  617. package/dist/init/claudeConfigInjector.d.ts +116 -0
  618. package/dist/init/claudeConfigInjector.d.ts.map +1 -0
  619. package/dist/init/claudeConfigInjector.js +1154 -0
  620. package/dist/init/claudeConfigInjector.js.map +1 -0
  621. package/dist/installer/autoInstall.d.ts +72 -0
  622. package/dist/installer/autoInstall.d.ts.map +1 -0
  623. package/dist/installer/autoInstall.js +617 -0
  624. package/dist/installer/autoInstall.js.map +1 -0
  625. package/dist/installer/dbSetup.d.ts +84 -0
  626. package/dist/installer/dbSetup.d.ts.map +1 -0
  627. package/dist/installer/dbSetup.js +350 -0
  628. package/dist/installer/dbSetup.js.map +1 -0
  629. package/dist/installer/firstRun.d.ts +49 -0
  630. package/dist/installer/firstRun.d.ts.map +1 -0
  631. package/dist/installer/firstRun.js +207 -0
  632. package/dist/installer/firstRun.js.map +1 -0
  633. package/dist/installer/index.d.ts +10 -0
  634. package/dist/installer/index.d.ts.map +1 -0
  635. package/dist/installer/index.js +10 -0
  636. package/dist/installer/index.js.map +1 -0
  637. package/dist/installer/silentAutoInstall.d.ts +99 -0
  638. package/dist/installer/silentAutoInstall.d.ts.map +1 -0
  639. package/dist/installer/silentAutoInstall.js +491 -0
  640. package/dist/installer/silentAutoInstall.js.map +1 -0
  641. package/dist/installer/systemDeps.d.ts +54 -0
  642. package/dist/installer/systemDeps.d.ts.map +1 -0
  643. package/dist/installer/systemDeps.js +322 -0
  644. package/dist/installer/systemDeps.js.map +1 -0
  645. package/dist/mcp/cliNotifications.d.ts +133 -0
  646. package/dist/mcp/cliNotifications.d.ts.map +1 -0
  647. package/dist/mcp/cliNotifications.js +289 -0
  648. package/dist/mcp/cliNotifications.js.map +1 -0
  649. package/dist/mcp/embeddingServerManager.d.ts +307 -0
  650. package/dist/mcp/embeddingServerManager.d.ts.map +1 -0
  651. package/dist/mcp/embeddingServerManager.js +2081 -0
  652. package/dist/mcp/embeddingServerManager.js.map +1 -0
  653. package/dist/mcp/healthMonitor.d.ts +196 -0
  654. package/dist/mcp/healthMonitor.d.ts.map +1 -0
  655. package/dist/mcp/healthMonitor.js +685 -0
  656. package/dist/mcp/healthMonitor.js.map +1 -0
  657. package/dist/mcp/hotReloadManager.d.ts +101 -0
  658. package/dist/mcp/hotReloadManager.d.ts.map +1 -0
  659. package/dist/mcp/hotReloadManager.js +251 -0
  660. package/dist/mcp/hotReloadManager.js.map +1 -0
  661. package/dist/mcp/index.d.ts +16 -0
  662. package/dist/mcp/index.d.ts.map +1 -0
  663. package/dist/mcp/index.js +22 -0
  664. package/dist/mcp/index.js.map +1 -0
  665. package/dist/mcp/mcpProtocolHandler.d.ts +64 -0
  666. package/dist/mcp/mcpProtocolHandler.d.ts.map +1 -0
  667. package/dist/mcp/mcpProtocolHandler.js +253 -0
  668. package/dist/mcp/mcpProtocolHandler.js.map +1 -0
  669. package/dist/mcp/miniCOTServerManager.d.ts +336 -0
  670. package/dist/mcp/miniCOTServerManager.d.ts.map +1 -0
  671. package/dist/mcp/miniCOTServerManager.js +1384 -0
  672. package/dist/mcp/miniCOTServerManager.js.map +1 -0
  673. package/dist/mcp/promptExecutor.d.ts +188 -0
  674. package/dist/mcp/promptExecutor.d.ts.map +1 -0
  675. package/dist/mcp/promptExecutor.js +469 -0
  676. package/dist/mcp/promptExecutor.js.map +1 -0
  677. package/dist/mcp/reloadBroadcast.d.ts +127 -0
  678. package/dist/mcp/reloadBroadcast.d.ts.map +1 -0
  679. package/dist/mcp/reloadBroadcast.js +275 -0
  680. package/dist/mcp/reloadBroadcast.js.map +1 -0
  681. package/dist/mcp/resilientTransport.d.ts +249 -0
  682. package/dist/mcp/resilientTransport.d.ts.map +1 -0
  683. package/dist/mcp/resilientTransport.js +931 -0
  684. package/dist/mcp/resilientTransport.js.map +1 -0
  685. package/dist/mcp/samplingHandler.d.ts +129 -0
  686. package/dist/mcp/samplingHandler.d.ts.map +1 -0
  687. package/dist/mcp/samplingHandler.js +276 -0
  688. package/dist/mcp/samplingHandler.js.map +1 -0
  689. package/dist/mcp/specMemServer.d.ts +305 -0
  690. package/dist/mcp/specMemServer.d.ts.map +1 -0
  691. package/dist/mcp/specMemServer.js +2048 -0
  692. package/dist/mcp/specMemServer.js.map +1 -0
  693. package/dist/mcp/toolRegistry.d.ts +122 -0
  694. package/dist/mcp/toolRegistry.d.ts.map +1 -0
  695. package/dist/mcp/toolRegistry.js +609 -0
  696. package/dist/mcp/toolRegistry.js.map +1 -0
  697. package/dist/mcp/tools/embeddingControl.d.ts +114 -0
  698. package/dist/mcp/tools/embeddingControl.d.ts.map +1 -0
  699. package/dist/mcp/tools/embeddingControl.js +222 -0
  700. package/dist/mcp/tools/embeddingControl.js.map +1 -0
  701. package/dist/mcp/tools/index.d.ts +10 -0
  702. package/dist/mcp/tools/index.d.ts.map +1 -0
  703. package/dist/mcp/tools/index.js +17 -0
  704. package/dist/mcp/tools/index.js.map +1 -0
  705. package/dist/mcp/tools/teamComms.d.ts +444 -0
  706. package/dist/mcp/tools/teamComms.d.ts.map +1 -0
  707. package/dist/mcp/tools/teamComms.js +1953 -0
  708. package/dist/mcp/tools/teamComms.js.map +1 -0
  709. package/dist/mcp/triggerSystem.d.ts +129 -0
  710. package/dist/mcp/triggerSystem.d.ts.map +1 -0
  711. package/dist/mcp/triggerSystem.js +363 -0
  712. package/dist/mcp/triggerSystem.js.map +1 -0
  713. package/dist/mcp/watcherIntegration.d.ts +77 -0
  714. package/dist/mcp/watcherIntegration.d.ts.map +1 -0
  715. package/dist/mcp/watcherIntegration.js +428 -0
  716. package/dist/mcp/watcherIntegration.js.map +1 -0
  717. package/dist/mcp/watcherToolWrappers.d.ts +89 -0
  718. package/dist/mcp/watcherToolWrappers.d.ts.map +1 -0
  719. package/dist/mcp/watcherToolWrappers.js +91 -0
  720. package/dist/mcp/watcherToolWrappers.js.map +1 -0
  721. package/dist/memorization/claudeCodeMigration.d.ts +34 -0
  722. package/dist/memorization/claudeCodeMigration.d.ts.map +1 -0
  723. package/dist/memorization/claudeCodeMigration.js +210 -0
  724. package/dist/memorization/claudeCodeMigration.js.map +1 -0
  725. package/dist/memorization/claudeCodeTracker.d.ts +147 -0
  726. package/dist/memorization/claudeCodeTracker.d.ts.map +1 -0
  727. package/dist/memorization/claudeCodeTracker.js +424 -0
  728. package/dist/memorization/claudeCodeTracker.js.map +1 -0
  729. package/dist/memorization/codeMemorizer.d.ts +158 -0
  730. package/dist/memorization/codeMemorizer.d.ts.map +1 -0
  731. package/dist/memorization/codeMemorizer.js +357 -0
  732. package/dist/memorization/codeMemorizer.js.map +1 -0
  733. package/dist/memorization/codeRecall.d.ts +156 -0
  734. package/dist/memorization/codeRecall.d.ts.map +1 -0
  735. package/dist/memorization/codeRecall.js +499 -0
  736. package/dist/memorization/codeRecall.js.map +1 -0
  737. package/dist/memorization/index.d.ts +55 -0
  738. package/dist/memorization/index.d.ts.map +1 -0
  739. package/dist/memorization/index.js +64 -0
  740. package/dist/memorization/index.js.map +1 -0
  741. package/dist/memorization/memorizationTools.d.ts +413 -0
  742. package/dist/memorization/memorizationTools.d.ts.map +1 -0
  743. package/dist/memorization/memorizationTools.js +513 -0
  744. package/dist/memorization/memorizationTools.js.map +1 -0
  745. package/dist/memorization/watcherIntegration.d.ts +100 -0
  746. package/dist/memorization/watcherIntegration.d.ts.map +1 -0
  747. package/dist/memorization/watcherIntegration.js +196 -0
  748. package/dist/memorization/watcherIntegration.js.map +1 -0
  749. package/dist/memory/humanLikeMemory.d.ts +206 -0
  750. package/dist/memory/humanLikeMemory.d.ts.map +1 -0
  751. package/dist/memory/humanLikeMemory.js +603 -0
  752. package/dist/memory/humanLikeMemory.js.map +1 -0
  753. package/dist/memory/index.d.ts +22 -0
  754. package/dist/memory/index.d.ts.map +1 -0
  755. package/dist/memory/index.js +24 -0
  756. package/dist/memory/index.js.map +1 -0
  757. package/dist/memory/memoryEvolutionMigration.d.ts +36 -0
  758. package/dist/memory/memoryEvolutionMigration.d.ts.map +1 -0
  759. package/dist/memory/memoryEvolutionMigration.js +371 -0
  760. package/dist/memory/memoryEvolutionMigration.js.map +1 -0
  761. package/dist/memory/quadrantSearch.d.ts +221 -0
  762. package/dist/memory/quadrantSearch.d.ts.map +1 -0
  763. package/dist/memory/quadrantSearch.js +897 -0
  764. package/dist/memory/quadrantSearch.js.map +1 -0
  765. package/dist/middleware/apiVersioning.d.ts +83 -0
  766. package/dist/middleware/apiVersioning.d.ts.map +1 -0
  767. package/dist/middleware/apiVersioning.js +152 -0
  768. package/dist/middleware/apiVersioning.js.map +1 -0
  769. package/dist/middleware/compression.d.ts +48 -0
  770. package/dist/middleware/compression.d.ts.map +1 -0
  771. package/dist/middleware/compression.js +240 -0
  772. package/dist/middleware/compression.js.map +1 -0
  773. package/dist/middleware/csrf.d.ts +118 -0
  774. package/dist/middleware/csrf.d.ts.map +1 -0
  775. package/dist/middleware/csrf.js +300 -0
  776. package/dist/middleware/csrf.js.map +1 -0
  777. package/dist/middleware/index.d.ts +13 -0
  778. package/dist/middleware/index.d.ts.map +1 -0
  779. package/dist/middleware/index.js +17 -0
  780. package/dist/middleware/index.js.map +1 -0
  781. package/dist/middleware/wsRateLimiter.d.ts +129 -0
  782. package/dist/middleware/wsRateLimiter.d.ts.map +1 -0
  783. package/dist/middleware/wsRateLimiter.js +279 -0
  784. package/dist/middleware/wsRateLimiter.js.map +1 -0
  785. package/dist/migrations/run.d.ts +2 -0
  786. package/dist/migrations/run.d.ts.map +1 -0
  787. package/dist/migrations/run.js +25 -0
  788. package/dist/migrations/run.js.map +1 -0
  789. package/dist/migrations/syncDimensions.d.ts +24 -0
  790. package/dist/migrations/syncDimensions.d.ts.map +1 -0
  791. package/dist/migrations/syncDimensions.js +140 -0
  792. package/dist/migrations/syncDimensions.js.map +1 -0
  793. package/dist/migrations/teamComms.d.ts +16 -0
  794. package/dist/migrations/teamComms.d.ts.map +1 -0
  795. package/dist/migrations/teamComms.js +210 -0
  796. package/dist/migrations/teamComms.js.map +1 -0
  797. package/dist/openapi/index.d.ts +10 -0
  798. package/dist/openapi/index.d.ts.map +1 -0
  799. package/dist/openapi/index.js +10 -0
  800. package/dist/openapi/index.js.map +1 -0
  801. package/dist/openapi/spec.d.ts +902 -0
  802. package/dist/openapi/spec.d.ts.map +1 -0
  803. package/dist/openapi/spec.js +733 -0
  804. package/dist/openapi/spec.js.map +1 -0
  805. package/dist/packages/dependencyHistory.d.ts +113 -0
  806. package/dist/packages/dependencyHistory.d.ts.map +1 -0
  807. package/dist/packages/dependencyHistory.js +360 -0
  808. package/dist/packages/dependencyHistory.js.map +1 -0
  809. package/dist/packages/index.d.ts +30 -0
  810. package/dist/packages/index.d.ts.map +1 -0
  811. package/dist/packages/index.js +65 -0
  812. package/dist/packages/index.js.map +1 -0
  813. package/dist/packages/packageTools.d.ts +255 -0
  814. package/dist/packages/packageTools.d.ts.map +1 -0
  815. package/dist/packages/packageTools.js +242 -0
  816. package/dist/packages/packageTools.js.map +1 -0
  817. package/dist/packages/packageTracker.d.ts +98 -0
  818. package/dist/packages/packageTracker.d.ts.map +1 -0
  819. package/dist/packages/packageTracker.js +268 -0
  820. package/dist/packages/packageTracker.js.map +1 -0
  821. package/dist/packages/packageWatcher.d.ts +62 -0
  822. package/dist/packages/packageWatcher.d.ts.map +1 -0
  823. package/dist/packages/packageWatcher.js +146 -0
  824. package/dist/packages/packageWatcher.js.map +1 -0
  825. package/dist/providers/MiniCOTProvider.d.ts +48 -0
  826. package/dist/providers/MiniCOTProvider.d.ts.map +1 -0
  827. package/dist/providers/MiniCOTProvider.js +98 -0
  828. package/dist/providers/MiniCOTProvider.js.map +1 -0
  829. package/dist/reminders/index.d.ts +5 -0
  830. package/dist/reminders/index.d.ts.map +1 -0
  831. package/dist/reminders/index.js +5 -0
  832. package/dist/reminders/index.js.map +1 -0
  833. package/dist/reminders/skillReminder.d.ts +131 -0
  834. package/dist/reminders/skillReminder.d.ts.map +1 -0
  835. package/dist/reminders/skillReminder.js +386 -0
  836. package/dist/reminders/skillReminder.js.map +1 -0
  837. package/dist/search.d.ts +35 -0
  838. package/dist/search.d.ts.map +1 -0
  839. package/dist/search.js +574 -0
  840. package/dist/search.js.map +1 -0
  841. package/dist/security/localhostOnly.d.ts +36 -0
  842. package/dist/security/localhostOnly.d.ts.map +1 -0
  843. package/dist/security/localhostOnly.js +101 -0
  844. package/dist/security/localhostOnly.js.map +1 -0
  845. package/dist/services/CameraZoomSearch.d.ts +206 -0
  846. package/dist/services/CameraZoomSearch.d.ts.map +1 -0
  847. package/dist/services/CameraZoomSearch.js +669 -0
  848. package/dist/services/CameraZoomSearch.js.map +1 -0
  849. package/dist/services/DataFlowPipeline.d.ts +111 -0
  850. package/dist/services/DataFlowPipeline.d.ts.map +1 -0
  851. package/dist/services/DataFlowPipeline.js +379 -0
  852. package/dist/services/DataFlowPipeline.js.map +1 -0
  853. package/dist/services/DimensionAdapter.d.ts +194 -0
  854. package/dist/services/DimensionAdapter.d.ts.map +1 -0
  855. package/dist/services/DimensionAdapter.js +566 -0
  856. package/dist/services/DimensionAdapter.js.map +1 -0
  857. package/dist/services/DimensionService.d.ts +252 -0
  858. package/dist/services/DimensionService.d.ts.map +1 -0
  859. package/dist/services/DimensionService.js +564 -0
  860. package/dist/services/DimensionService.js.map +1 -0
  861. package/dist/services/EmbeddingQueue.d.ts +71 -0
  862. package/dist/services/EmbeddingQueue.d.ts.map +1 -0
  863. package/dist/services/EmbeddingQueue.js +258 -0
  864. package/dist/services/EmbeddingQueue.js.map +1 -0
  865. package/dist/services/MemoryDrilldown.d.ts +226 -0
  866. package/dist/services/MemoryDrilldown.d.ts.map +1 -0
  867. package/dist/services/MemoryDrilldown.js +479 -0
  868. package/dist/services/MemoryDrilldown.js.map +1 -0
  869. package/dist/services/MiniCOTScorer.d.ts +140 -0
  870. package/dist/services/MiniCOTScorer.d.ts.map +1 -0
  871. package/dist/services/MiniCOTScorer.js +292 -0
  872. package/dist/services/MiniCOTScorer.js.map +1 -0
  873. package/dist/services/ProjectContext.d.ts +342 -0
  874. package/dist/services/ProjectContext.d.ts.map +1 -0
  875. package/dist/services/ProjectContext.js +667 -0
  876. package/dist/services/ProjectContext.js.map +1 -0
  877. package/dist/services/ResponseCompactor.d.ts +135 -0
  878. package/dist/services/ResponseCompactor.d.ts.map +1 -0
  879. package/dist/services/ResponseCompactor.js +501 -0
  880. package/dist/services/ResponseCompactor.js.map +1 -0
  881. package/dist/services/TeamCommsDbService.d.ts +202 -0
  882. package/dist/services/TeamCommsDbService.d.ts.map +1 -0
  883. package/dist/services/TeamCommsDbService.js +526 -0
  884. package/dist/services/TeamCommsDbService.js.map +1 -0
  885. package/dist/services/UnifiedPasswordService.d.ts +166 -0
  886. package/dist/services/UnifiedPasswordService.d.ts.map +1 -0
  887. package/dist/services/UnifiedPasswordService.js +587 -0
  888. package/dist/services/UnifiedPasswordService.js.map +1 -0
  889. package/dist/services/adaptiveSearchConfig.d.ts +64 -0
  890. package/dist/services/adaptiveSearchConfig.d.ts.map +1 -0
  891. package/dist/services/adaptiveSearchConfig.js +187 -0
  892. package/dist/services/adaptiveSearchConfig.js.map +1 -0
  893. package/dist/skills/index.d.ts +8 -0
  894. package/dist/skills/index.d.ts.map +1 -0
  895. package/dist/skills/index.js +8 -0
  896. package/dist/skills/index.js.map +1 -0
  897. package/dist/skills/skillScanner.d.ts +203 -0
  898. package/dist/skills/skillScanner.d.ts.map +1 -0
  899. package/dist/skills/skillScanner.js +559 -0
  900. package/dist/skills/skillScanner.js.map +1 -0
  901. package/dist/skills/skillsResource.d.ts +69 -0
  902. package/dist/skills/skillsResource.d.ts.map +1 -0
  903. package/dist/skills/skillsResource.js +257 -0
  904. package/dist/skills/skillsResource.js.map +1 -0
  905. package/dist/startup/index.d.ts +9 -0
  906. package/dist/startup/index.d.ts.map +1 -0
  907. package/dist/startup/index.js +12 -0
  908. package/dist/startup/index.js.map +1 -0
  909. package/dist/startup/startupIndexing.d.ts +80 -0
  910. package/dist/startup/startupIndexing.d.ts.map +1 -0
  911. package/dist/startup/startupIndexing.js +463 -0
  912. package/dist/startup/startupIndexing.js.map +1 -0
  913. package/dist/startup/validation.d.ts +89 -0
  914. package/dist/startup/validation.d.ts.map +1 -0
  915. package/dist/startup/validation.js +590 -0
  916. package/dist/startup/validation.js.map +1 -0
  917. package/dist/storage/index.d.ts +4 -0
  918. package/dist/storage/index.d.ts.map +1 -0
  919. package/dist/storage/index.js +4 -0
  920. package/dist/storage/index.js.map +1 -0
  921. package/dist/storage/overflowManager.d.ts +80 -0
  922. package/dist/storage/overflowManager.d.ts.map +1 -0
  923. package/dist/storage/overflowManager.js +317 -0
  924. package/dist/storage/overflowManager.js.map +1 -0
  925. package/dist/storage/overflowStorage.d.ts +69 -0
  926. package/dist/storage/overflowStorage.d.ts.map +1 -0
  927. package/dist/storage/overflowStorage.js +379 -0
  928. package/dist/storage/overflowStorage.js.map +1 -0
  929. package/dist/storage/toonFormat.d.ts +50 -0
  930. package/dist/storage/toonFormat.d.ts.map +1 -0
  931. package/dist/storage/toonFormat.js +224 -0
  932. package/dist/storage/toonFormat.js.map +1 -0
  933. package/dist/team-members/communication.d.ts +237 -0
  934. package/dist/team-members/communication.d.ts.map +1 -0
  935. package/dist/team-members/communication.js +650 -0
  936. package/dist/team-members/communication.js.map +1 -0
  937. package/dist/team-members/index.d.ts +14 -0
  938. package/dist/team-members/index.d.ts.map +1 -0
  939. package/dist/team-members/index.js +22 -0
  940. package/dist/team-members/index.js.map +1 -0
  941. package/dist/team-members/taskOrchestrator.d.ts +224 -0
  942. package/dist/team-members/taskOrchestrator.d.ts.map +1 -0
  943. package/dist/team-members/taskOrchestrator.js +574 -0
  944. package/dist/team-members/taskOrchestrator.js.map +1 -0
  945. package/dist/team-members/taskTeamMemberLogger.d.ts +157 -0
  946. package/dist/team-members/taskTeamMemberLogger.d.ts.map +1 -0
  947. package/dist/team-members/taskTeamMemberLogger.js +478 -0
  948. package/dist/team-members/taskTeamMemberLogger.js.map +1 -0
  949. package/dist/team-members/teamCommsService.d.ts +221 -0
  950. package/dist/team-members/teamCommsService.d.ts.map +1 -0
  951. package/dist/team-members/teamCommsService.js +628 -0
  952. package/dist/team-members/teamCommsService.js.map +1 -0
  953. package/dist/team-members/teamMemberChannels.d.ts +217 -0
  954. package/dist/team-members/teamMemberChannels.d.ts.map +1 -0
  955. package/dist/team-members/teamMemberChannels.js +687 -0
  956. package/dist/team-members/teamMemberChannels.js.map +1 -0
  957. package/dist/team-members/teamMemberDashboard.d.ts +222 -0
  958. package/dist/team-members/teamMemberDashboard.d.ts.map +1 -0
  959. package/dist/team-members/teamMemberDashboard.js +610 -0
  960. package/dist/team-members/teamMemberDashboard.js.map +1 -0
  961. package/dist/team-members/teamMemberDeployment.d.ts +60 -0
  962. package/dist/team-members/teamMemberDeployment.d.ts.map +1 -0
  963. package/dist/team-members/teamMemberDeployment.js +429 -0
  964. package/dist/team-members/teamMemberDeployment.js.map +1 -0
  965. package/dist/team-members/teamMemberDiscovery.d.ts +178 -0
  966. package/dist/team-members/teamMemberDiscovery.d.ts.map +1 -0
  967. package/dist/team-members/teamMemberDiscovery.js +446 -0
  968. package/dist/team-members/teamMemberDiscovery.js.map +1 -0
  969. package/dist/team-members/teamMemberHistory.d.ts +80 -0
  970. package/dist/team-members/teamMemberHistory.d.ts.map +1 -0
  971. package/dist/team-members/teamMemberHistory.js +426 -0
  972. package/dist/team-members/teamMemberHistory.js.map +1 -0
  973. package/dist/team-members/teamMemberLimits.d.ts +66 -0
  974. package/dist/team-members/teamMemberLimits.d.ts.map +1 -0
  975. package/dist/team-members/teamMemberLimits.js +259 -0
  976. package/dist/team-members/teamMemberLimits.js.map +1 -0
  977. package/dist/team-members/teamMemberRegistry.d.ts +199 -0
  978. package/dist/team-members/teamMemberRegistry.d.ts.map +1 -0
  979. package/dist/team-members/teamMemberRegistry.js +572 -0
  980. package/dist/team-members/teamMemberRegistry.js.map +1 -0
  981. package/dist/team-members/teamMemberTracker.d.ts +148 -0
  982. package/dist/team-members/teamMemberTracker.d.ts.map +1 -0
  983. package/dist/team-members/teamMemberTracker.js +828 -0
  984. package/dist/team-members/teamMemberTracker.js.map +1 -0
  985. package/dist/team-members/workers/aiWorker.d.ts +53 -0
  986. package/dist/team-members/workers/aiWorker.d.ts.map +1 -0
  987. package/dist/team-members/workers/aiWorker.js +322 -0
  988. package/dist/team-members/workers/aiWorker.js.map +1 -0
  989. package/dist/team-members/workers/baseWorker.d.ts +101 -0
  990. package/dist/team-members/workers/baseWorker.d.ts.map +1 -0
  991. package/dist/team-members/workers/baseWorker.js +179 -0
  992. package/dist/team-members/workers/baseWorker.js.map +1 -0
  993. package/dist/team-members/workers/codeReviewWorker.d.ts +3 -0
  994. package/dist/team-members/workers/codeReviewWorker.d.ts.map +1 -0
  995. package/dist/team-members/workers/codeReviewWorker.js +144 -0
  996. package/dist/team-members/workers/codeReviewWorker.js.map +1 -0
  997. package/dist/team-members/workers/index.d.ts +7 -0
  998. package/dist/team-members/workers/index.d.ts.map +1 -0
  999. package/dist/team-members/workers/index.js +7 -0
  1000. package/dist/team-members/workers/index.js.map +1 -0
  1001. package/dist/team-members/workers/repairWorker.d.ts +9 -0
  1002. package/dist/team-members/workers/repairWorker.d.ts.map +1 -0
  1003. package/dist/team-members/workers/repairWorker.js +102 -0
  1004. package/dist/team-members/workers/repairWorker.js.map +1 -0
  1005. package/dist/team-members/workers/sendToTeamMemberB.d.ts +9 -0
  1006. package/dist/team-members/workers/sendToTeamMemberB.d.ts.map +1 -0
  1007. package/dist/team-members/workers/sendToTeamMemberB.js +105 -0
  1008. package/dist/team-members/workers/sendToTeamMemberB.js.map +1 -0
  1009. package/dist/team-members/workers/specmemClient.d.ts +179 -0
  1010. package/dist/team-members/workers/specmemClient.d.ts.map +1 -0
  1011. package/dist/team-members/workers/specmemClient.js +421 -0
  1012. package/dist/team-members/workers/specmemClient.js.map +1 -0
  1013. package/dist/team-members/workers/testCommunication.d.ts +8 -0
  1014. package/dist/team-members/workers/testCommunication.d.ts.map +1 -0
  1015. package/dist/team-members/workers/testCommunication.js +136 -0
  1016. package/dist/team-members/workers/testCommunication.js.map +1 -0
  1017. package/dist/team-members/workers/testCommunicationSuite.d.ts +26 -0
  1018. package/dist/team-members/workers/testCommunicationSuite.d.ts.map +1 -0
  1019. package/dist/team-members/workers/testCommunicationSuite.js +415 -0
  1020. package/dist/team-members/workers/testCommunicationSuite.js.map +1 -0
  1021. package/dist/team-members/workers/testWorker.d.ts +9 -0
  1022. package/dist/team-members/workers/testWorker.d.ts.map +1 -0
  1023. package/dist/team-members/workers/testWorker.js +107 -0
  1024. package/dist/team-members/workers/testWorker.js.map +1 -0
  1025. package/dist/tools/agentDefinitions.d.ts +30 -0
  1026. package/dist/tools/agentDefinitions.d.ts.map +1 -0
  1027. package/dist/tools/agentDefinitions.js +166 -0
  1028. package/dist/tools/agentDefinitions.js.map +1 -0
  1029. package/dist/tools/goofy/checkSyncStatus.d.ts +68 -0
  1030. package/dist/tools/goofy/checkSyncStatus.d.ts.map +1 -0
  1031. package/dist/tools/goofy/checkSyncStatus.js +112 -0
  1032. package/dist/tools/goofy/checkSyncStatus.js.map +1 -0
  1033. package/dist/tools/goofy/codeMemoryLink.d.ts +82 -0
  1034. package/dist/tools/goofy/codeMemoryLink.d.ts.map +1 -0
  1035. package/dist/tools/goofy/codeMemoryLink.js +212 -0
  1036. package/dist/tools/goofy/codeMemoryLink.js.map +1 -0
  1037. package/dist/tools/goofy/compareInstanceMemory.d.ts +97 -0
  1038. package/dist/tools/goofy/compareInstanceMemory.d.ts.map +1 -0
  1039. package/dist/tools/goofy/compareInstanceMemory.js +218 -0
  1040. package/dist/tools/goofy/compareInstanceMemory.js.map +1 -0
  1041. package/dist/tools/goofy/createReasoningChain.d.ts +135 -0
  1042. package/dist/tools/goofy/createReasoningChain.d.ts.map +1 -0
  1043. package/dist/tools/goofy/createReasoningChain.js +257 -0
  1044. package/dist/tools/goofy/createReasoningChain.js.map +1 -0
  1045. package/dist/tools/goofy/deployTeamMember.d.ts +63 -0
  1046. package/dist/tools/goofy/deployTeamMember.d.ts.map +1 -0
  1047. package/dist/tools/goofy/deployTeamMember.js +103 -0
  1048. package/dist/tools/goofy/deployTeamMember.js.map +1 -0
  1049. package/dist/tools/goofy/drillDown.d.ts +143 -0
  1050. package/dist/tools/goofy/drillDown.d.ts.map +1 -0
  1051. package/dist/tools/goofy/drillDown.js +288 -0
  1052. package/dist/tools/goofy/drillDown.js.map +1 -0
  1053. package/dist/tools/goofy/extractClaudeSessions.d.ts +90 -0
  1054. package/dist/tools/goofy/extractClaudeSessions.d.ts.map +1 -0
  1055. package/dist/tools/goofy/extractClaudeSessions.js +277 -0
  1056. package/dist/tools/goofy/extractClaudeSessions.js.map +1 -0
  1057. package/dist/tools/goofy/extractContextRestorations.d.ts +70 -0
  1058. package/dist/tools/goofy/extractContextRestorations.d.ts.map +1 -0
  1059. package/dist/tools/goofy/extractContextRestorations.js +100 -0
  1060. package/dist/tools/goofy/extractContextRestorations.js.map +1 -0
  1061. package/dist/tools/goofy/findCodePointers.d.ts +364 -0
  1062. package/dist/tools/goofy/findCodePointers.d.ts.map +1 -0
  1063. package/dist/tools/goofy/findCodePointers.js +1764 -0
  1064. package/dist/tools/goofy/findCodePointers.js.map +1 -0
  1065. package/dist/tools/goofy/findMemoryGallery.d.ts +40 -0
  1066. package/dist/tools/goofy/findMemoryGallery.d.ts.map +1 -0
  1067. package/dist/tools/goofy/findMemoryGallery.js +66 -0
  1068. package/dist/tools/goofy/findMemoryGallery.js.map +1 -0
  1069. package/dist/tools/goofy/findWhatISaid.d.ts +300 -0
  1070. package/dist/tools/goofy/findWhatISaid.d.ts.map +1 -0
  1071. package/dist/tools/goofy/findWhatISaid.js +2547 -0
  1072. package/dist/tools/goofy/findWhatISaid.js.map +1 -0
  1073. package/dist/tools/goofy/forceResync.d.ts +57 -0
  1074. package/dist/tools/goofy/forceResync.d.ts.map +1 -0
  1075. package/dist/tools/goofy/forceResync.js +100 -0
  1076. package/dist/tools/goofy/forceResync.js.map +1 -0
  1077. package/dist/tools/goofy/getActiveTeamMembers.d.ts +48 -0
  1078. package/dist/tools/goofy/getActiveTeamMembers.d.ts.map +1 -0
  1079. package/dist/tools/goofy/getActiveTeamMembers.js +136 -0
  1080. package/dist/tools/goofy/getActiveTeamMembers.js.map +1 -0
  1081. package/dist/tools/goofy/getMemoryFull.d.ts +34 -0
  1082. package/dist/tools/goofy/getMemoryFull.d.ts.map +1 -0
  1083. package/dist/tools/goofy/getMemoryFull.js +58 -0
  1084. package/dist/tools/goofy/getMemoryFull.js.map +1 -0
  1085. package/dist/tools/goofy/getSessionWatcherStatus.d.ts +43 -0
  1086. package/dist/tools/goofy/getSessionWatcherStatus.d.ts.map +1 -0
  1087. package/dist/tools/goofy/getSessionWatcherStatus.js +92 -0
  1088. package/dist/tools/goofy/getSessionWatcherStatus.js.map +1 -0
  1089. package/dist/tools/goofy/getTeamMemberOutput.d.ts +35 -0
  1090. package/dist/tools/goofy/getTeamMemberOutput.d.ts.map +1 -0
  1091. package/dist/tools/goofy/getTeamMemberOutput.js +62 -0
  1092. package/dist/tools/goofy/getTeamMemberOutput.js.map +1 -0
  1093. package/dist/tools/goofy/getTeamMemberScreen.d.ts +28 -0
  1094. package/dist/tools/goofy/getTeamMemberScreen.d.ts.map +1 -0
  1095. package/dist/tools/goofy/getTeamMemberScreen.js +59 -0
  1096. package/dist/tools/goofy/getTeamMemberScreen.js.map +1 -0
  1097. package/dist/tools/goofy/getTeamMemberStatus.d.ts +33 -0
  1098. package/dist/tools/goofy/getTeamMemberStatus.d.ts.map +1 -0
  1099. package/dist/tools/goofy/getTeamMemberStatus.js +56 -0
  1100. package/dist/tools/goofy/getTeamMemberStatus.js.map +1 -0
  1101. package/dist/tools/goofy/index.d.ts +39 -0
  1102. package/dist/tools/goofy/index.d.ts.map +1 -0
  1103. package/dist/tools/goofy/index.js +51 -0
  1104. package/dist/tools/goofy/index.js.map +1 -0
  1105. package/dist/tools/goofy/interveneTeamMember.d.ts +33 -0
  1106. package/dist/tools/goofy/interveneTeamMember.d.ts.map +1 -0
  1107. package/dist/tools/goofy/interveneTeamMember.js +69 -0
  1108. package/dist/tools/goofy/interveneTeamMember.js.map +1 -0
  1109. package/dist/tools/goofy/killDeployedTeamMember.d.ts +29 -0
  1110. package/dist/tools/goofy/killDeployedTeamMember.d.ts.map +1 -0
  1111. package/dist/tools/goofy/killDeployedTeamMember.js +56 -0
  1112. package/dist/tools/goofy/killDeployedTeamMember.js.map +1 -0
  1113. package/dist/tools/goofy/linkTheVibes.d.ts +125 -0
  1114. package/dist/tools/goofy/linkTheVibes.d.ts.map +1 -0
  1115. package/dist/tools/goofy/linkTheVibes.js +354 -0
  1116. package/dist/tools/goofy/linkTheVibes.js.map +1 -0
  1117. package/dist/tools/goofy/listDeployedTeamMembers.d.ts +26 -0
  1118. package/dist/tools/goofy/listDeployedTeamMembers.d.ts.map +1 -0
  1119. package/dist/tools/goofy/listDeployedTeamMembers.js +52 -0
  1120. package/dist/tools/goofy/listDeployedTeamMembers.js.map +1 -0
  1121. package/dist/tools/goofy/listenForMessages.d.ts +56 -0
  1122. package/dist/tools/goofy/listenForMessages.d.ts.map +1 -0
  1123. package/dist/tools/goofy/listenForMessages.js +122 -0
  1124. package/dist/tools/goofy/listenForMessages.js.map +1 -0
  1125. package/dist/tools/goofy/memoryHealthCheck.d.ts +159 -0
  1126. package/dist/tools/goofy/memoryHealthCheck.d.ts.map +1 -0
  1127. package/dist/tools/goofy/memoryHealthCheck.js +443 -0
  1128. package/dist/tools/goofy/memoryHealthCheck.js.map +1 -0
  1129. package/dist/tools/goofy/rememberThisShit.d.ts +103 -0
  1130. package/dist/tools/goofy/rememberThisShit.d.ts.map +1 -0
  1131. package/dist/tools/goofy/rememberThisShit.js +291 -0
  1132. package/dist/tools/goofy/rememberThisShit.js.map +1 -0
  1133. package/dist/tools/goofy/sayToTeamMember.d.ts +55 -0
  1134. package/dist/tools/goofy/sayToTeamMember.d.ts.map +1 -0
  1135. package/dist/tools/goofy/sayToTeamMember.js +116 -0
  1136. package/dist/tools/goofy/sayToTeamMember.js.map +1 -0
  1137. package/dist/tools/goofy/selfMessage.d.ts +54 -0
  1138. package/dist/tools/goofy/selfMessage.d.ts.map +1 -0
  1139. package/dist/tools/goofy/selfMessage.js +111 -0
  1140. package/dist/tools/goofy/selfMessage.js.map +1 -0
  1141. package/dist/tools/goofy/sendHeartbeat.d.ts +53 -0
  1142. package/dist/tools/goofy/sendHeartbeat.d.ts.map +1 -0
  1143. package/dist/tools/goofy/sendHeartbeat.js +119 -0
  1144. package/dist/tools/goofy/sendHeartbeat.js.map +1 -0
  1145. package/dist/tools/goofy/showMeTheStats.d.ts +216 -0
  1146. package/dist/tools/goofy/showMeTheStats.d.ts.map +1 -0
  1147. package/dist/tools/goofy/showMeTheStats.js +535 -0
  1148. package/dist/tools/goofy/showMeTheStats.js.map +1 -0
  1149. package/dist/tools/goofy/smartRecall.d.ts +136 -0
  1150. package/dist/tools/goofy/smartRecall.d.ts.map +1 -0
  1151. package/dist/tools/goofy/smartRecall.js +286 -0
  1152. package/dist/tools/goofy/smartRecall.js.map +1 -0
  1153. package/dist/tools/goofy/smartSearch.d.ts +64 -0
  1154. package/dist/tools/goofy/smartSearch.d.ts.map +1 -0
  1155. package/dist/tools/goofy/smartSearch.js +89 -0
  1156. package/dist/tools/goofy/smartSearch.js.map +1 -0
  1157. package/dist/tools/goofy/smushMemoriesTogether.d.ts +128 -0
  1158. package/dist/tools/goofy/smushMemoriesTogether.d.ts.map +1 -0
  1159. package/dist/tools/goofy/smushMemoriesTogether.js +536 -0
  1160. package/dist/tools/goofy/smushMemoriesTogether.js.map +1 -0
  1161. package/dist/tools/goofy/spatialSearch.d.ts +198 -0
  1162. package/dist/tools/goofy/spatialSearch.d.ts.map +1 -0
  1163. package/dist/tools/goofy/spatialSearch.js +551 -0
  1164. package/dist/tools/goofy/spatialSearch.js.map +1 -0
  1165. package/dist/tools/goofy/spawnResearchTeamMember.d.ts +104 -0
  1166. package/dist/tools/goofy/spawnResearchTeamMember.d.ts.map +1 -0
  1167. package/dist/tools/goofy/spawnResearchTeamMember.js +290 -0
  1168. package/dist/tools/goofy/spawnResearchTeamMember.js.map +1 -0
  1169. package/dist/tools/goofy/spawnResearchTeamMemberTool.d.ts +121 -0
  1170. package/dist/tools/goofy/spawnResearchTeamMemberTool.d.ts.map +1 -0
  1171. package/dist/tools/goofy/spawnResearchTeamMemberTool.js +215 -0
  1172. package/dist/tools/goofy/spawnResearchTeamMemberTool.js.map +1 -0
  1173. package/dist/tools/goofy/startWatchingTheFiles.d.ts +81 -0
  1174. package/dist/tools/goofy/startWatchingTheFiles.d.ts.map +1 -0
  1175. package/dist/tools/goofy/startWatchingTheFiles.js +161 -0
  1176. package/dist/tools/goofy/startWatchingTheFiles.js.map +1 -0
  1177. package/dist/tools/goofy/stopWatchingTheFiles.d.ts +50 -0
  1178. package/dist/tools/goofy/stopWatchingTheFiles.d.ts.map +1 -0
  1179. package/dist/tools/goofy/stopWatchingTheFiles.js +81 -0
  1180. package/dist/tools/goofy/stopWatchingTheFiles.js.map +1 -0
  1181. package/dist/tools/goofy/whatDidIMean.d.ts +113 -0
  1182. package/dist/tools/goofy/whatDidIMean.d.ts.map +1 -0
  1183. package/dist/tools/goofy/whatDidIMean.js +401 -0
  1184. package/dist/tools/goofy/whatDidIMean.js.map +1 -0
  1185. package/dist/tools/goofy/yeahNahDeleteThat.d.ts +109 -0
  1186. package/dist/tools/goofy/yeahNahDeleteThat.d.ts.map +1 -0
  1187. package/dist/tools/goofy/yeahNahDeleteThat.js +319 -0
  1188. package/dist/tools/goofy/yeahNahDeleteThat.js.map +1 -0
  1189. package/dist/tools/index.d.ts +9 -0
  1190. package/dist/tools/index.d.ts.map +1 -0
  1191. package/dist/tools/index.js +9 -0
  1192. package/dist/tools/index.js.map +1 -0
  1193. package/dist/tools/teamMemberDeployer.d.ts +117 -0
  1194. package/dist/tools/teamMemberDeployer.d.ts.map +1 -0
  1195. package/dist/tools/teamMemberDeployer.js +613 -0
  1196. package/dist/tools/teamMemberDeployer.js.map +1 -0
  1197. package/dist/trace/index.d.ts +14 -0
  1198. package/dist/trace/index.d.ts.map +1 -0
  1199. package/dist/trace/index.js +16 -0
  1200. package/dist/trace/index.js.map +1 -0
  1201. package/dist/trace/tools/analyzeImpact.d.ts +90 -0
  1202. package/dist/trace/tools/analyzeImpact.d.ts.map +1 -0
  1203. package/dist/trace/tools/analyzeImpact.js +240 -0
  1204. package/dist/trace/tools/analyzeImpact.js.map +1 -0
  1205. package/dist/trace/tools/exploreDependencies.d.ts +81 -0
  1206. package/dist/trace/tools/exploreDependencies.d.ts.map +1 -0
  1207. package/dist/trace/tools/exploreDependencies.js +161 -0
  1208. package/dist/trace/tools/exploreDependencies.js.map +1 -0
  1209. package/dist/trace/tools/findSimilarBugs.d.ts +112 -0
  1210. package/dist/trace/tools/findSimilarBugs.d.ts.map +1 -0
  1211. package/dist/trace/tools/findSimilarBugs.js +216 -0
  1212. package/dist/trace/tools/findSimilarBugs.js.map +1 -0
  1213. package/dist/trace/tools/index.d.ts +22 -0
  1214. package/dist/trace/tools/index.d.ts.map +1 -0
  1215. package/dist/trace/tools/index.js +39 -0
  1216. package/dist/trace/tools/index.js.map +1 -0
  1217. package/dist/trace/tools/smartExplore.d.ts +126 -0
  1218. package/dist/trace/tools/smartExplore.d.ts.map +1 -0
  1219. package/dist/trace/tools/smartExplore.js +303 -0
  1220. package/dist/trace/tools/smartExplore.js.map +1 -0
  1221. package/dist/trace/tools/traceError.d.ts +101 -0
  1222. package/dist/trace/tools/traceError.d.ts.map +1 -0
  1223. package/dist/trace/tools/traceError.js +175 -0
  1224. package/dist/trace/tools/traceError.js.map +1 -0
  1225. package/dist/trace/traceExploreSystem.d.ts +271 -0
  1226. package/dist/trace/traceExploreSystem.d.ts.map +1 -0
  1227. package/dist/trace/traceExploreSystem.js +789 -0
  1228. package/dist/trace/traceExploreSystem.js.map +1 -0
  1229. package/dist/types/index.d.ts +421 -0
  1230. package/dist/types/index.d.ts.map +1 -0
  1231. package/dist/types/index.js +118 -0
  1232. package/dist/types/index.js.map +1 -0
  1233. package/dist/utils/circuitBreaker.d.ts +195 -0
  1234. package/dist/utils/circuitBreaker.d.ts.map +1 -0
  1235. package/dist/utils/circuitBreaker.js +374 -0
  1236. package/dist/utils/circuitBreaker.js.map +1 -0
  1237. package/dist/utils/cleanupHandler.d.ts +108 -0
  1238. package/dist/utils/cleanupHandler.d.ts.map +1 -0
  1239. package/dist/utils/cleanupHandler.js +203 -0
  1240. package/dist/utils/cleanupHandler.js.map +1 -0
  1241. package/dist/utils/compactXmlResponse.d.ts +60 -0
  1242. package/dist/utils/compactXmlResponse.d.ts.map +1 -0
  1243. package/dist/utils/compactXmlResponse.js +209 -0
  1244. package/dist/utils/compactXmlResponse.js.map +1 -0
  1245. package/dist/utils/cotBroadcast.d.ts +56 -0
  1246. package/dist/utils/cotBroadcast.d.ts.map +1 -0
  1247. package/dist/utils/cotBroadcast.js +157 -0
  1248. package/dist/utils/cotBroadcast.js.map +1 -0
  1249. package/dist/utils/debugLogger.d.ts +95 -0
  1250. package/dist/utils/debugLogger.d.ts.map +1 -0
  1251. package/dist/utils/debugLogger.js +610 -0
  1252. package/dist/utils/debugLogger.js.map +1 -0
  1253. package/dist/utils/fileProcessingQueue.d.ts +259 -0
  1254. package/dist/utils/fileProcessingQueue.d.ts.map +1 -0
  1255. package/dist/utils/fileProcessingQueue.js +714 -0
  1256. package/dist/utils/fileProcessingQueue.js.map +1 -0
  1257. package/dist/utils/humanReadableOutput.d.ts +124 -0
  1258. package/dist/utils/humanReadableOutput.d.ts.map +1 -0
  1259. package/dist/utils/humanReadableOutput.js +340 -0
  1260. package/dist/utils/humanReadableOutput.js.map +1 -0
  1261. package/dist/utils/index.d.ts +32 -0
  1262. package/dist/utils/index.d.ts.map +1 -0
  1263. package/dist/utils/index.js +71 -0
  1264. package/dist/utils/index.js.map +1 -0
  1265. package/dist/utils/instanceManager.d.ts +530 -0
  1266. package/dist/utils/instanceManager.d.ts.map +1 -0
  1267. package/dist/utils/instanceManager.js +1784 -0
  1268. package/dist/utils/instanceManager.js.map +1 -0
  1269. package/dist/utils/logger.d.ts +6 -0
  1270. package/dist/utils/logger.d.ts.map +1 -0
  1271. package/dist/utils/logger.js +49 -0
  1272. package/dist/utils/logger.js.map +1 -0
  1273. package/dist/utils/mapCleanup.d.ts +58 -0
  1274. package/dist/utils/mapCleanup.d.ts.map +1 -0
  1275. package/dist/utils/mapCleanup.js +150 -0
  1276. package/dist/utils/mapCleanup.js.map +1 -0
  1277. package/dist/utils/memoryManager.d.ts +349 -0
  1278. package/dist/utils/memoryManager.d.ts.map +1 -0
  1279. package/dist/utils/memoryManager.js +799 -0
  1280. package/dist/utils/memoryManager.js.map +1 -0
  1281. package/dist/utils/metrics.d.ts +160 -0
  1282. package/dist/utils/metrics.d.ts.map +1 -0
  1283. package/dist/utils/metrics.js +558 -0
  1284. package/dist/utils/metrics.js.map +1 -0
  1285. package/dist/utils/pathValidator.d.ts +96 -0
  1286. package/dist/utils/pathValidator.d.ts.map +1 -0
  1287. package/dist/utils/pathValidator.js +320 -0
  1288. package/dist/utils/pathValidator.js.map +1 -0
  1289. package/dist/utils/portAllocator.d.ts +296 -0
  1290. package/dist/utils/portAllocator.d.ts.map +1 -0
  1291. package/dist/utils/portAllocator.js +768 -0
  1292. package/dist/utils/portAllocator.js.map +1 -0
  1293. package/dist/utils/portUtils.d.ts +97 -0
  1294. package/dist/utils/portUtils.d.ts.map +1 -0
  1295. package/dist/utils/portUtils.js +285 -0
  1296. package/dist/utils/portUtils.js.map +1 -0
  1297. package/dist/utils/postgresAutoSetup.d.ts +55 -0
  1298. package/dist/utils/postgresAutoSetup.d.ts.map +1 -0
  1299. package/dist/utils/postgresAutoSetup.js +406 -0
  1300. package/dist/utils/postgresAutoSetup.js.map +1 -0
  1301. package/dist/utils/processHealthCheck.d.ts +61 -0
  1302. package/dist/utils/processHealthCheck.d.ts.map +1 -0
  1303. package/dist/utils/processHealthCheck.js +313 -0
  1304. package/dist/utils/processHealthCheck.js.map +1 -0
  1305. package/dist/utils/progressReporter.d.ts +151 -0
  1306. package/dist/utils/progressReporter.d.ts.map +1 -0
  1307. package/dist/utils/progressReporter.js +345 -0
  1308. package/dist/utils/progressReporter.js.map +1 -0
  1309. package/dist/utils/projectEnv.d.ts +73 -0
  1310. package/dist/utils/projectEnv.d.ts.map +1 -0
  1311. package/dist/utils/projectEnv.js +137 -0
  1312. package/dist/utils/projectEnv.js.map +1 -0
  1313. package/dist/utils/qoms.d.ts +122 -0
  1314. package/dist/utils/qoms.d.ts.map +1 -0
  1315. package/dist/utils/qoms.js +650 -0
  1316. package/dist/utils/qoms.js.map +1 -0
  1317. package/dist/utils/retryHelper.d.ts +122 -0
  1318. package/dist/utils/retryHelper.d.ts.map +1 -0
  1319. package/dist/utils/retryHelper.js +272 -0
  1320. package/dist/utils/retryHelper.js.map +1 -0
  1321. package/dist/utils/safeProcessTermination.d.ts +206 -0
  1322. package/dist/utils/safeProcessTermination.d.ts.map +1 -0
  1323. package/dist/utils/safeProcessTermination.js +552 -0
  1324. package/dist/utils/safeProcessTermination.js.map +1 -0
  1325. package/dist/utils/sessionInjector.d.ts +68 -0
  1326. package/dist/utils/sessionInjector.d.ts.map +1 -0
  1327. package/dist/utils/sessionInjector.js +189 -0
  1328. package/dist/utils/sessionInjector.js.map +1 -0
  1329. package/dist/utils/statsCache.d.ts +134 -0
  1330. package/dist/utils/statsCache.d.ts.map +1 -0
  1331. package/dist/utils/statsCache.js +285 -0
  1332. package/dist/utils/statsCache.js.map +1 -0
  1333. package/dist/utils/timeoutMiddleware.d.ts +81 -0
  1334. package/dist/utils/timeoutMiddleware.d.ts.map +1 -0
  1335. package/dist/utils/timeoutMiddleware.js +155 -0
  1336. package/dist/utils/timeoutMiddleware.js.map +1 -0
  1337. package/dist/utils/timerRegistry.d.ts +91 -0
  1338. package/dist/utils/timerRegistry.d.ts.map +1 -0
  1339. package/dist/utils/timerRegistry.js +187 -0
  1340. package/dist/utils/timerRegistry.js.map +1 -0
  1341. package/dist/utils/tokenCompressor.d.ts +332 -0
  1342. package/dist/utils/tokenCompressor.d.ts.map +1 -0
  1343. package/dist/utils/tokenCompressor.js +1306 -0
  1344. package/dist/utils/tokenCompressor.js.map +1 -0
  1345. package/dist/utils/tracing.d.ts +236 -0
  1346. package/dist/utils/tracing.d.ts.map +1 -0
  1347. package/dist/utils/tracing.js +378 -0
  1348. package/dist/utils/tracing.js.map +1 -0
  1349. package/dist/watcher/changeHandler.d.ts +123 -0
  1350. package/dist/watcher/changeHandler.d.ts.map +1 -0
  1351. package/dist/watcher/changeHandler.js +623 -0
  1352. package/dist/watcher/changeHandler.js.map +1 -0
  1353. package/dist/watcher/changeQueue.d.ts +133 -0
  1354. package/dist/watcher/changeQueue.d.ts.map +1 -0
  1355. package/dist/watcher/changeQueue.js +355 -0
  1356. package/dist/watcher/changeQueue.js.map +1 -0
  1357. package/dist/watcher/fileWatcher.d.ts +121 -0
  1358. package/dist/watcher/fileWatcher.d.ts.map +1 -0
  1359. package/dist/watcher/fileWatcher.js +531 -0
  1360. package/dist/watcher/fileWatcher.js.map +1 -0
  1361. package/dist/watcher/index.d.ts +94 -0
  1362. package/dist/watcher/index.d.ts.map +1 -0
  1363. package/dist/watcher/index.js +235 -0
  1364. package/dist/watcher/index.js.map +1 -0
  1365. package/dist/watcher/syncChecker.d.ts +93 -0
  1366. package/dist/watcher/syncChecker.d.ts.map +1 -0
  1367. package/dist/watcher/syncChecker.js +401 -0
  1368. package/dist/watcher/syncChecker.js.map +1 -0
  1369. package/dist/watcher/tsCompiler.d.ts +88 -0
  1370. package/dist/watcher/tsCompiler.d.ts.map +1 -0
  1371. package/dist/watcher/tsCompiler.js +212 -0
  1372. package/dist/watcher/tsCompiler.js.map +1 -0
  1373. package/embedding-sandbox/Dockerfile +77 -0
  1374. package/embedding-sandbox/Dockerfile.frankenstein +91 -0
  1375. package/embedding-sandbox/README.md +193 -0
  1376. package/embedding-sandbox/__pycache__/frankenstein-embeddings.cpython-312.pyc +0 -0
  1377. package/embedding-sandbox/__pycache__/frankenstein-embeddings.cpython-313.pyc +0 -0
  1378. package/embedding-sandbox/__pycache__/qqms_v2.cpython-312.pyc +0 -0
  1379. package/embedding-sandbox/__pycache__/qqms_v2.cpython-313.pyc +0 -0
  1380. package/embedding-sandbox/add_js_docs.py +684 -0
  1381. package/embedding-sandbox/build_docs_db.py +239 -0
  1382. package/embedding-sandbox/client.cjs +376 -0
  1383. package/embedding-sandbox/client.ts +913 -0
  1384. package/embedding-sandbox/deploy-frankenstein.sh +240 -0
  1385. package/embedding-sandbox/docker-compose.yml +60 -0
  1386. package/embedding-sandbox/docker-manager.py +325 -0
  1387. package/embedding-sandbox/docs/python_docs.db +0 -0
  1388. package/embedding-sandbox/download-model.mjs +79 -0
  1389. package/embedding-sandbox/download-model.py +28 -0
  1390. package/embedding-sandbox/embedding-supervisor.sh +164 -0
  1391. package/embedding-sandbox/frankenstein-embeddings.py +3940 -0
  1392. package/embedding-sandbox/manage-services.sh +354 -0
  1393. package/embedding-sandbox/overflow_queue.py +345 -0
  1394. package/embedding-sandbox/package.json +17 -0
  1395. package/embedding-sandbox/project_isolation.py +292 -0
  1396. package/embedding-sandbox/qqms_v2.py +967 -0
  1397. package/embedding-sandbox/ram-manager.sh +311 -0
  1398. package/embedding-sandbox/requirements-frankenstein.txt +7 -0
  1399. package/embedding-sandbox/run_js_docs.py +59 -0
  1400. package/embedding-sandbox/seed_docs.py +885 -0
  1401. package/embedding-sandbox/server-batch.mjs +228 -0
  1402. package/embedding-sandbox/server.mjs +389 -0
  1403. package/embedding-sandbox/specmem/sockets/claude-input-state.json +1 -0
  1404. package/embedding-sandbox/specmem/sockets/embedding-death-reason.txt +3 -0
  1405. package/embedding-sandbox/specmem/sockets/seen-sessions.json +1 -0
  1406. package/embedding-sandbox/specmem/sockets/session-start.lock +1 -0
  1407. package/embedding-sandbox/specmem/sockets/session-stops.log +7 -0
  1408. package/embedding-sandbox/start-frankenstein-throttled.sh +98 -0
  1409. package/embedding-sandbox/start-on-demand.sh +116 -0
  1410. package/embedding-sandbox/start-sandbox.sh +237 -0
  1411. package/embedding-sandbox/start-supervised.sh +11 -0
  1412. package/embedding-sandbox/stop-sandbox.sh +51 -0
  1413. package/embedding-sandbox/test-socket.mjs +61 -0
  1414. package/embedding-sandbox/warm-start.sh +353 -0
  1415. package/embedding-sandbox/warm_start_feeder.py +660 -0
  1416. package/legal/README.md +31 -0
  1417. package/legal/anthropic-privacy-center-screenshot-2026-01-30.png +0 -0
  1418. package/legal/anthropic-tos-screenshot-2026-01-30.png +0 -0
  1419. package/lib/codebase-bridge.cjs +308 -0
  1420. package/package.json +136 -0
  1421. package/plugins/specmem-agents/agents/bug-hunter.md +79 -0
  1422. package/plugins/specmem-agents/agents/memory-explorer.md +57 -0
  1423. package/plugins/specmem-agents/agents/team-coordinator.md +82 -0
  1424. package/scripts/auto-updater.cjs +399 -0
  1425. package/scripts/backfill-code-definition-embeddings.ts +440 -0
  1426. package/scripts/backfill-code-embeddings.ts +206 -0
  1427. package/scripts/capture-tos-screenshots.cjs +94 -0
  1428. package/scripts/check-global-install.cjs +67 -0
  1429. package/scripts/cleanup-embedding-servers.sh +25 -0
  1430. package/scripts/dashboard-standalone.sh +369 -0
  1431. package/scripts/deploy-hooks.cjs +1451 -0
  1432. package/scripts/deploy.sh +106 -0
  1433. package/scripts/docker-project-down.sh +83 -0
  1434. package/scripts/docker-project-list.sh +40 -0
  1435. package/scripts/docker-project-up.sh +79 -0
  1436. package/scripts/fast-backfill-embeddings.ts +173 -0
  1437. package/scripts/fast-batch-embedder.cjs +334 -0
  1438. package/scripts/first-run-model-setup.cjs +849 -0
  1439. package/scripts/global-postinstall.cjs +1957 -0
  1440. package/scripts/index-codebase.js +72 -0
  1441. package/scripts/migrate-fix-embeddings.py +110 -0
  1442. package/scripts/migrate-to-project-schemas.ts +525 -0
  1443. package/scripts/optimize-embedding-model.py +324 -0
  1444. package/scripts/optimize-instructions.cjs +530 -0
  1445. package/scripts/pack-docker-images.sh +68 -0
  1446. package/scripts/pack-for-testing.sh +130 -0
  1447. package/scripts/postinstall.cjs +54 -0
  1448. package/scripts/project-env.sh +51 -0
  1449. package/scripts/reset-db.sh +30 -0
  1450. package/scripts/run-indexer.ts +69 -0
  1451. package/scripts/run-migrations.js +47 -0
  1452. package/scripts/setup-db.sh +34 -0
  1453. package/scripts/setup-minimal-schema.sql +143 -0
  1454. package/scripts/skills/code-review.md +44 -0
  1455. package/scripts/skills/debugging.md +56 -0
  1456. package/scripts/skills/specmem-deployteam.md +239 -0
  1457. package/scripts/skills/teammemberskills/EFFICIENT_GREP.md +171 -0
  1458. package/scripts/skills/teammemberskills/task-planning.md +67 -0
  1459. package/scripts/specmem/sockets/session-start.lock +1 -0
  1460. package/scripts/specmem/sockets/session-stops.log +1 -0
  1461. package/scripts/specmem-health.sh +382 -0
  1462. package/scripts/specmem-init.cjs +6935 -0
  1463. package/scripts/strip-debug-logs.cjs +43 -0
  1464. package/scripts/test-mcp-standalone.sh +365 -0
  1465. package/scripts/test-optimized-models.py +166 -0
  1466. package/scripts/verify-embedding-fix.sh +148 -0
  1467. package/skills/code-review.md +44 -0
  1468. package/skills/debugging.md +56 -0
  1469. package/skills/specmem-deployteam.md +239 -0
  1470. package/skills/teammemberskills/EFFICIENT_GREP.md +171 -0
  1471. package/skills/teammemberskills/task-planning.md +67 -0
  1472. package/specmem-health.cjs +522 -0
  1473. package/specmem.env +216 -0
@@ -0,0 +1,4266 @@
1
+ // ayo this migration system hits DIFFERENT
2
+ // handles schema evolution for MILLIONS of rows no cap
3
+ // partitioning, indexes, all the enterprise drip
4
+ //
5
+ // =============================================================================
6
+ // EMBEDDING DIMENSION NOTE
7
+ // =============================================================================
8
+ // DEPRECATED: SPECMEM_EMBEDDING_DIMENSIONS is no longer used.
9
+ //
10
+ // Embedding dimensions are now AUTO-DETECTED from the database pgvector column.
11
+ // The database pg_attribute table is the single source of truth for dimensions.
12
+ // The Frankenstein embedding model outputs 384-dim embeddings natively.
13
+ //
14
+ // The system auto-migrates when dimension mismatch is detected at startup.
15
+ // See src/dashboard/standalone.ts for auto-migration logic.
16
+ //
17
+ // For new tables, use 384 as the default (Frankenstein native dimension).
18
+ // =============================================================================
19
+ import { logger } from '../utils/logger.js';
20
+ import { getProjectSchema } from './projectNamespacing.js';
21
+ /**
22
+ * BigBrainMigrations - handles schema evolution like a BOSS
23
+ *
24
+ * features that absolutely SLAP:
25
+ * - version tracking with checksums
26
+ * - up/down migrations
27
+ * - partitioning for massive tables
28
+ * - proper index management
29
+ * - pgvector setup for semantic search
30
+ * - transaction-safe migrations
31
+ */
32
+ export class BigBrainMigrations {
33
+ pool;
34
+ constructor(pool) {
35
+ this.pool = pool;
36
+ }
37
+ // runs all pending migrations in order
38
+ async runAllMigrations() {
39
+ logger.info('starting BigBrain migration run - LESGO');
40
+ const start = Date.now();
41
+ // SCHEMA ISOLATION: Set search_path BEFORE any CREATE TABLE
42
+ const schemaName = getProjectSchema();
43
+ await this.pool.queryWithSwag(`CREATE SCHEMA IF NOT EXISTS ${schemaName}`);
44
+ await this.pool.queryWithSwag(`SET search_path TO ${schemaName}, public`);
45
+ logger.info({ schemaName }, 'search_path set for migrations');
46
+ await this.ensureMigrationTable();
47
+ const applied = await this.getAppliedMigrations();
48
+ const pending = this.getMigrations().filter(m => !applied.some(a => a.version === m.version));
49
+ if (pending.length === 0) {
50
+ logger.info('no pending migrations - schema is up to date fr');
51
+ return;
52
+ }
53
+ logger.info({ pendingCount: pending.length }, 'found pending migrations');
54
+ let applied_count = 0;
55
+ let failed_count = 0;
56
+ for (const migration of pending.sort((a, b) => a.version - b.version)) {
57
+ try {
58
+ await this.runMigration(migration);
59
+ applied_count++;
60
+ } catch (migErr) {
61
+ failed_count++;
62
+ const errMsg = migErr instanceof Error ? migErr.message : String(migErr);
63
+ logger.warn({ version: migration.version, name: migration.name, error: errMsg }, 'migration failed - skipping to next');
64
+ }
65
+ }
66
+ const duration = Date.now() - start;
67
+ logger.info({ duration, migrationsApplied: applied_count, migrationsFailed: failed_count }, 'all migrations complete - WE DID IT');
68
+ }
69
+ // ensures the migration tracking table exists
70
+ async ensureMigrationTable() {
71
+ await this.pool.queryWithSwag(`
72
+ CREATE TABLE IF NOT EXISTS _specmem_migrations (
73
+ version INTEGER PRIMARY KEY,
74
+ name VARCHAR(255) NOT NULL,
75
+ executed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
76
+ duration_ms INTEGER NOT NULL,
77
+ checksum VARCHAR(64) NOT NULL
78
+ )
79
+ `);
80
+ logger.debug('migration table ready');
81
+ }
82
+ // gets all migrations that have already been applied
83
+ async getAppliedMigrations() {
84
+ const result = await this.pool.queryWithSwag('SELECT * FROM _specmem_migrations ORDER BY version');
85
+ return result.rows.map((row) => ({
86
+ version: row.version,
87
+ name: row.name,
88
+ executedAt: row.executed_at,
89
+ durationMs: row.duration_ms,
90
+ checksum: row.checksum
91
+ }));
92
+ }
93
+ // runs a single migration in a transaction
94
+ async runMigration(migration) {
95
+ logger.info({ version: migration.version, name: migration.name }, 'running migration');
96
+ const start = Date.now();
97
+ await this.pool.transactionGang(async (client) => {
98
+ // run the migration SQL
99
+ await client.query(migration.up);
100
+ // record the migration
101
+ const duration = Date.now() - start;
102
+ await client.query(`INSERT INTO _specmem_migrations (version, name, duration_ms, checksum)
103
+ VALUES ($1, $2, $3, $4)`, [migration.version, migration.name, duration, migration.checksum]);
104
+ });
105
+ const duration = Date.now() - start;
106
+ logger.info({ version: migration.version, duration }, 'migration complete - fire');
107
+ }
108
+ // rolls back the last migration
109
+ async rollbackLast() {
110
+ const applied = await this.getAppliedMigrations();
111
+ if (applied.length === 0) {
112
+ logger.warn('no migrations to rollback bro');
113
+ return;
114
+ }
115
+ const last = applied[applied.length - 1];
116
+ const migration = this.getMigrations().find(m => m.version === last.version);
117
+ if (!migration) {
118
+ throw new Error(`cant find migration ${last.version} to rollback - this is bad`);
119
+ }
120
+ logger.info({ version: migration.version, name: migration.name }, 'rolling back migration');
121
+ await this.pool.transactionGang(async (client) => {
122
+ await client.query(migration.down);
123
+ await client.query('DELETE FROM _specmem_migrations WHERE version = $1', [migration.version]);
124
+ });
125
+ logger.info({ version: migration.version }, 'rollback complete');
126
+ }
127
+ // generates a simple checksum for migration SQL
128
+ generateChecksum(sql) {
129
+ let hash = 0;
130
+ for (let i = 0; i < sql.length; i++) {
131
+ const char = sql.charCodeAt(i);
132
+ hash = ((hash << 5) - hash) + char;
133
+ hash = hash & hash;
134
+ }
135
+ return Math.abs(hash).toString(16).padStart(8, '0');
136
+ }
137
+ // returns all migrations in order
138
+ getMigrations() {
139
+ return [
140
+ // migration 1: install required extensions
141
+ {
142
+ version: 1,
143
+ name: 'install_extensions',
144
+ up: `
145
+ -- yo pgvector is the GOAT for semantic search
146
+ CREATE EXTENSION IF NOT EXISTS vector;
147
+
148
+ -- trigram for fuzzy text search
149
+ CREATE EXTENSION IF NOT EXISTS pg_trgm;
150
+
151
+ -- btree_gin for composite indexes
152
+ CREATE EXTENSION IF NOT EXISTS btree_gin;
153
+
154
+ -- uuid-ossp for generating uuids
155
+ CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
156
+ `,
157
+ down: `
158
+ -- nah we cant really uninstall extensions safely
159
+ -- other tables might depend on them
160
+ SELECT 1;
161
+ `,
162
+ checksum: this.generateChecksum('install_extensions_v1')
163
+ },
164
+ // migration 2: create core enum types
165
+ {
166
+ version: 2,
167
+ name: 'create_enum_types',
168
+ up: `
169
+ -- memory types - episodic, semantic, etc
170
+ DO $$ BEGIN
171
+ CREATE TYPE memory_type AS ENUM (
172
+ 'episodic', -- specific events/experiences
173
+ 'semantic', -- facts and knowledge
174
+ 'procedural', -- how to do stuff
175
+ 'working', -- temporary/short-term
176
+ 'consolidated' -- merged from multiple memories
177
+ );
178
+ EXCEPTION WHEN duplicate_object THEN NULL;
179
+ END $$;
180
+
181
+ -- importance levels for prioritization
182
+ DO $$ BEGIN
183
+ CREATE TYPE importance_level AS ENUM (
184
+ 'critical', -- NEVER forget this
185
+ 'high', -- pretty important
186
+ 'medium', -- normal stuff
187
+ 'low', -- meh
188
+ 'trivial' -- who cares
189
+ );
190
+ EXCEPTION WHEN duplicate_object THEN NULL;
191
+ END $$;
192
+ `,
193
+ down: `
194
+ DROP TYPE IF EXISTS importance_level;
195
+ DROP TYPE IF EXISTS memory_type;
196
+ `,
197
+ checksum: this.generateChecksum('create_enum_types_v2')
198
+ },
199
+ // migration 3: create main memories table with partitioning
200
+ {
201
+ version: 3,
202
+ name: 'create_memories_table',
203
+ up: `
204
+ -- main memories table - THE BIG ONE
205
+ -- partitioned by created_at for handling MILLIONS of rows
206
+ CREATE TABLE IF NOT EXISTS memories (
207
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
208
+
209
+ -- content and search
210
+ content TEXT NOT NULL,
211
+ -- MED-18 FIX: Use convert_to() for proper UTF-8 to bytea conversion
212
+ -- The ::bytea cast can fail with "invalid input syntax for type bytea"
213
+ -- on content containing special characters like backslashes or non-ASCII
214
+ -- See yeetStuffInDb.ts computeContentHash() for consistent approach
215
+ content_hash VARCHAR(64) GENERATED ALWAYS AS (
216
+ encode(sha256(convert_to(content, 'UTF8')), 'hex')
217
+ ) STORED,
218
+ content_tsv TSVECTOR GENERATED ALWAYS AS (
219
+ to_tsvector('english', content)
220
+ ) STORED,
221
+
222
+ -- classification
223
+ memory_type memory_type NOT NULL DEFAULT 'semantic',
224
+ importance importance_level NOT NULL DEFAULT 'medium',
225
+
226
+ -- tags stored as array - supports millions of tags
227
+ tags TEXT[] NOT NULL DEFAULT '{}',
228
+
229
+ -- flexible metadata as JSONB - way faster than TEXT
230
+ metadata JSONB NOT NULL DEFAULT '{}',
231
+
232
+ -- EMBEDDINGS - the secret sauce
233
+ -- Dimension is auto-detected from memories table, unbounded initially
234
+ embedding vector(384),
235
+
236
+ -- image support
237
+ image_data BYTEA,
238
+ image_mime_type VARCHAR(50),
239
+
240
+ -- timestamps
241
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
242
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
243
+
244
+ -- access tracking for consolidation
245
+ access_count INTEGER NOT NULL DEFAULT 0,
246
+ last_accessed_at TIMESTAMPTZ,
247
+
248
+ -- expiration for auto-cleanup
249
+ expires_at TIMESTAMPTZ,
250
+
251
+ -- consolidation tracking
252
+ consolidated_from UUID[] DEFAULT '{}',
253
+
254
+ -- constraints
255
+ CONSTRAINT content_not_empty CHECK (length(content) > 0),
256
+ CONSTRAINT content_not_too_big CHECK (length(content) <= 1000000),
257
+ CONSTRAINT valid_image CHECK (
258
+ (image_data IS NULL AND image_mime_type IS NULL) OR
259
+ (image_data IS NOT NULL AND image_mime_type IS NOT NULL)
260
+ )
261
+ );
262
+
263
+ -- index for content hash deduplication
264
+ CREATE INDEX IF NOT EXISTS idx_memories_content_hash
265
+ ON memories(content_hash);
266
+
267
+ -- full-text search index - GIN goes CRAZY
268
+ CREATE INDEX IF NOT EXISTS idx_memories_content_tsv
269
+ ON memories USING GIN(content_tsv);
270
+
271
+ -- tag search - also GIN because arrays
272
+ CREATE INDEX IF NOT EXISTS idx_memories_tags
273
+ ON memories USING GIN(tags);
274
+
275
+ -- JSONB metadata search
276
+ CREATE INDEX IF NOT EXISTS idx_memories_metadata
277
+ ON memories USING GIN(metadata jsonb_path_ops);
278
+
279
+ -- type and importance filtering
280
+ CREATE INDEX IF NOT EXISTS idx_memories_type
281
+ ON memories(memory_type);
282
+ CREATE INDEX IF NOT EXISTS idx_memories_importance
283
+ ON memories(importance);
284
+
285
+ -- time-based queries
286
+ CREATE INDEX IF NOT EXISTS idx_memories_created
287
+ ON memories(created_at DESC);
288
+ CREATE INDEX IF NOT EXISTS idx_memories_updated
289
+ ON memories(updated_at DESC);
290
+
291
+ -- expiration cleanup
292
+ CREATE INDEX IF NOT EXISTS idx_memories_expires
293
+ ON memories(expires_at)
294
+ WHERE expires_at IS NOT NULL;
295
+
296
+ -- access pattern tracking
297
+ CREATE INDEX IF NOT EXISTS idx_memories_access
298
+ ON memories(last_accessed_at DESC NULLS LAST);
299
+ `,
300
+ down: `
301
+ DROP TABLE IF EXISTS memories CASCADE;
302
+ `,
303
+ checksum: this.generateChecksum('create_memories_table_v3')
304
+ },
305
+ // migration 4: create HNSW index for vector search
306
+ {
307
+ version: 4,
308
+ name: 'create_vector_index',
309
+ up: `
310
+ -- HNSW index for vector similarity search
311
+ -- this is the FAST one - O(log n) search time
312
+ -- ef_construction and m affect build time vs search quality
313
+ CREATE INDEX IF NOT EXISTS idx_memories_embedding_hnsw
314
+ ON memories
315
+ USING hnsw (embedding vector_cosine_ops)
316
+ WITH (m = 16, ef_construction = 64);
317
+
318
+ -- also create IVFFlat for comparison (legacy compatibility)
319
+ -- IVFFlat is faster to build but slower to search
320
+ CREATE INDEX IF NOT EXISTS idx_memories_embedding_ivfflat
321
+ ON memories
322
+ USING ivfflat (embedding vector_cosine_ops)
323
+ WITH (lists = 100);
324
+ `,
325
+ down: `
326
+ DROP INDEX IF EXISTS idx_memories_embedding_hnsw;
327
+ DROP INDEX IF EXISTS idx_memories_embedding_ivfflat;
328
+ `,
329
+ checksum: this.generateChecksum('create_vector_index_v4')
330
+ },
331
+ // migration 5: create memory relations table
332
+ {
333
+ version: 5,
334
+ name: 'create_memory_relations',
335
+ up: `
336
+ -- tracks relationships between memories
337
+ CREATE TABLE IF NOT EXISTS memory_relations (
338
+ source_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
339
+ target_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
340
+ relation_type VARCHAR(50) NOT NULL DEFAULT 'related',
341
+ strength FLOAT NOT NULL DEFAULT 1.0 CHECK (strength >= 0 AND strength <= 1),
342
+ metadata JSONB DEFAULT '{}',
343
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
344
+
345
+ PRIMARY KEY (source_id, target_id, relation_type),
346
+ CONSTRAINT no_self_relation CHECK (source_id != target_id)
347
+ );
348
+
349
+ -- index for finding related memories
350
+ CREATE INDEX IF NOT EXISTS idx_memory_relations_source
351
+ ON memory_relations(source_id);
352
+ CREATE INDEX IF NOT EXISTS idx_memory_relations_target
353
+ ON memory_relations(target_id);
354
+ CREATE INDEX IF NOT EXISTS idx_memory_relations_type
355
+ ON memory_relations(relation_type);
356
+ `,
357
+ down: `
358
+ DROP TABLE IF EXISTS memory_relations CASCADE;
359
+ `,
360
+ checksum: this.generateChecksum('create_memory_relations_v5')
361
+ },
362
+ // migration 6: create normalized tags table
363
+ {
364
+ version: 6,
365
+ name: 'create_tags_table',
366
+ up: `
367
+ -- normalized tags for better query performance
368
+ -- this is in addition to the array column
369
+ CREATE TABLE IF NOT EXISTS tags (
370
+ id SERIAL PRIMARY KEY,
371
+ name VARCHAR(255) NOT NULL UNIQUE,
372
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
373
+ usage_count INTEGER NOT NULL DEFAULT 0
374
+ );
375
+
376
+ -- junction table for memory-tag relationships
377
+ CREATE TABLE IF NOT EXISTS memory_tags (
378
+ memory_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
379
+ tag_id INTEGER NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
380
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
381
+ PRIMARY KEY (memory_id, tag_id)
382
+ );
383
+
384
+ CREATE INDEX IF NOT EXISTS idx_tags_name ON tags(name);
385
+ CREATE INDEX IF NOT EXISTS idx_tags_usage ON tags(usage_count DESC);
386
+ CREATE INDEX IF NOT EXISTS idx_memory_tags_memory ON memory_tags(memory_id);
387
+ CREATE INDEX IF NOT EXISTS idx_memory_tags_tag ON memory_tags(tag_id);
388
+ `,
389
+ down: `
390
+ DROP TABLE IF EXISTS memory_tags CASCADE;
391
+ DROP TABLE IF EXISTS tags CASCADE;
392
+ `,
393
+ checksum: this.generateChecksum('create_tags_table_v6')
394
+ },
395
+ // migration 7: create consolidation history
396
+ {
397
+ version: 7,
398
+ name: 'create_consolidation_history',
399
+ up: `
400
+ -- tracks consolidation runs for debugging and optimization
401
+ CREATE TABLE IF NOT EXISTS consolidation_history (
402
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
403
+ strategy VARCHAR(50) NOT NULL,
404
+ started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
405
+ completed_at TIMESTAMPTZ,
406
+ memories_processed INTEGER DEFAULT 0,
407
+ memories_consolidated INTEGER DEFAULT 0,
408
+ clusters_found INTEGER DEFAULT 0,
409
+ duration_ms INTEGER,
410
+ error_message TEXT,
411
+ metadata JSONB DEFAULT '{}'
412
+ );
413
+
414
+ CREATE INDEX IF NOT EXISTS idx_consolidation_started
415
+ ON consolidation_history(started_at DESC);
416
+ `,
417
+ down: `
418
+ DROP TABLE IF EXISTS consolidation_history CASCADE;
419
+ `,
420
+ checksum: this.generateChecksum('create_consolidation_history_v7')
421
+ },
422
+ // migration 8: create updated_at trigger
423
+ {
424
+ version: 8,
425
+ name: 'create_updated_at_trigger',
426
+ up: `
427
+ -- auto-update updated_at on any row change
428
+ CREATE OR REPLACE FUNCTION update_updated_at_column()
429
+ RETURNS TRIGGER AS $$
430
+ BEGIN
431
+ NEW.updated_at = NOW();
432
+ RETURN NEW;
433
+ END;
434
+ $$ LANGUAGE plpgsql;
435
+
436
+ -- apply to memories table
437
+ DROP TRIGGER IF EXISTS memories_updated_at ON memories;
438
+ CREATE TRIGGER memories_updated_at
439
+ BEFORE UPDATE ON memories
440
+ FOR EACH ROW
441
+ EXECUTE FUNCTION update_updated_at_column();
442
+ `,
443
+ down: `
444
+ DROP TRIGGER IF EXISTS memories_updated_at ON memories;
445
+ DROP FUNCTION IF EXISTS update_updated_at_column();
446
+ `,
447
+ checksum: this.generateChecksum('create_updated_at_trigger_v8')
448
+ },
449
+ // migration 9: create partitioning for memories (for massive scale)
450
+ {
451
+ version: 9,
452
+ name: 'create_partitions_prep',
453
+ up: `
454
+ -- nah we're keeping the table as-is for now
455
+ -- partitioning requires recreating the table and that's risky
456
+ -- but we'll add a view for time-based access patterns
457
+
458
+ CREATE OR REPLACE VIEW memories_recent AS
459
+ SELECT * FROM memories
460
+ WHERE created_at > NOW() - INTERVAL '30 days'
461
+ AND (expires_at IS NULL OR expires_at > NOW());
462
+
463
+ CREATE OR REPLACE VIEW memories_active AS
464
+ SELECT * FROM memories
465
+ WHERE (expires_at IS NULL OR expires_at > NOW())
466
+ AND memory_type != 'consolidated';
467
+ `,
468
+ down: `
469
+ DROP VIEW IF EXISTS memories_active;
470
+ DROP VIEW IF EXISTS memories_recent;
471
+ `,
472
+ checksum: this.generateChecksum('create_partitions_prep_v9')
473
+ },
474
+ // migration 10: create embedding cache table
475
+ {
476
+ version: 10,
477
+ name: 'create_embedding_cache',
478
+ up: `
479
+ -- cache embeddings to avoid recomputing them
480
+ -- content_hash -> embedding mapping
481
+ -- NOTE: Dimension is auto-detected, unbounded initially
482
+ CREATE TABLE IF NOT EXISTS embedding_cache (
483
+ content_hash VARCHAR(64) PRIMARY KEY,
484
+ embedding vector(384) NOT NULL,
485
+ model VARCHAR(100) NOT NULL DEFAULT 'text-embedding-3-small',
486
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
487
+ last_used_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
488
+ hit_count INTEGER NOT NULL DEFAULT 0
489
+ );
490
+
491
+ CREATE INDEX IF NOT EXISTS idx_embedding_cache_model
492
+ ON embedding_cache(model);
493
+ CREATE INDEX IF NOT EXISTS idx_embedding_cache_used
494
+ ON embedding_cache(last_used_at);
495
+ `,
496
+ down: `
497
+ DROP TABLE IF EXISTS embedding_cache CASCADE;
498
+ `,
499
+ checksum: this.generateChecksum('create_embedding_cache_v10')
500
+ },
501
+ // migration 11: add composite indexes for common queries
502
+ {
503
+ version: 11,
504
+ name: 'create_composite_indexes',
505
+ up: `
506
+ -- composite indexes for common query patterns
507
+
508
+ -- search by type + importance
509
+ CREATE INDEX IF NOT EXISTS idx_memories_type_importance
510
+ ON memories(memory_type, importance);
511
+
512
+ -- search by type + created
513
+ CREATE INDEX IF NOT EXISTS idx_memories_type_created
514
+ ON memories(memory_type, created_at DESC);
515
+
516
+ -- non-expired memories ordered by access (no NOW() - not IMMUTABLE)
517
+ -- use expires_at IS NULL for permanent memories - expiring ones filtered at query time
518
+ CREATE INDEX IF NOT EXISTS idx_memories_active_access
519
+ ON memories(access_count DESC, last_accessed_at DESC)
520
+ WHERE expires_at IS NULL;
521
+
522
+ -- separate index for memories with expiration (for cleanup queries)
523
+ CREATE INDEX IF NOT EXISTS idx_memories_expiring
524
+ ON memories(expires_at)
525
+ WHERE expires_at IS NOT NULL;
526
+
527
+ -- content length for analytics (length() is IMMUTABLE)
528
+ CREATE INDEX IF NOT EXISTS idx_memories_content_length
529
+ ON memories(length(content));
530
+ `,
531
+ down: `
532
+ DROP INDEX IF EXISTS idx_memories_type_importance;
533
+ DROP INDEX IF EXISTS idx_memories_type_created;
534
+ DROP INDEX IF EXISTS idx_memories_active_access;
535
+ DROP INDEX IF EXISTS idx_memories_expiring;
536
+ DROP INDEX IF EXISTS idx_memories_content_length;
537
+ `,
538
+ checksum: this.generateChecksum('create_composite_indexes_v11_fixed')
539
+ },
540
+ // migration 12: create stats materialized view
541
+ {
542
+ version: 12,
543
+ name: 'create_stats_view',
544
+ up: `
545
+ -- materialized view for fast stats queries
546
+ CREATE MATERIALIZED VIEW IF NOT EXISTS memory_stats AS
547
+ SELECT
548
+ COUNT(*) as total_memories,
549
+ COUNT(*) FILTER (WHERE memory_type = 'episodic') as episodic_count,
550
+ COUNT(*) FILTER (WHERE memory_type = 'semantic') as semantic_count,
551
+ COUNT(*) FILTER (WHERE memory_type = 'procedural') as procedural_count,
552
+ COUNT(*) FILTER (WHERE memory_type = 'working') as working_count,
553
+ COUNT(*) FILTER (WHERE memory_type = 'consolidated') as consolidated_count,
554
+ COUNT(*) FILTER (WHERE importance = 'critical') as critical_count,
555
+ COUNT(*) FILTER (WHERE importance = 'high') as high_count,
556
+ COUNT(*) FILTER (WHERE image_data IS NOT NULL) as with_images,
557
+ COUNT(*) FILTER (WHERE embedding IS NOT NULL) as with_embeddings,
558
+ COUNT(*) FILTER (WHERE expires_at IS NOT NULL AND expires_at < NOW()) as expired_count,
559
+ AVG(access_count)::FLOAT as avg_access_count,
560
+ AVG(length(content))::FLOAT as avg_content_length,
561
+ MIN(created_at) as oldest_memory,
562
+ MAX(created_at) as newest_memory,
563
+ NOW() as computed_at
564
+ FROM memories;
565
+
566
+ -- index on the materialized view
567
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_memory_stats_singleton
568
+ ON memory_stats(computed_at);
569
+
570
+ -- function to refresh stats
571
+ CREATE OR REPLACE FUNCTION refresh_memory_stats()
572
+ RETURNS void AS $$
573
+ BEGIN
574
+ REFRESH MATERIALIZED VIEW CONCURRENTLY memory_stats;
575
+ END;
576
+ $$ LANGUAGE plpgsql;
577
+ `,
578
+ down: `
579
+ DROP FUNCTION IF EXISTS refresh_memory_stats();
580
+ DROP MATERIALIZED VIEW IF EXISTS memory_stats;
581
+ `,
582
+ checksum: this.generateChecksum('create_stats_view_v12')
583
+ },
584
+ // migration 13: create codebase_files table for ingestThisWholeAssMfCodebase
585
+ {
586
+ version: 13,
587
+ name: 'create_codebase_files_table',
588
+ up: `
589
+ -- yooo this table holds ENTIRE CODEBASES in memory
590
+ -- we about to store MILLIONS of lines of code fr fr
591
+ CREATE TABLE IF NOT EXISTS codebase_files (
592
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
593
+
594
+ -- file identification
595
+ file_path TEXT NOT NULL, -- relative path from root
596
+ absolute_path TEXT NOT NULL, -- full system path
597
+ file_name VARCHAR(255) NOT NULL, -- just the filename
598
+ extension VARCHAR(50), -- file extension
599
+
600
+ -- language detection
601
+ language_id VARCHAR(50) NOT NULL DEFAULT 'unknown',
602
+ language_name VARCHAR(100) NOT NULL DEFAULT 'Unknown',
603
+ language_type VARCHAR(50) NOT NULL DEFAULT 'data',
604
+
605
+ -- content storage
606
+ content TEXT NOT NULL,
607
+ content_hash VARCHAR(64), -- computed by application, not GENERATED (avoids bytea cast issues)
608
+ content_tsv TSVECTOR GENERATED ALWAYS AS (
609
+ to_tsvector('english', content)
610
+ ) STORED,
611
+
612
+ -- file stats
613
+ size_bytes INTEGER NOT NULL DEFAULT 0,
614
+ line_count INTEGER NOT NULL DEFAULT 0,
615
+ char_count INTEGER NOT NULL DEFAULT 0,
616
+ last_modified TIMESTAMPTZ NOT NULL DEFAULT NOW(),
617
+
618
+ -- chunking support for MASSIVE files
619
+ chunk_index INTEGER, -- null = not chunked, 0+ = chunk number
620
+ total_chunks INTEGER, -- total chunks if chunked
621
+ original_file_id UUID, -- parent file if this is a chunk
622
+
623
+ -- EMBEDDINGS for semantic code search
624
+ -- NOTE: Dimension is auto-detected, unbounded initially
625
+ embedding vector(384),
626
+
627
+ -- timestamps
628
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
629
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
630
+
631
+ -- constraints
632
+ CONSTRAINT content_not_empty CHECK (length(content) > 0),
633
+ CONSTRAINT valid_chunk CHECK (
634
+ (chunk_index IS NULL AND total_chunks IS NULL AND original_file_id IS NULL) OR
635
+ (chunk_index IS NOT NULL AND total_chunks IS NOT NULL AND original_file_id IS NOT NULL)
636
+ )
637
+ );
638
+
639
+ -- index for content hash deduplication
640
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_codebase_files_content_hash
641
+ ON codebase_files(content_hash);
642
+
643
+ -- full-text search index for code search
644
+ CREATE INDEX IF NOT EXISTS idx_codebase_files_content_tsv
645
+ ON codebase_files USING GIN(content_tsv);
646
+
647
+ -- file path searches
648
+ CREATE INDEX IF NOT EXISTS idx_codebase_files_path
649
+ ON codebase_files(file_path);
650
+ CREATE INDEX IF NOT EXISTS idx_codebase_files_path_trgm
651
+ ON codebase_files USING GIN(file_path gin_trgm_ops);
652
+
653
+ -- language filtering
654
+ CREATE INDEX IF NOT EXISTS idx_codebase_files_language
655
+ ON codebase_files(language_id);
656
+
657
+ -- chunk lookups
658
+ CREATE INDEX IF NOT EXISTS idx_codebase_files_original
659
+ ON codebase_files(original_file_id)
660
+ WHERE original_file_id IS NOT NULL;
661
+
662
+ -- time-based queries
663
+ CREATE INDEX IF NOT EXISTS idx_codebase_files_modified
664
+ ON codebase_files(last_modified DESC);
665
+
666
+ -- HNSW index for FAST semantic code search
667
+ CREATE INDEX IF NOT EXISTS idx_codebase_files_embedding_hnsw
668
+ ON codebase_files
669
+ USING hnsw (embedding vector_cosine_ops)
670
+ WITH (m = 16, ef_construction = 64);
671
+
672
+ -- trigger for updated_at
673
+ DROP TRIGGER IF EXISTS codebase_files_updated_at ON codebase_files;
674
+ CREATE TRIGGER codebase_files_updated_at
675
+ BEFORE UPDATE ON codebase_files
676
+ FOR EACH ROW
677
+ EXECUTE FUNCTION update_updated_at_column();
678
+ `,
679
+ down: `
680
+ DROP TRIGGER IF EXISTS codebase_files_updated_at ON codebase_files;
681
+ DROP TABLE IF EXISTS codebase_files CASCADE;
682
+ `,
683
+ checksum: this.generateChecksum('create_codebase_files_table_v13')
684
+ },
685
+ // migration 14: create codebase stats materialized view
686
+ {
687
+ version: 14,
688
+ name: 'create_codebase_stats_view',
689
+ up: `
690
+ -- materialized view for codebase stats - codebaseStatsGoCrazy
691
+ CREATE MATERIALIZED VIEW IF NOT EXISTS codebase_stats AS
692
+ SELECT
693
+ COUNT(*) as total_files,
694
+ COUNT(*) FILTER (WHERE chunk_index IS NOT NULL) as total_chunks,
695
+ COUNT(*) FILTER (WHERE chunk_index IS NULL) as unique_files,
696
+ SUM(line_count) as total_lines,
697
+ SUM(size_bytes) as total_bytes,
698
+ COUNT(DISTINCT language_id) as language_count,
699
+ COUNT(*) FILTER (WHERE embedding IS NOT NULL) as files_with_embeddings,
700
+ MIN(last_modified) as oldest_file,
701
+ MAX(last_modified) as newest_file,
702
+ NOW() as computed_at
703
+ FROM codebase_files;
704
+
705
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_codebase_stats_singleton
706
+ ON codebase_stats(computed_at);
707
+
708
+ -- function to refresh codebase stats
709
+ CREATE OR REPLACE FUNCTION refresh_codebase_stats()
710
+ RETURNS void AS $$
711
+ BEGIN
712
+ REFRESH MATERIALIZED VIEW CONCURRENTLY codebase_stats;
713
+ END;
714
+ $$ LANGUAGE plpgsql;
715
+ `,
716
+ down: `
717
+ DROP FUNCTION IF EXISTS refresh_codebase_stats();
718
+ DROP MATERIALIZED VIEW IF EXISTS codebase_stats;
719
+ `,
720
+ checksum: this.generateChecksum('create_codebase_stats_view_v14')
721
+ },
722
+ // migration 15: create dependency_history table
723
+ {
724
+ version: 15,
725
+ name: 'create_dependency_history_table',
726
+ up: `
727
+ -- yooo tracking package.json changes without indexing node_modules
728
+ -- this is the BIG BRAIN move fr fr
729
+ CREATE TABLE IF NOT EXISTS dependency_history (
730
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
731
+
732
+ -- package identification
733
+ package_name VARCHAR(255) NOT NULL,
734
+ version VARCHAR(100),
735
+
736
+ -- event tracking
737
+ event_type VARCHAR(20) NOT NULL CHECK (event_type IN ('added', 'updated', 'removed')),
738
+ package_type VARCHAR(20) NOT NULL CHECK (package_type IN (
739
+ 'dependency',
740
+ 'devDependency',
741
+ 'peerDependency',
742
+ 'optionalDependency'
743
+ )),
744
+
745
+ -- timestamp
746
+ timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),
747
+
748
+ -- source context
749
+ package_json_path TEXT NOT NULL,
750
+ project_name VARCHAR(255),
751
+
752
+ -- metadata for storing old/new versions during updates
753
+ metadata JSONB,
754
+
755
+ -- timestamps
756
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
757
+ );
758
+
759
+ -- index for package name lookups - whenDidWeAddThisPackage
760
+ CREATE INDEX IF NOT EXISTS idx_dependency_history_package_name
761
+ ON dependency_history(package_name);
762
+
763
+ -- index for event type filtering
764
+ CREATE INDEX IF NOT EXISTS idx_dependency_history_event_type
765
+ ON dependency_history(event_type);
766
+
767
+ -- index for package type filtering
768
+ CREATE INDEX IF NOT EXISTS idx_dependency_history_package_type
769
+ ON dependency_history(package_type);
770
+
771
+ -- index for timestamp-based queries - recent changes
772
+ CREATE INDEX IF NOT EXISTS idx_dependency_history_timestamp
773
+ ON dependency_history(timestamp DESC);
774
+
775
+ -- index for project lookups
776
+ CREATE INDEX IF NOT EXISTS idx_dependency_history_project
777
+ ON dependency_history(project_name)
778
+ WHERE project_name IS NOT NULL;
779
+
780
+ -- composite index for package + path lookups
781
+ CREATE INDEX IF NOT EXISTS idx_dependency_history_package_path
782
+ ON dependency_history(package_name, package_json_path);
783
+
784
+ -- composite index for common queries
785
+ CREATE INDEX IF NOT EXISTS idx_dependency_history_event_timestamp
786
+ ON dependency_history(event_type, timestamp DESC);
787
+
788
+ -- GIN index for JSONB metadata queries
789
+ CREATE INDEX IF NOT EXISTS idx_dependency_history_metadata
790
+ ON dependency_history USING GIN(metadata);
791
+ `,
792
+ down: `
793
+ DROP TABLE IF EXISTS dependency_history CASCADE;
794
+ `,
795
+ checksum: this.generateChecksum('create_dependency_history_table_v15')
796
+ },
797
+ // migration 16: create claude_code_history table
798
+ // yooo about to remember EVERYTHING it writes
799
+ // no more massive explores needed fr
800
+ {
801
+ version: 16,
802
+ name: 'create_claude_code_history',
803
+ up: `
804
+ -- yooo about to remember EVERYTHING it writes
805
+ -- no more massive explores needed fr
806
+
807
+ -- main table for tracking 's code
808
+ CREATE TABLE IF NOT EXISTS claude_code_history (
809
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
810
+
811
+ -- what did write?
812
+ file_path TEXT NOT NULL,
813
+ file_name VARCHAR(255) NOT NULL,
814
+ code_content TEXT NOT NULL,
815
+ code_hash VARCHAR(64) GENERATED ALWAYS AS (
816
+ encode(sha256(code_content::bytea), 'hex')
817
+ ) STORED,
818
+
819
+ -- why did write it?
820
+ purpose TEXT NOT NULL,
821
+ conversation_context TEXT,
822
+
823
+ -- classification
824
+ operation_type VARCHAR(50) NOT NULL DEFAULT 'write',
825
+ language VARCHAR(50) NOT NULL DEFAULT 'unknown',
826
+
827
+ -- relationships
828
+ related_files TEXT[] NOT NULL DEFAULT '{}',
829
+ related_memory_ids UUID[] DEFAULT '{}',
830
+ parent_code_id UUID REFERENCES claude_code_history(id),
831
+
832
+ -- tagging for searchability
833
+ tags TEXT[] NOT NULL DEFAULT '{}',
834
+ metadata JSONB NOT NULL DEFAULT '{}',
835
+
836
+ -- EMBEDDINGS for semantic search
837
+ -- NOTE: Dimension is auto-detected, unbounded initially
838
+ embedding vector(384),
839
+
840
+ -- full text search
841
+ content_tsv TSVECTOR GENERATED ALWAYS AS (
842
+ to_tsvector('english', code_content || ' ' || purpose)
843
+ ) STORED,
844
+
845
+ -- timestamps
846
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
847
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
848
+
849
+ -- version tracking for same file
850
+ version INTEGER NOT NULL DEFAULT 1,
851
+
852
+ -- constraints
853
+ CONSTRAINT code_not_empty CHECK (length(code_content) > 0),
854
+ CONSTRAINT purpose_not_empty CHECK (length(purpose) > 0),
855
+ CONSTRAINT valid_operation CHECK (
856
+ operation_type IN ('write', 'edit', 'notebook_edit', 'create', 'update', 'delete')
857
+ )
858
+ );
859
+
860
+ -- indexes for FAST lookups
861
+
862
+ -- file path searches
863
+ CREATE INDEX IF NOT EXISTS idx_claude_code_file_path
864
+ ON claude_code_history(file_path);
865
+ CREATE INDEX IF NOT EXISTS idx_claude_code_file_path_trgm
866
+ ON claude_code_history USING GIN(file_path gin_trgm_ops);
867
+
868
+ -- content hash for deduplication
869
+ CREATE INDEX IF NOT EXISTS idx_claude_code_hash
870
+ ON claude_code_history(code_hash);
871
+
872
+ -- full-text search on code + purpose
873
+ CREATE INDEX IF NOT EXISTS idx_claude_code_tsv
874
+ ON claude_code_history USING GIN(content_tsv);
875
+
876
+ -- tag searches
877
+ CREATE INDEX IF NOT EXISTS idx_claude_code_tags
878
+ ON claude_code_history USING GIN(tags);
879
+
880
+ -- metadata JSONB searches
881
+ CREATE INDEX IF NOT EXISTS idx_claude_code_metadata
882
+ ON claude_code_history USING GIN(metadata jsonb_path_ops);
883
+
884
+ -- language filtering
885
+ CREATE INDEX IF NOT EXISTS idx_claude_code_language
886
+ ON claude_code_history(language);
887
+
888
+ -- operation type filtering
889
+ CREATE INDEX IF NOT EXISTS idx_claude_code_operation
890
+ ON claude_code_history(operation_type);
891
+
892
+ -- time-based queries
893
+ CREATE INDEX IF NOT EXISTS idx_claude_code_created
894
+ ON claude_code_history(created_at DESC);
895
+
896
+ -- version tracking for same file
897
+ CREATE INDEX IF NOT EXISTS idx_claude_code_file_version
898
+ ON claude_code_history(file_path, version DESC);
899
+
900
+ -- HNSW vector index for semantic code search
901
+ CREATE INDEX IF NOT EXISTS idx_claude_code_embedding_hnsw
902
+ ON claude_code_history
903
+ USING hnsw (embedding vector_cosine_ops)
904
+ WITH (m = 16, ef_construction = 64);
905
+
906
+ -- related files search
907
+ CREATE INDEX IF NOT EXISTS idx_claude_code_related
908
+ ON claude_code_history USING GIN(related_files);
909
+
910
+ -- parent-child relationship
911
+ CREATE INDEX IF NOT EXISTS idx_claude_code_parent
912
+ ON claude_code_history(parent_code_id)
913
+ WHERE parent_code_id IS NOT NULL;
914
+
915
+ -- trigger for updated_at
916
+ DROP TRIGGER IF EXISTS claude_code_history_updated_at ON claude_code_history;
917
+ CREATE TRIGGER claude_code_history_updated_at
918
+ BEFORE UPDATE ON claude_code_history
919
+ FOR EACH ROW
920
+ EXECUTE FUNCTION update_updated_at_column();
921
+
922
+ -- materialized view for code stats
923
+ CREATE MATERIALIZED VIEW IF NOT EXISTS claude_code_stats AS
924
+ SELECT
925
+ COUNT(*) as total_code_entries,
926
+ COUNT(DISTINCT file_path) as unique_files,
927
+ COUNT(*) FILTER (WHERE operation_type = 'write') as writes,
928
+ COUNT(*) FILTER (WHERE operation_type = 'edit') as edits,
929
+ COUNT(*) FILTER (WHERE operation_type = 'create') as creates,
930
+ COUNT(*) FILTER (WHERE embedding IS NOT NULL) as with_embeddings,
931
+ SUM(length(code_content)) as total_characters,
932
+ AVG(length(code_content))::INTEGER as avg_code_length,
933
+ MIN(created_at) as oldest_code,
934
+ MAX(created_at) as newest_code,
935
+ NOW() as computed_at
936
+ FROM claude_code_history;
937
+
938
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_claude_code_stats_singleton
939
+ ON claude_code_stats(computed_at);
940
+
941
+ -- function to refresh claude code stats
942
+ CREATE OR REPLACE FUNCTION refresh_claude_code_stats()
943
+ RETURNS void AS $$
944
+ BEGIN
945
+ REFRESH MATERIALIZED VIEW CONCURRENTLY claude_code_stats;
946
+ END;
947
+ $$ LANGUAGE plpgsql;
948
+ `,
949
+ down: `
950
+ DROP FUNCTION IF EXISTS refresh_claude_code_stats();
951
+ DROP MATERIALIZED VIEW IF EXISTS claude_code_stats;
952
+ DROP TRIGGER IF EXISTS claude_code_history_updated_at ON claude_code_history;
953
+ DROP TABLE IF EXISTS claude_code_history CASCADE;
954
+ `,
955
+ checksum: this.generateChecksum('create_claude_code_history_v16')
956
+ },
957
+ // migration 17: create code_chunks table for semantic search
958
+ // yooo this is where the MAGIC happens
959
+ // chunks of code with embeddings for findSimilarCode
960
+ {
961
+ version: 17,
962
+ name: 'create_code_chunks_table',
963
+ up: `
964
+ -- code_chunks - SEMANTIC CODE SEARCH goes CRAZY here
965
+ -- stores code chunks with embeddings for similarity search
966
+ -- this is how we find similar code across the ENTIRE codebase
967
+ CREATE TABLE IF NOT EXISTS code_chunks (
968
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
969
+
970
+ -- reference to parent file
971
+ file_id UUID NOT NULL REFERENCES codebase_files(id) ON DELETE CASCADE,
972
+ file_path TEXT NOT NULL,
973
+
974
+ -- chunk positioning
975
+ chunk_index INTEGER NOT NULL DEFAULT 0,
976
+ start_line INTEGER NOT NULL,
977
+ end_line INTEGER NOT NULL,
978
+ start_char INTEGER NOT NULL DEFAULT 0,
979
+ end_char INTEGER NOT NULL DEFAULT 0,
980
+
981
+ -- chunk content and metadata
982
+ content TEXT NOT NULL,
983
+ content_hash VARCHAR(64) GENERATED ALWAYS AS (
984
+ encode(sha256(content::bytea), 'hex')
985
+ ) STORED,
986
+
987
+ -- language and context
988
+ language VARCHAR(50) NOT NULL DEFAULT 'unknown',
989
+ chunk_type VARCHAR(50) NOT NULL DEFAULT 'code', -- code, comment, docstring, mixed
990
+
991
+ -- semantic context
992
+ context_before TEXT, -- few lines before for context
993
+ context_after TEXT, -- few lines after for context
994
+
995
+ -- EMBEDDINGS - the secret sauce for semantic search
996
+ -- NOTE: Dimension is auto-detected, unbounded initially
997
+ embedding vector(384),
998
+
999
+ -- full text search
1000
+ content_tsv TSVECTOR GENERATED ALWAYS AS (
1001
+ to_tsvector('english', content)
1002
+ ) STORED,
1003
+
1004
+ -- metadata
1005
+ metadata JSONB NOT NULL DEFAULT '{}',
1006
+
1007
+ -- timestamps
1008
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1009
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1010
+
1011
+ -- constraints
1012
+ CONSTRAINT chunk_not_empty CHECK (length(content) > 0),
1013
+ CONSTRAINT valid_lines CHECK (end_line >= start_line),
1014
+ CONSTRAINT valid_chunk_type CHECK (
1015
+ chunk_type IN ('code', 'comment', 'docstring', 'mixed', 'import', 'definition')
1016
+ )
1017
+ );
1018
+
1019
+ -- indexes for BLAZING FAST lookups
1020
+
1021
+ -- file lookups
1022
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_file_id
1023
+ ON code_chunks(file_id);
1024
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_file_path
1025
+ ON code_chunks(file_path);
1026
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_file_path_trgm
1027
+ ON code_chunks USING GIN(file_path gin_trgm_ops);
1028
+
1029
+ -- chunk ordering within file
1030
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_file_order
1031
+ ON code_chunks(file_id, chunk_index);
1032
+
1033
+ -- line range queries
1034
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_lines
1035
+ ON code_chunks(file_id, start_line, end_line);
1036
+
1037
+ -- content hash for deduplication
1038
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_hash
1039
+ ON code_chunks(content_hash);
1040
+
1041
+ -- language filtering
1042
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_language
1043
+ ON code_chunks(language);
1044
+
1045
+ -- chunk type filtering
1046
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_type
1047
+ ON code_chunks(chunk_type);
1048
+
1049
+ -- full-text search
1050
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_tsv
1051
+ ON code_chunks USING GIN(content_tsv);
1052
+
1053
+ -- HNSW vector index for FAST semantic search
1054
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_embedding_hnsw
1055
+ ON code_chunks
1056
+ USING hnsw (embedding vector_cosine_ops)
1057
+ WITH (m = 16, ef_construction = 64);
1058
+
1059
+ -- metadata queries
1060
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_metadata
1061
+ ON code_chunks USING GIN(metadata jsonb_path_ops);
1062
+
1063
+ -- time-based queries
1064
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_created
1065
+ ON code_chunks(created_at DESC);
1066
+
1067
+ -- trigger for updated_at
1068
+ DROP TRIGGER IF EXISTS code_chunks_updated_at ON code_chunks;
1069
+ CREATE TRIGGER code_chunks_updated_at
1070
+ BEFORE UPDATE ON code_chunks
1071
+ FOR EACH ROW
1072
+ EXECUTE FUNCTION update_updated_at_column();
1073
+ `,
1074
+ down: `
1075
+ DROP TRIGGER IF EXISTS code_chunks_updated_at ON code_chunks;
1076
+ DROP TABLE IF EXISTS code_chunks CASCADE;
1077
+ `,
1078
+ checksum: this.generateChecksum('create_code_chunks_table_v17')
1079
+ },
1080
+ // migration 18: create code_definitions table
1081
+ // tracks all function/class/variable definitions
1082
+ // this is how we know WHAT code exists in the codebase
1083
+ {
1084
+ version: 18,
1085
+ name: 'create_code_definitions_table',
1086
+ up: `
1087
+ -- code_definitions - EVERY function, class, variable, etc
1088
+ -- this is your codebase's BRAIN MAP fr fr
1089
+ -- tracks signatures, types, exports, everything
1090
+ CREATE TABLE IF NOT EXISTS code_definitions (
1091
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
1092
+
1093
+ -- reference to parent file
1094
+ file_id UUID NOT NULL REFERENCES codebase_files(id) ON DELETE CASCADE,
1095
+ file_path TEXT NOT NULL,
1096
+
1097
+ -- definition identification
1098
+ name VARCHAR(500) NOT NULL,
1099
+ qualified_name TEXT, -- full path like module.class.method
1100
+ definition_type VARCHAR(50) NOT NULL, -- function, class, method, variable, interface, type, enum, constant
1101
+
1102
+ -- location
1103
+ start_line INTEGER NOT NULL,
1104
+ end_line INTEGER NOT NULL,
1105
+ start_column INTEGER DEFAULT 0,
1106
+ end_column INTEGER DEFAULT 0,
1107
+
1108
+ -- signature and documentation
1109
+ signature TEXT, -- full function/class signature
1110
+ docstring TEXT, -- extracted documentation
1111
+ return_type VARCHAR(255), -- for functions
1112
+
1113
+ -- visibility and scope
1114
+ visibility VARCHAR(20) DEFAULT 'public', -- public, private, protected, internal
1115
+ is_exported BOOLEAN DEFAULT false,
1116
+ is_async BOOLEAN DEFAULT false,
1117
+ is_static BOOLEAN DEFAULT false,
1118
+ is_abstract BOOLEAN DEFAULT false,
1119
+
1120
+ -- parent relationship (for nested definitions)
1121
+ parent_definition_id UUID REFERENCES code_definitions(id) ON DELETE CASCADE,
1122
+
1123
+ -- parameters (for functions/methods)
1124
+ parameters JSONB DEFAULT '[]', -- [{name, type, default, optional}]
1125
+
1126
+ -- language specific
1127
+ language VARCHAR(50) NOT NULL DEFAULT 'unknown',
1128
+
1129
+ -- decorators/annotations
1130
+ decorators TEXT[] DEFAULT '{}',
1131
+
1132
+ -- EMBEDDINGS for semantic search on definitions
1133
+ -- NOTE: Dimension is auto-detected, unbounded initially
1134
+ embedding vector(384),
1135
+
1136
+ -- full text search on name + signature + docstring
1137
+ definition_tsv TSVECTOR GENERATED ALWAYS AS (
1138
+ to_tsvector('english',
1139
+ COALESCE(name, '') || ' ' ||
1140
+ COALESCE(signature, '') || ' ' ||
1141
+ COALESCE(docstring, '')
1142
+ )
1143
+ ) STORED,
1144
+
1145
+ -- metadata
1146
+ metadata JSONB NOT NULL DEFAULT '{}',
1147
+
1148
+ -- timestamps
1149
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1150
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1151
+
1152
+ -- constraints
1153
+ CONSTRAINT name_not_empty CHECK (length(name) > 0),
1154
+ CONSTRAINT valid_definition_type CHECK (
1155
+ definition_type IN (
1156
+ 'function', 'method', 'class', 'interface', 'type', 'enum',
1157
+ 'variable', 'constant', 'property', 'getter', 'setter',
1158
+ 'constructor', 'decorator', 'module', 'namespace', 'trait',
1159
+ 'struct', 'protocol', 'extension', 'mixin', 'alias'
1160
+ )
1161
+ ),
1162
+ CONSTRAINT valid_visibility CHECK (
1163
+ visibility IN ('public', 'private', 'protected', 'internal', 'package')
1164
+ )
1165
+ );
1166
+
1167
+ -- indexes for LIGHTNING lookups
1168
+
1169
+ -- file lookups
1170
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_file_id
1171
+ ON code_definitions(file_id);
1172
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_file_path
1173
+ ON code_definitions(file_path);
1174
+
1175
+ -- name searches (the main use case)
1176
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_name
1177
+ ON code_definitions(name);
1178
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_name_trgm
1179
+ ON code_definitions USING GIN(name gin_trgm_ops);
1180
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_qualified
1181
+ ON code_definitions(qualified_name)
1182
+ WHERE qualified_name IS NOT NULL;
1183
+
1184
+ -- type filtering
1185
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_type
1186
+ ON code_definitions(definition_type);
1187
+
1188
+ -- language filtering
1189
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_language
1190
+ ON code_definitions(language);
1191
+
1192
+ -- exported definitions (for API surface)
1193
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_exported
1194
+ ON code_definitions(is_exported)
1195
+ WHERE is_exported = true;
1196
+
1197
+ -- parent-child relationships
1198
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_parent
1199
+ ON code_definitions(parent_definition_id)
1200
+ WHERE parent_definition_id IS NOT NULL;
1201
+
1202
+ -- full-text search
1203
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_tsv
1204
+ ON code_definitions USING GIN(definition_tsv);
1205
+
1206
+ -- HNSW vector index for semantic definition search
1207
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_embedding_hnsw
1208
+ ON code_definitions
1209
+ USING hnsw (embedding vector_cosine_ops)
1210
+ WITH (m = 16, ef_construction = 64);
1211
+
1212
+ -- line lookups (for finding definition at cursor)
1213
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_lines
1214
+ ON code_definitions(file_id, start_line, end_line);
1215
+
1216
+ -- composite for common queries
1217
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_type_name
1218
+ ON code_definitions(definition_type, name);
1219
+
1220
+ -- time-based queries
1221
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_created
1222
+ ON code_definitions(created_at DESC);
1223
+
1224
+ -- trigger for updated_at
1225
+ DROP TRIGGER IF EXISTS code_definitions_updated_at ON code_definitions;
1226
+ CREATE TRIGGER code_definitions_updated_at
1227
+ BEFORE UPDATE ON code_definitions
1228
+ FOR EACH ROW
1229
+ EXECUTE FUNCTION update_updated_at_column();
1230
+ `,
1231
+ down: `
1232
+ DROP TRIGGER IF EXISTS code_definitions_updated_at ON code_definitions;
1233
+ DROP TABLE IF EXISTS code_definitions CASCADE;
1234
+ `,
1235
+ checksum: this.generateChecksum('create_code_definitions_table_v18')
1236
+ },
1237
+ // migration 19: create code_dependencies table
1238
+ // tracks ALL imports, requires, includes across the codebase
1239
+ // builds the full dependency graph fr fr
1240
+ {
1241
+ version: 19,
1242
+ name: 'create_code_dependencies_table',
1243
+ up: `
1244
+ -- code_dependencies - the DEPENDENCY GRAPH
1245
+ -- tracks every import, require, include in the codebase
1246
+ -- we can trace dependencies through the ENTIRE project
1247
+ CREATE TABLE IF NOT EXISTS code_dependencies (
1248
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
1249
+
1250
+ -- source file (the file doing the importing)
1251
+ source_file_id UUID NOT NULL REFERENCES codebase_files(id) ON DELETE CASCADE,
1252
+ source_file_path TEXT NOT NULL,
1253
+
1254
+ -- target (what's being imported)
1255
+ target_path TEXT NOT NULL, -- could be relative, absolute, or package name
1256
+ resolved_path TEXT, -- resolved absolute path if local file
1257
+ target_file_id UUID REFERENCES codebase_files(id) ON DELETE SET NULL,
1258
+
1259
+ -- import details
1260
+ import_type VARCHAR(50) NOT NULL DEFAULT 'import', -- import, require, include, from, dynamic
1261
+ import_statement TEXT NOT NULL, -- the full import statement
1262
+
1263
+ -- what's being imported
1264
+ imported_names TEXT[] DEFAULT '{}', -- specific names: ['foo', 'bar']
1265
+ imported_as TEXT[] DEFAULT '{}', -- aliases: ['f', 'b']
1266
+ is_default_import BOOLEAN DEFAULT false,
1267
+ is_namespace_import BOOLEAN DEFAULT false, -- import * as
1268
+ is_type_import BOOLEAN DEFAULT false, -- TypeScript type imports
1269
+ is_side_effect_import BOOLEAN DEFAULT false, -- import 'polyfill'
1270
+
1271
+ -- location in source file
1272
+ line_number INTEGER NOT NULL,
1273
+ column_number INTEGER DEFAULT 0,
1274
+
1275
+ -- dependency classification
1276
+ is_external BOOLEAN DEFAULT false, -- from node_modules or external package
1277
+ is_builtin BOOLEAN DEFAULT false, -- built-in module (fs, path, etc)
1278
+ is_relative BOOLEAN DEFAULT false, -- ./foo or ../bar
1279
+ is_absolute BOOLEAN DEFAULT false, -- /abs/path
1280
+ is_dynamic BOOLEAN DEFAULT false, -- dynamic import()
1281
+
1282
+ -- package info (for external deps)
1283
+ package_name VARCHAR(255), -- extracted package name
1284
+ package_version VARCHAR(50), -- from package.json if available
1285
+
1286
+ -- language
1287
+ language VARCHAR(50) NOT NULL DEFAULT 'unknown',
1288
+
1289
+ -- metadata
1290
+ metadata JSONB NOT NULL DEFAULT '{}',
1291
+
1292
+ -- timestamps
1293
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1294
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1295
+
1296
+ -- constraints
1297
+ CONSTRAINT target_not_empty CHECK (length(target_path) > 0),
1298
+ CONSTRAINT valid_import_type CHECK (
1299
+ import_type IN (
1300
+ 'import', 'require', 'include', 'from', 'dynamic',
1301
+ 'import_type', 'import_value', 'reexport', 'side_effect'
1302
+ )
1303
+ )
1304
+ );
1305
+
1306
+ -- indexes for CRAZY FAST dependency lookups
1307
+
1308
+ -- source file lookups (what does this file import?)
1309
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_source_file
1310
+ ON code_dependencies(source_file_id);
1311
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_source_path
1312
+ ON code_dependencies(source_file_path);
1313
+
1314
+ -- target lookups (what imports this file?)
1315
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_target_file
1316
+ ON code_dependencies(target_file_id)
1317
+ WHERE target_file_id IS NOT NULL;
1318
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_target_path
1319
+ ON code_dependencies(target_path);
1320
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_resolved_path
1321
+ ON code_dependencies(resolved_path)
1322
+ WHERE resolved_path IS NOT NULL;
1323
+
1324
+ -- package lookups
1325
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_package
1326
+ ON code_dependencies(package_name)
1327
+ WHERE package_name IS NOT NULL;
1328
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_package_trgm
1329
+ ON code_dependencies USING GIN(package_name gin_trgm_ops)
1330
+ WHERE package_name IS NOT NULL;
1331
+
1332
+ -- external vs internal deps
1333
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_external
1334
+ ON code_dependencies(is_external);
1335
+
1336
+ -- import type filtering
1337
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_type
1338
+ ON code_dependencies(import_type);
1339
+
1340
+ -- language filtering
1341
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_language
1342
+ ON code_dependencies(language);
1343
+
1344
+ -- imported names search
1345
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_names
1346
+ ON code_dependencies USING GIN(imported_names);
1347
+
1348
+ -- composite for dependency graph traversal
1349
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_graph
1350
+ ON code_dependencies(source_file_id, target_file_id)
1351
+ WHERE target_file_id IS NOT NULL;
1352
+
1353
+ -- time-based queries
1354
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_created
1355
+ ON code_dependencies(created_at DESC);
1356
+
1357
+ -- trigger for updated_at
1358
+ DROP TRIGGER IF EXISTS code_dependencies_updated_at ON code_dependencies;
1359
+ CREATE TRIGGER code_dependencies_updated_at
1360
+ BEFORE UPDATE ON code_dependencies
1361
+ FOR EACH ROW
1362
+ EXECUTE FUNCTION update_updated_at_column();
1363
+ `,
1364
+ down: `
1365
+ DROP TRIGGER IF EXISTS code_dependencies_updated_at ON code_dependencies;
1366
+ DROP TABLE IF EXISTS code_dependencies CASCADE;
1367
+ `,
1368
+ checksum: this.generateChecksum('create_code_dependencies_table_v19')
1369
+ },
1370
+ // migration 20: create code_complexity table
1371
+ // tracks code complexity metrics for analysis
1372
+ // cyclomatic complexity, lines of code, maintainability index, etc
1373
+ {
1374
+ version: 20,
1375
+ name: 'create_code_complexity_table',
1376
+ up: `
1377
+ -- code_complexity - CODE QUALITY METRICS
1378
+ -- tracks complexity, maintainability, and other metrics
1379
+ -- helps identify code that needs refactoring fr
1380
+ CREATE TABLE IF NOT EXISTS code_complexity (
1381
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
1382
+
1383
+ -- reference to file
1384
+ file_id UUID NOT NULL REFERENCES codebase_files(id) ON DELETE CASCADE,
1385
+ file_path TEXT NOT NULL,
1386
+
1387
+ -- optional reference to specific definition
1388
+ definition_id UUID REFERENCES code_definitions(id) ON DELETE CASCADE,
1389
+ definition_name VARCHAR(500),
1390
+
1391
+ -- scope of measurement
1392
+ scope_type VARCHAR(50) NOT NULL DEFAULT 'file', -- file, function, class, method
1393
+
1394
+ -- basic metrics
1395
+ lines_of_code INTEGER NOT NULL DEFAULT 0,
1396
+ logical_lines INTEGER NOT NULL DEFAULT 0,
1397
+ comment_lines INTEGER NOT NULL DEFAULT 0,
1398
+ blank_lines INTEGER NOT NULL DEFAULT 0,
1399
+
1400
+ -- complexity metrics
1401
+ cyclomatic_complexity INTEGER, -- McCabe complexity
1402
+ cognitive_complexity INTEGER, -- SonarSource cognitive complexity
1403
+ halstead_difficulty FLOAT, -- Halstead difficulty
1404
+ halstead_effort FLOAT, -- Halstead effort
1405
+ halstead_volume FLOAT, -- Halstead volume
1406
+ maintainability_index FLOAT, -- Microsoft maintainability index
1407
+
1408
+ -- function/class specific metrics
1409
+ parameter_count INTEGER,
1410
+ return_statement_count INTEGER,
1411
+ nesting_depth INTEGER,
1412
+ coupling_score INTEGER, -- dependencies count
1413
+
1414
+ -- code smells and issues
1415
+ issues_count INTEGER DEFAULT 0,
1416
+ issues JSONB DEFAULT '[]', -- [{type, severity, message, line}]
1417
+
1418
+ -- duplicate code detection
1419
+ duplicate_blocks INTEGER DEFAULT 0,
1420
+ duplicate_lines INTEGER DEFAULT 0,
1421
+
1422
+ -- language
1423
+ language VARCHAR(50) NOT NULL DEFAULT 'unknown',
1424
+
1425
+ -- metadata
1426
+ metadata JSONB NOT NULL DEFAULT '{}',
1427
+
1428
+ -- when was this analyzed?
1429
+ analyzed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1430
+ analyzer_version VARCHAR(50),
1431
+
1432
+ -- timestamps
1433
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1434
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1435
+
1436
+ -- constraints
1437
+ CONSTRAINT valid_scope_type CHECK (
1438
+ scope_type IN ('file', 'function', 'method', 'class', 'module', 'chunk')
1439
+ ),
1440
+ CONSTRAINT valid_lines CHECK (lines_of_code >= 0)
1441
+ );
1442
+
1443
+ -- indexes for complexity analysis
1444
+
1445
+ -- file lookups
1446
+ CREATE INDEX IF NOT EXISTS idx_code_complexity_file_id
1447
+ ON code_complexity(file_id);
1448
+ CREATE INDEX IF NOT EXISTS idx_code_complexity_file_path
1449
+ ON code_complexity(file_path);
1450
+
1451
+ -- definition lookups
1452
+ CREATE INDEX IF NOT EXISTS idx_code_complexity_definition
1453
+ ON code_complexity(definition_id)
1454
+ WHERE definition_id IS NOT NULL;
1455
+
1456
+ -- scope filtering
1457
+ CREATE INDEX IF NOT EXISTS idx_code_complexity_scope
1458
+ ON code_complexity(scope_type);
1459
+
1460
+ -- complexity ranking (find most complex code)
1461
+ CREATE INDEX IF NOT EXISTS idx_code_complexity_cyclomatic
1462
+ ON code_complexity(cyclomatic_complexity DESC)
1463
+ WHERE cyclomatic_complexity IS NOT NULL;
1464
+ CREATE INDEX IF NOT EXISTS idx_code_complexity_cognitive
1465
+ ON code_complexity(cognitive_complexity DESC)
1466
+ WHERE cognitive_complexity IS NOT NULL;
1467
+
1468
+ -- maintainability ranking (find code needing work)
1469
+ CREATE INDEX IF NOT EXISTS idx_code_complexity_maintainability
1470
+ ON code_complexity(maintainability_index)
1471
+ WHERE maintainability_index IS NOT NULL;
1472
+
1473
+ -- issue tracking
1474
+ CREATE INDEX IF NOT EXISTS idx_code_complexity_issues
1475
+ ON code_complexity(issues_count DESC)
1476
+ WHERE issues_count > 0;
1477
+
1478
+ -- language filtering
1479
+ CREATE INDEX IF NOT EXISTS idx_code_complexity_language
1480
+ ON code_complexity(language);
1481
+
1482
+ -- time-based queries
1483
+ CREATE INDEX IF NOT EXISTS idx_code_complexity_analyzed
1484
+ ON code_complexity(analyzed_at DESC);
1485
+
1486
+ -- composite for common queries
1487
+ CREATE INDEX IF NOT EXISTS idx_code_complexity_scope_cyclomatic
1488
+ ON code_complexity(scope_type, cyclomatic_complexity DESC)
1489
+ WHERE cyclomatic_complexity IS NOT NULL;
1490
+
1491
+ -- trigger for updated_at
1492
+ DROP TRIGGER IF EXISTS code_complexity_updated_at ON code_complexity;
1493
+ CREATE TRIGGER code_complexity_updated_at
1494
+ BEFORE UPDATE ON code_complexity
1495
+ FOR EACH ROW
1496
+ EXECUTE FUNCTION update_updated_at_column();
1497
+
1498
+ -- materialized view for codebase health overview
1499
+ CREATE MATERIALIZED VIEW IF NOT EXISTS codebase_health_stats AS
1500
+ SELECT
1501
+ COUNT(*) as total_files_analyzed,
1502
+ SUM(lines_of_code) as total_lines,
1503
+ SUM(comment_lines) as total_comments,
1504
+ AVG(cyclomatic_complexity)::FLOAT as avg_cyclomatic_complexity,
1505
+ AVG(cognitive_complexity)::FLOAT as avg_cognitive_complexity,
1506
+ AVG(maintainability_index)::FLOAT as avg_maintainability_index,
1507
+ MAX(cyclomatic_complexity) as max_cyclomatic_complexity,
1508
+ MAX(cognitive_complexity) as max_cognitive_complexity,
1509
+ MIN(maintainability_index) as min_maintainability_index,
1510
+ SUM(issues_count) as total_issues,
1511
+ SUM(duplicate_lines) as total_duplicate_lines,
1512
+ COUNT(*) FILTER (WHERE cyclomatic_complexity > 10) as high_complexity_count,
1513
+ COUNT(*) FILTER (WHERE maintainability_index < 20) as low_maintainability_count,
1514
+ NOW() as computed_at
1515
+ FROM code_complexity
1516
+ WHERE scope_type = 'file';
1517
+
1518
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_codebase_health_stats_singleton
1519
+ ON codebase_health_stats(computed_at);
1520
+
1521
+ -- function to refresh health stats
1522
+ CREATE OR REPLACE FUNCTION refresh_codebase_health_stats()
1523
+ RETURNS void AS $$
1524
+ BEGIN
1525
+ REFRESH MATERIALIZED VIEW CONCURRENTLY codebase_health_stats;
1526
+ END;
1527
+ $$ LANGUAGE plpgsql;
1528
+ `,
1529
+ down: `
1530
+ DROP FUNCTION IF EXISTS refresh_codebase_health_stats();
1531
+ DROP MATERIALIZED VIEW IF EXISTS codebase_health_stats;
1532
+ DROP TRIGGER IF EXISTS code_complexity_updated_at ON code_complexity;
1533
+ DROP TABLE IF EXISTS code_complexity CASCADE;
1534
+ `,
1535
+ checksum: this.generateChecksum('create_code_complexity_table_v20')
1536
+ },
1537
+ // migration 21: create team_member_sessions table
1538
+ // tracks all team member sessions for the communication dashboard
1539
+ // this is where we track EVERY team member that connects fr
1540
+ {
1541
+ version: 21,
1542
+ name: 'create_team_member_sessions_table',
1543
+ up: `
1544
+ -- team_member_sessions - TEAM_MEMBER COMMUNICATION DASHBOARD
1545
+ -- tracks every team member session for live monitoring
1546
+ -- stores session lifecycle, status, and metadata
1547
+ CREATE TABLE IF NOT EXISTS team_member_sessions (
1548
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
1549
+
1550
+ -- team member identification
1551
+ team_member_id VARCHAR(255) NOT NULL,
1552
+ team_member_name VARCHAR(255) NOT NULL,
1553
+ team_member_type VARCHAR(100) NOT NULL DEFAULT 'assistant',
1554
+
1555
+ -- session lifecycle
1556
+ status VARCHAR(50) NOT NULL DEFAULT 'active',
1557
+ started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1558
+ ended_at TIMESTAMPTZ,
1559
+ last_heartbeat TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1560
+
1561
+ -- connection info
1562
+ connection_type VARCHAR(50) DEFAULT 'websocket',
1563
+ client_ip VARCHAR(45),
1564
+ user_agent TEXT,
1565
+
1566
+ -- task context
1567
+ current_task TEXT,
1568
+ working_directory TEXT,
1569
+ project_name VARCHAR(255),
1570
+
1571
+ -- metrics
1572
+ message_count INTEGER NOT NULL DEFAULT 0,
1573
+ tool_calls INTEGER NOT NULL DEFAULT 0,
1574
+ errors_count INTEGER NOT NULL DEFAULT 0,
1575
+ tokens_used INTEGER DEFAULT 0,
1576
+
1577
+ -- parent session for sub-team-members
1578
+ parent_session_id UUID REFERENCES team_member_sessions(id) ON DELETE SET NULL,
1579
+
1580
+ -- flexible metadata
1581
+ metadata JSONB NOT NULL DEFAULT '{}',
1582
+ capabilities JSONB DEFAULT '[]',
1583
+ environment JSONB DEFAULT '{}',
1584
+
1585
+ -- timestamps
1586
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1587
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1588
+
1589
+ -- constraints
1590
+ CONSTRAINT valid_status CHECK (
1591
+ status IN ('active', 'idle', 'busy', 'disconnected', 'terminated', 'error')
1592
+ ),
1593
+ CONSTRAINT valid_connection_type CHECK (
1594
+ connection_type IN ('websocket', 'http', 'grpc', 'stdio')
1595
+ )
1596
+ );
1597
+
1598
+ -- indexes for FAST session lookups
1599
+
1600
+ -- team member lookups
1601
+ CREATE INDEX IF NOT EXISTS idx_team_member_sessions_team_member_id
1602
+ ON team_member_sessions(team_member_id);
1603
+ CREATE INDEX IF NOT EXISTS idx_team_member_sessions_team_member_name
1604
+ ON team_member_sessions(team_member_name);
1605
+ CREATE INDEX IF NOT EXISTS idx_team_member_sessions_team_member_type
1606
+ ON team_member_sessions(team_member_type);
1607
+
1608
+ -- status filtering (active team members)
1609
+ CREATE INDEX IF NOT EXISTS idx_team_member_sessions_status
1610
+ ON team_member_sessions(status);
1611
+ CREATE INDEX IF NOT EXISTS idx_team_member_sessions_active
1612
+ ON team_member_sessions(team_member_id, last_heartbeat)
1613
+ WHERE status = 'active';
1614
+
1615
+ -- time-based queries
1616
+ CREATE INDEX IF NOT EXISTS idx_team_member_sessions_started
1617
+ ON team_member_sessions(started_at DESC);
1618
+ CREATE INDEX IF NOT EXISTS idx_team_member_sessions_ended
1619
+ ON team_member_sessions(ended_at DESC)
1620
+ WHERE ended_at IS NOT NULL;
1621
+ CREATE INDEX IF NOT EXISTS idx_team_member_sessions_heartbeat
1622
+ ON team_member_sessions(last_heartbeat DESC);
1623
+
1624
+ -- parent-child relationships
1625
+ CREATE INDEX IF NOT EXISTS idx_team_member_sessions_parent
1626
+ ON team_member_sessions(parent_session_id)
1627
+ WHERE parent_session_id IS NOT NULL;
1628
+
1629
+ -- project filtering
1630
+ CREATE INDEX IF NOT EXISTS idx_team_member_sessions_project
1631
+ ON team_member_sessions(project_name)
1632
+ WHERE project_name IS NOT NULL;
1633
+
1634
+ -- metadata queries
1635
+ CREATE INDEX IF NOT EXISTS idx_team_member_sessions_metadata
1636
+ ON team_member_sessions USING GIN(metadata jsonb_path_ops);
1637
+
1638
+ -- trigger for updated_at
1639
+ DROP TRIGGER IF EXISTS team_member_sessions_updated_at ON team_member_sessions;
1640
+ CREATE TRIGGER team_member_sessions_updated_at
1641
+ BEFORE UPDATE ON team_member_sessions
1642
+ FOR EACH ROW
1643
+ EXECUTE FUNCTION update_updated_at_column();
1644
+ `,
1645
+ down: `
1646
+ DROP TRIGGER IF EXISTS team_member_sessions_updated_at ON team_member_sessions;
1647
+ DROP TABLE IF EXISTS team_member_sessions CASCADE;
1648
+ `,
1649
+ checksum: this.generateChecksum('create_team_member_sessions_table_v21')
1650
+ },
1651
+ // migration 22: create team_member_messages table
1652
+ // stores all messages between team members and the system
1653
+ // this is the FULL communication log no cap
1654
+ {
1655
+ version: 22,
1656
+ name: 'create_team_member_messages_table',
1657
+ up: `
1658
+ -- team_member_messages - FULL COMMUNICATION LOG
1659
+ -- stores every message for replay and analysis
1660
+ -- supports streaming, tool calls, and responses
1661
+ CREATE TABLE IF NOT EXISTS team_member_messages (
1662
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
1663
+
1664
+ -- session reference
1665
+ session_id UUID NOT NULL REFERENCES team_member_sessions(id) ON DELETE CASCADE,
1666
+
1667
+ -- message identification
1668
+ message_type VARCHAR(50) NOT NULL DEFAULT 'text',
1669
+ direction VARCHAR(20) NOT NULL DEFAULT 'inbound',
1670
+ sequence_number INTEGER NOT NULL DEFAULT 0,
1671
+
1672
+ -- message content
1673
+ content TEXT NOT NULL,
1674
+ content_preview VARCHAR(500) GENERATED ALWAYS AS (
1675
+ CASE WHEN LENGTH(content) > 500 THEN LEFT(content, 497) || '...' ELSE content END
1676
+ ) STORED,
1677
+
1678
+ -- for tool calls
1679
+ tool_name VARCHAR(255),
1680
+ tool_input JSONB,
1681
+ tool_output JSONB,
1682
+ tool_error TEXT,
1683
+ tool_duration_ms INTEGER,
1684
+
1685
+ -- for streaming
1686
+ is_streaming BOOLEAN DEFAULT false,
1687
+ stream_complete BOOLEAN DEFAULT true,
1688
+ parent_message_id UUID REFERENCES team_member_messages(id) ON DELETE SET NULL,
1689
+
1690
+ -- classification
1691
+ role VARCHAR(50) NOT NULL DEFAULT 'assistant',
1692
+ importance VARCHAR(20) DEFAULT 'normal',
1693
+
1694
+ -- tokens and cost tracking
1695
+ input_tokens INTEGER DEFAULT 0,
1696
+ output_tokens INTEGER DEFAULT 0,
1697
+ estimated_cost_cents FLOAT DEFAULT 0,
1698
+
1699
+ -- error tracking
1700
+ is_error BOOLEAN DEFAULT false,
1701
+ error_code VARCHAR(100),
1702
+ error_message TEXT,
1703
+
1704
+ -- timestamps
1705
+ timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1706
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1707
+
1708
+ -- constraints
1709
+ CONSTRAINT valid_message_type CHECK (
1710
+ message_type IN (
1711
+ 'text', 'tool_call', 'tool_result', 'system', 'error',
1712
+ 'thinking', 'code', 'file_edit', 'command', 'response'
1713
+ )
1714
+ ),
1715
+ CONSTRAINT valid_direction CHECK (
1716
+ direction IN ('inbound', 'outbound', 'internal')
1717
+ ),
1718
+ CONSTRAINT valid_role CHECK (
1719
+ role IN ('user', 'assistant', 'system', 'tool')
1720
+ ),
1721
+ CONSTRAINT valid_importance CHECK (
1722
+ importance IN ('critical', 'high', 'normal', 'low', 'debug')
1723
+ )
1724
+ );
1725
+
1726
+ -- indexes for BLAZING FAST message queries
1727
+
1728
+ -- session lookups (primary query pattern)
1729
+ CREATE INDEX IF NOT EXISTS idx_team_member_messages_session
1730
+ ON team_member_messages(session_id, sequence_number);
1731
+ CREATE INDEX IF NOT EXISTS idx_team_member_messages_session_time
1732
+ ON team_member_messages(session_id, timestamp DESC);
1733
+
1734
+ -- message type filtering
1735
+ CREATE INDEX IF NOT EXISTS idx_team_member_messages_type
1736
+ ON team_member_messages(message_type);
1737
+
1738
+ -- tool call queries
1739
+ CREATE INDEX IF NOT EXISTS idx_team_member_messages_tool
1740
+ ON team_member_messages(tool_name)
1741
+ WHERE tool_name IS NOT NULL;
1742
+ CREATE INDEX IF NOT EXISTS idx_team_member_messages_tool_session
1743
+ ON team_member_messages(session_id, tool_name)
1744
+ WHERE message_type = 'tool_call';
1745
+
1746
+ -- error queries
1747
+ CREATE INDEX IF NOT EXISTS idx_team_member_messages_errors
1748
+ ON team_member_messages(session_id, timestamp)
1749
+ WHERE is_error = true;
1750
+
1751
+ -- streaming queries
1752
+ CREATE INDEX IF NOT EXISTS idx_team_member_messages_streaming
1753
+ ON team_member_messages(session_id, parent_message_id)
1754
+ WHERE is_streaming = true;
1755
+
1756
+ -- time-based queries
1757
+ CREATE INDEX IF NOT EXISTS idx_team_member_messages_timestamp
1758
+ ON team_member_messages(timestamp DESC);
1759
+
1760
+ -- direction filtering
1761
+ CREATE INDEX IF NOT EXISTS idx_team_member_messages_direction
1762
+ ON team_member_messages(direction);
1763
+
1764
+ -- role filtering
1765
+ CREATE INDEX IF NOT EXISTS idx_team_member_messages_role
1766
+ ON team_member_messages(role);
1767
+
1768
+ -- content search (full-text)
1769
+ CREATE INDEX IF NOT EXISTS idx_team_member_messages_content_tsv
1770
+ ON team_member_messages USING GIN(to_tsvector('english', content));
1771
+
1772
+ -- JSONB indexes for tool input/output
1773
+ CREATE INDEX IF NOT EXISTS idx_team_member_messages_tool_input
1774
+ ON team_member_messages USING GIN(tool_input)
1775
+ WHERE tool_input IS NOT NULL;
1776
+ `,
1777
+ down: `
1778
+ DROP TABLE IF EXISTS team_member_messages CASCADE;
1779
+ `,
1780
+ checksum: this.generateChecksum('create_team_member_messages_table_v22')
1781
+ },
1782
+ // migration 23: create team_member_deployments table
1783
+ // tracks deployment configurations and environments
1784
+ // supports multi-team member coordination and deployment history
1785
+ {
1786
+ version: 23,
1787
+ name: 'create_team_member_deployments_table',
1788
+ up: `
1789
+ -- team_member_deployments - DEPLOYMENT TRACKING
1790
+ -- tracks team member deployment configurations
1791
+ -- supports multi-environment and orchestration
1792
+ CREATE TABLE IF NOT EXISTS team_member_deployments (
1793
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
1794
+
1795
+ -- deployment identification
1796
+ deployment_name VARCHAR(255) NOT NULL,
1797
+ deployment_type VARCHAR(100) NOT NULL DEFAULT 'single',
1798
+ environment VARCHAR(100) NOT NULL DEFAULT 'development',
1799
+
1800
+ -- team member configuration
1801
+ team_member_config JSONB NOT NULL DEFAULT '{}',
1802
+ team_member_count INTEGER NOT NULL DEFAULT 1,
1803
+ team_member_template VARCHAR(255),
1804
+
1805
+ -- deployment status
1806
+ status VARCHAR(50) NOT NULL DEFAULT 'pending',
1807
+ health VARCHAR(50) DEFAULT 'unknown',
1808
+
1809
+ -- scheduling and lifecycle
1810
+ scheduled_at TIMESTAMPTZ,
1811
+ started_at TIMESTAMPTZ,
1812
+ completed_at TIMESTAMPTZ,
1813
+ timeout_seconds INTEGER DEFAULT 3600,
1814
+
1815
+ -- task configuration
1816
+ task_description TEXT,
1817
+ task_config JSONB DEFAULT '{}',
1818
+ input_data JSONB DEFAULT '{}',
1819
+ output_data JSONB DEFAULT '{}',
1820
+
1821
+ -- coordination
1822
+ coordinator_session_id UUID REFERENCES team_member_sessions(id) ON DELETE SET NULL,
1823
+ parent_deployment_id UUID REFERENCES team_member_deployments(id) ON DELETE SET NULL,
1824
+ child_deployment_count INTEGER DEFAULT 0,
1825
+
1826
+ -- resource tracking
1827
+ max_tokens INTEGER,
1828
+ max_cost_cents INTEGER,
1829
+ actual_tokens_used INTEGER DEFAULT 0,
1830
+ actual_cost_cents FLOAT DEFAULT 0,
1831
+
1832
+ -- results
1833
+ success BOOLEAN,
1834
+ result_summary TEXT,
1835
+ error_message TEXT,
1836
+ artifacts JSONB DEFAULT '[]',
1837
+
1838
+ -- version and rollback
1839
+ version INTEGER NOT NULL DEFAULT 1,
1840
+ previous_deployment_id UUID REFERENCES team_member_deployments(id) ON DELETE SET NULL,
1841
+ rollback_reason TEXT,
1842
+
1843
+ -- metadata
1844
+ metadata JSONB NOT NULL DEFAULT '{}',
1845
+ tags TEXT[] DEFAULT '{}',
1846
+ labels JSONB DEFAULT '{}',
1847
+
1848
+ -- timestamps
1849
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1850
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1851
+
1852
+ -- constraints
1853
+ CONSTRAINT valid_deployment_type CHECK (
1854
+ deployment_type IN (
1855
+ 'single', 'parallel', 'sequential', 'swarm', 'pipeline', 'orchestrated'
1856
+ )
1857
+ ),
1858
+ CONSTRAINT valid_deployment_status CHECK (
1859
+ status IN (
1860
+ 'pending', 'scheduled', 'running', 'paused', 'completed',
1861
+ 'failed', 'cancelled', 'timeout', 'rolled_back'
1862
+ )
1863
+ ),
1864
+ CONSTRAINT valid_health CHECK (
1865
+ health IN ('unknown', 'healthy', 'degraded', 'unhealthy', 'critical')
1866
+ ),
1867
+ CONSTRAINT valid_environment CHECK (
1868
+ environment IN (
1869
+ 'development', 'staging', 'production', 'test', 'local'
1870
+ )
1871
+ )
1872
+ );
1873
+
1874
+ -- indexes for deployment queries
1875
+
1876
+ -- name and type lookups
1877
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_name
1878
+ ON team_member_deployments(deployment_name);
1879
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_type
1880
+ ON team_member_deployments(deployment_type);
1881
+
1882
+ -- environment filtering
1883
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_env
1884
+ ON team_member_deployments(environment);
1885
+
1886
+ -- status queries
1887
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_status
1888
+ ON team_member_deployments(status);
1889
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_active
1890
+ ON team_member_deployments(status, started_at)
1891
+ WHERE status IN ('running', 'scheduled', 'pending');
1892
+
1893
+ -- health monitoring
1894
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_health
1895
+ ON team_member_deployments(health)
1896
+ WHERE status = 'running';
1897
+
1898
+ -- time-based queries
1899
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_created
1900
+ ON team_member_deployments(created_at DESC);
1901
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_started
1902
+ ON team_member_deployments(started_at DESC)
1903
+ WHERE started_at IS NOT NULL;
1904
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_completed
1905
+ ON team_member_deployments(completed_at DESC)
1906
+ WHERE completed_at IS NOT NULL;
1907
+
1908
+ -- coordinator lookups
1909
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_coordinator
1910
+ ON team_member_deployments(coordinator_session_id)
1911
+ WHERE coordinator_session_id IS NOT NULL;
1912
+
1913
+ -- parent-child relationships
1914
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_parent
1915
+ ON team_member_deployments(parent_deployment_id)
1916
+ WHERE parent_deployment_id IS NOT NULL;
1917
+
1918
+ -- version tracking
1919
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_version
1920
+ ON team_member_deployments(deployment_name, version DESC);
1921
+
1922
+ -- tag searches
1923
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_tags
1924
+ ON team_member_deployments USING GIN(tags);
1925
+
1926
+ -- metadata queries
1927
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_metadata
1928
+ ON team_member_deployments USING GIN(metadata jsonb_path_ops);
1929
+
1930
+ -- success rate queries
1931
+ CREATE INDEX IF NOT EXISTS idx_team_member_deployments_success
1932
+ ON team_member_deployments(deployment_type, success)
1933
+ WHERE completed_at IS NOT NULL;
1934
+
1935
+ -- trigger for updated_at
1936
+ DROP TRIGGER IF EXISTS team_member_deployments_updated_at ON team_member_deployments;
1937
+ CREATE TRIGGER team_member_deployments_updated_at
1938
+ BEFORE UPDATE ON team_member_deployments
1939
+ FOR EACH ROW
1940
+ EXECUTE FUNCTION update_updated_at_column();
1941
+
1942
+ -- materialized view for deployment stats
1943
+ CREATE MATERIALIZED VIEW IF NOT EXISTS team_member_deployment_stats AS
1944
+ SELECT
1945
+ COUNT(*) as total_deployments,
1946
+ COUNT(*) FILTER (WHERE status = 'running') as running_count,
1947
+ COUNT(*) FILTER (WHERE status = 'completed') as completed_count,
1948
+ COUNT(*) FILTER (WHERE status = 'failed') as failed_count,
1949
+ COUNT(*) FILTER (WHERE success = true) as success_count,
1950
+ COUNT(*) FILTER (WHERE success = false) as failure_count,
1951
+ AVG(EXTRACT(EPOCH FROM (completed_at - started_at)))::FLOAT as avg_duration_seconds,
1952
+ SUM(actual_tokens_used) as total_tokens_used,
1953
+ SUM(actual_cost_cents) as total_cost_cents,
1954
+ COUNT(DISTINCT deployment_name) as unique_deployments,
1955
+ COUNT(DISTINCT environment) as environments_used,
1956
+ NOW() as computed_at
1957
+ FROM team_member_deployments;
1958
+
1959
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_team_member_deployment_stats_singleton
1960
+ ON team_member_deployment_stats(computed_at);
1961
+
1962
+ -- function to refresh deployment stats
1963
+ CREATE OR REPLACE FUNCTION refresh_team_member_deployment_stats()
1964
+ RETURNS void AS $$
1965
+ BEGIN
1966
+ REFRESH MATERIALIZED VIEW CONCURRENTLY team_member_deployment_stats;
1967
+ END;
1968
+ $$ LANGUAGE plpgsql;
1969
+ `,
1970
+ down: `
1971
+ DROP FUNCTION IF EXISTS refresh_team_member_deployment_stats();
1972
+ DROP MATERIALIZED VIEW IF EXISTS team_member_deployment_stats;
1973
+ DROP TRIGGER IF EXISTS team_member_deployments_updated_at ON team_member_deployments;
1974
+ DROP TABLE IF EXISTS team_member_deployments CASCADE;
1975
+ `,
1976
+ checksum: this.generateChecksum('create_team_member_deployments_table_v23')
1977
+ },
1978
+ // migration 24: Phase 4-6 - Direct Prompting and Control tables
1979
+ {
1980
+ version: 24,
1981
+ name: 'create_prompt_and_trigger_tables',
1982
+ up: `
1983
+ -- Table for storing prompt/conversation history (Phase 4)
1984
+ CREATE TABLE IF NOT EXISTS prompt_history (
1985
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
1986
+ session_id VARCHAR(255) NOT NULL,
1987
+ prompt TEXT NOT NULL,
1988
+ response TEXT,
1989
+ context JSONB NOT NULL DEFAULT '{}',
1990
+ config JSONB NOT NULL DEFAULT '{}',
1991
+ tokens_used INTEGER DEFAULT 0,
1992
+ duration_ms INTEGER DEFAULT 0,
1993
+ status VARCHAR(20) NOT NULL DEFAULT 'pending',
1994
+ error_message TEXT,
1995
+ model VARCHAR(100),
1996
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1997
+
1998
+ CONSTRAINT valid_prompt_status CHECK (
1999
+ status IN ('pending', 'success', 'error')
2000
+ )
2001
+ );
2002
+
2003
+ -- Indexes for prompt history
2004
+ CREATE INDEX IF NOT EXISTS idx_prompt_history_session
2005
+ ON prompt_history(session_id);
2006
+ CREATE INDEX IF NOT EXISTS idx_prompt_history_created
2007
+ ON prompt_history(created_at DESC);
2008
+ CREATE INDEX IF NOT EXISTS idx_prompt_history_status
2009
+ ON prompt_history(status);
2010
+
2011
+ -- Table for storing trigger history (Phase 6)
2012
+ CREATE TABLE IF NOT EXISTS trigger_history (
2013
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
2014
+ action VARCHAR(50) NOT NULL,
2015
+ prompt TEXT NOT NULL,
2016
+ config JSONB NOT NULL DEFAULT '{}',
2017
+ context JSONB NOT NULL DEFAULT '{}',
2018
+ status VARCHAR(20) NOT NULL DEFAULT 'pending',
2019
+ result TEXT,
2020
+ error_message TEXT,
2021
+ confirmed_by VARCHAR(255),
2022
+ confirmed_at TIMESTAMPTZ,
2023
+ started_at TIMESTAMPTZ,
2024
+ completed_at TIMESTAMPTZ,
2025
+ tokens_used INTEGER DEFAULT 0,
2026
+ duration_ms INTEGER DEFAULT 0,
2027
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2028
+
2029
+ CONSTRAINT valid_trigger_status CHECK (
2030
+ status IN ('pending', 'running', 'completed', 'failed', 'cancelled')
2031
+ ),
2032
+ CONSTRAINT valid_trigger_action CHECK (
2033
+ action IN ('fix-error', 'consolidate', 'deploy-team-member', 'analyze-codebase', 'summarize-session', 'custom')
2034
+ )
2035
+ );
2036
+
2037
+ -- Indexes for trigger history
2038
+ CREATE INDEX IF NOT EXISTS idx_trigger_history_action
2039
+ ON trigger_history(action);
2040
+ CREATE INDEX IF NOT EXISTS idx_trigger_history_status
2041
+ ON trigger_history(status);
2042
+ CREATE INDEX IF NOT EXISTS idx_trigger_history_created
2043
+ ON trigger_history(created_at DESC);
2044
+
2045
+ -- Table for scheduled triggers (Phase 6)
2046
+ CREATE TABLE IF NOT EXISTS scheduled_triggers (
2047
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
2048
+ action VARCHAR(50) NOT NULL,
2049
+ prompt TEXT NOT NULL,
2050
+ config JSONB NOT NULL DEFAULT '{}',
2051
+ schedule JSONB NOT NULL,
2052
+ enabled BOOLEAN NOT NULL DEFAULT true,
2053
+ last_run TIMESTAMPTZ,
2054
+ next_run TIMESTAMPTZ,
2055
+ run_count INTEGER NOT NULL DEFAULT 0,
2056
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2057
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2058
+
2059
+ CONSTRAINT valid_scheduled_action CHECK (
2060
+ action IN ('fix-error', 'consolidate', 'deploy-team-member', 'analyze-codebase', 'summarize-session', 'custom')
2061
+ )
2062
+ );
2063
+
2064
+ -- Indexes for scheduled triggers
2065
+ CREATE INDEX IF NOT EXISTS idx_scheduled_triggers_enabled
2066
+ ON scheduled_triggers(enabled, next_run)
2067
+ WHERE enabled = true;
2068
+ CREATE INDEX IF NOT EXISTS idx_scheduled_triggers_next_run
2069
+ ON scheduled_triggers(next_run)
2070
+ WHERE enabled = true;
2071
+
2072
+ -- trigger for updated_at
2073
+ DROP TRIGGER IF EXISTS scheduled_triggers_updated_at ON scheduled_triggers;
2074
+ CREATE TRIGGER scheduled_triggers_updated_at
2075
+ BEFORE UPDATE ON scheduled_triggers
2076
+ FOR EACH ROW
2077
+ EXECUTE FUNCTION update_updated_at_column();
2078
+ `,
2079
+ down: `
2080
+ DROP TRIGGER IF EXISTS scheduled_triggers_updated_at ON scheduled_triggers;
2081
+ DROP TABLE IF EXISTS scheduled_triggers CASCADE;
2082
+ DROP TABLE IF EXISTS trigger_history CASCADE;
2083
+ DROP TABLE IF EXISTS prompt_history CASCADE;
2084
+ `,
2085
+ checksum: this.generateChecksum('create_prompt_and_trigger_tables_v24')
2086
+ },
2087
+ // migration 25: File change history tracking - ACTIVE CODE MONITORING
2088
+ // Tracks every file change so we can see what ACTUALLY changed over time
2089
+ {
2090
+ version: 25,
2091
+ name: 'create_file_change_history',
2092
+ up: `
2093
+ -- Make sure pgcrypto is available for digest function
2094
+ CREATE EXTENSION IF NOT EXISTS pgcrypto;
2095
+
2096
+ -- Add content_hash column to codebase_files if missing
2097
+ -- SHA256 hash of content for change detection
2098
+ DO $$ BEGIN
2099
+ ALTER TABLE codebase_files
2100
+ ADD COLUMN IF NOT EXISTS content_hash VARCHAR(64);
2101
+ EXCEPTION WHEN duplicate_column THEN NULL;
2102
+ END $$;
2103
+
2104
+ -- Update existing rows with their content hash using pgcrypto digest
2105
+ UPDATE codebase_files
2106
+ SET content_hash = encode(digest(content, 'sha256'), 'hex')
2107
+ WHERE content_hash IS NULL;
2108
+
2109
+ -- Create index for hash lookups
2110
+ CREATE INDEX IF NOT EXISTS idx_codebase_files_hash
2111
+ ON codebase_files(content_hash);
2112
+
2113
+ -- File change history table - THE MEMORY OF EVERY EDIT
2114
+ -- Tracks add, modify, delete events with before/after content
2115
+ CREATE TABLE IF NOT EXISTS file_change_history (
2116
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
2117
+
2118
+ -- File identification
2119
+ file_path TEXT NOT NULL,
2120
+ absolute_path TEXT NOT NULL,
2121
+ file_id UUID, -- Reference to codebase_files (null if deleted)
2122
+
2123
+ -- Change type
2124
+ change_type VARCHAR(20) NOT NULL,
2125
+
2126
+ -- Content tracking - stores diffs for efficiency
2127
+ previous_hash VARCHAR(64),
2128
+ new_hash VARCHAR(64),
2129
+ previous_content TEXT, -- Stored for small files or on demand
2130
+ new_content TEXT, -- Stored for small files or on demand
2131
+ content_diff TEXT, -- Unified diff format
2132
+
2133
+ -- Metadata
2134
+ size_before INTEGER,
2135
+ size_after INTEGER,
2136
+ line_count_before INTEGER,
2137
+ line_count_after INTEGER,
2138
+ lines_added INTEGER DEFAULT 0,
2139
+ lines_removed INTEGER DEFAULT 0,
2140
+
2141
+ -- Timestamps
2142
+ detected_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2143
+ file_modified_at TIMESTAMPTZ,
2144
+
2145
+ -- Context
2146
+ metadata JSONB NOT NULL DEFAULT '{}',
2147
+
2148
+ CONSTRAINT valid_change_type CHECK (
2149
+ change_type IN ('add', 'modify', 'delete', 'rename', 'move')
2150
+ )
2151
+ );
2152
+
2153
+ -- Indexes for history queries
2154
+ CREATE INDEX IF NOT EXISTS idx_file_change_history_path
2155
+ ON file_change_history(file_path);
2156
+ CREATE INDEX IF NOT EXISTS idx_file_change_history_file_id
2157
+ ON file_change_history(file_id)
2158
+ WHERE file_id IS NOT NULL;
2159
+ CREATE INDEX IF NOT EXISTS idx_file_change_history_detected
2160
+ ON file_change_history(detected_at DESC);
2161
+ CREATE INDEX IF NOT EXISTS idx_file_change_history_type
2162
+ ON file_change_history(change_type);
2163
+ CREATE INDEX IF NOT EXISTS idx_file_change_history_hash
2164
+ ON file_change_history(new_hash)
2165
+ WHERE new_hash IS NOT NULL;
2166
+
2167
+ -- Full text search on file paths in history
2168
+ CREATE INDEX IF NOT EXISTS idx_file_change_history_path_trgm
2169
+ ON file_change_history USING gin (file_path gin_trgm_ops);
2170
+
2171
+ -- Composite index for file timeline queries
2172
+ CREATE INDEX IF NOT EXISTS idx_file_change_history_timeline
2173
+ ON file_change_history(file_path, detected_at DESC);
2174
+
2175
+ -- Function to record file changes automatically using pgcrypto digest
2176
+ CREATE OR REPLACE FUNCTION record_file_change()
2177
+ RETURNS TRIGGER AS $$
2178
+ BEGIN
2179
+ IF TG_OP = 'INSERT' THEN
2180
+ INSERT INTO file_change_history (
2181
+ file_path, absolute_path, file_id, change_type,
2182
+ new_hash, new_content, size_after, line_count_after,
2183
+ file_modified_at, metadata
2184
+ ) VALUES (
2185
+ NEW.file_path, NEW.absolute_path, NEW.id, 'add',
2186
+ encode(digest(NEW.content, 'sha256'), 'hex'),
2187
+ CASE WHEN length(NEW.content) < 50000 THEN NEW.content ELSE NULL END,
2188
+ NEW.size_bytes, NEW.line_count,
2189
+ NEW.last_modified,
2190
+ jsonb_build_object('language', NEW.language_id, 'trigger', 'insert')
2191
+ );
2192
+ RETURN NEW;
2193
+ ELSIF TG_OP = 'UPDATE' THEN
2194
+ -- Only record if content actually changed
2195
+ IF OLD.content IS DISTINCT FROM NEW.content THEN
2196
+ INSERT INTO file_change_history (
2197
+ file_path, absolute_path, file_id, change_type,
2198
+ previous_hash, new_hash,
2199
+ previous_content, new_content,
2200
+ size_before, size_after,
2201
+ line_count_before, line_count_after,
2202
+ file_modified_at, metadata
2203
+ ) VALUES (
2204
+ NEW.file_path, NEW.absolute_path, NEW.id, 'modify',
2205
+ encode(digest(OLD.content, 'sha256'), 'hex'),
2206
+ encode(digest(NEW.content, 'sha256'), 'hex'),
2207
+ CASE WHEN length(OLD.content) < 50000 THEN OLD.content ELSE NULL END,
2208
+ CASE WHEN length(NEW.content) < 50000 THEN NEW.content ELSE NULL END,
2209
+ OLD.size_bytes, NEW.size_bytes,
2210
+ OLD.line_count, NEW.line_count,
2211
+ NEW.last_modified,
2212
+ jsonb_build_object('language', NEW.language_id, 'trigger', 'update')
2213
+ );
2214
+ END IF;
2215
+ RETURN NEW;
2216
+ ELSIF TG_OP = 'DELETE' THEN
2217
+ INSERT INTO file_change_history (
2218
+ file_path, absolute_path, file_id, change_type,
2219
+ previous_hash, previous_content,
2220
+ size_before, line_count_before,
2221
+ file_modified_at, metadata
2222
+ ) VALUES (
2223
+ OLD.file_path, OLD.absolute_path, NULL, 'delete',
2224
+ encode(digest(OLD.content, 'sha256'), 'hex'),
2225
+ CASE WHEN length(OLD.content) < 50000 THEN OLD.content ELSE NULL END,
2226
+ OLD.size_bytes, OLD.line_count,
2227
+ NOW(),
2228
+ jsonb_build_object('language', OLD.language_id, 'trigger', 'delete')
2229
+ );
2230
+ RETURN OLD;
2231
+ END IF;
2232
+ RETURN NULL;
2233
+ END;
2234
+ $$ LANGUAGE plpgsql;
2235
+
2236
+ -- Attach trigger to codebase_files
2237
+ DROP TRIGGER IF EXISTS codebase_files_change_history ON codebase_files;
2238
+ CREATE TRIGGER codebase_files_change_history
2239
+ AFTER INSERT OR UPDATE OR DELETE ON codebase_files
2240
+ FOR EACH ROW
2241
+ EXECUTE FUNCTION record_file_change();
2242
+
2243
+ -- View for recent changes summary
2244
+ CREATE OR REPLACE VIEW recent_file_changes AS
2245
+ SELECT
2246
+ fch.id,
2247
+ fch.file_path,
2248
+ fch.change_type,
2249
+ fch.detected_at,
2250
+ fch.lines_added,
2251
+ fch.lines_removed,
2252
+ fch.size_before,
2253
+ fch.size_after,
2254
+ cf.language_id
2255
+ FROM file_change_history fch
2256
+ LEFT JOIN codebase_files cf ON cf.id = fch.file_id
2257
+ ORDER BY fch.detected_at DESC
2258
+ LIMIT 100;
2259
+ `,
2260
+ down: `
2261
+ DROP VIEW IF EXISTS recent_file_changes;
2262
+ DROP TRIGGER IF EXISTS codebase_files_change_history ON codebase_files;
2263
+ DROP FUNCTION IF EXISTS record_file_change();
2264
+ DROP TABLE IF EXISTS file_change_history CASCADE;
2265
+ ALTER TABLE codebase_files DROP COLUMN IF EXISTS content_hash;
2266
+ `,
2267
+ checksum: this.generateChecksum('create_file_change_history_v25_fixed')
2268
+ },
2269
+ // migration 26: SPATIAL MEMORY EVOLUTION - Quadrants, Clusters, Hot Paths
2270
+ // Makes 's memory ACTUALLY INTELLIGENT through spatial organization
2271
+ // This is where memory becomes self-organizing fr fr
2272
+ {
2273
+ version: 26,
2274
+ name: 'create_spatial_memory_tables',
2275
+ up: `
2276
+ -- ============================================================
2277
+ -- SEMANTIC QUADRANTS - Organize memories in 2D semantic space
2278
+ -- Memories are assigned to quadrants based on embedding clusters
2279
+ -- Enables region-based searching like "find all memories in Q1"
2280
+ -- ============================================================
2281
+ CREATE TABLE IF NOT EXISTS semantic_quadrants (
2282
+ id SERIAL PRIMARY KEY,
2283
+
2284
+ -- Quadrant identification
2285
+ name VARCHAR(100) NOT NULL,
2286
+ description TEXT,
2287
+ quadrant_code VARCHAR(20) NOT NULL UNIQUE, -- e.g., 'Q1', 'Q2-A', 'tech-backend'
2288
+
2289
+ -- Centroid embedding for the quadrant
2290
+ -- NOTE: Dimension is auto-detected, unbounded initially
2291
+ centroid vector(384),
2292
+
2293
+ -- Bounding box in reduced dimension space (for fast filtering)
2294
+ -- Using 2D projection of embeddings (UMAP/t-SNE style)
2295
+ min_x FLOAT,
2296
+ max_x FLOAT,
2297
+ min_y FLOAT,
2298
+ max_y FLOAT,
2299
+
2300
+ -- Hierarchical structure support
2301
+ parent_quadrant_id INTEGER REFERENCES semantic_quadrants(id) ON DELETE SET NULL,
2302
+ depth INTEGER NOT NULL DEFAULT 0,
2303
+
2304
+ -- Statistics
2305
+ memory_count INTEGER NOT NULL DEFAULT 0,
2306
+ max_capacity INTEGER DEFAULT 1000, -- Triggers split when exceeded
2307
+ avg_similarity FLOAT, -- Average similarity within quadrant
2308
+ last_rebalanced_at TIMESTAMPTZ,
2309
+
2310
+ -- Metadata
2311
+ auto_generated BOOLEAN DEFAULT true,
2312
+ tags TEXT[] DEFAULT '{}',
2313
+ metadata JSONB NOT NULL DEFAULT '{}',
2314
+
2315
+ -- Timestamps
2316
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2317
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
2318
+ );
2319
+
2320
+ -- Indexes for quadrant lookups
2321
+ CREATE INDEX IF NOT EXISTS idx_semantic_quadrants_code
2322
+ ON semantic_quadrants(quadrant_code);
2323
+ CREATE INDEX IF NOT EXISTS idx_semantic_quadrants_parent
2324
+ ON semantic_quadrants(parent_quadrant_id)
2325
+ WHERE parent_quadrant_id IS NOT NULL;
2326
+ CREATE INDEX IF NOT EXISTS idx_semantic_quadrants_bounds
2327
+ ON semantic_quadrants(min_x, max_x, min_y, max_y)
2328
+ WHERE min_x IS NOT NULL;
2329
+
2330
+ -- Memory to quadrant assignments
2331
+ CREATE TABLE IF NOT EXISTS memory_quadrant_assignments (
2332
+ memory_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
2333
+ quadrant_id INTEGER NOT NULL REFERENCES semantic_quadrants(id) ON DELETE CASCADE,
2334
+
2335
+ -- Position within quadrant (reduced 2D space)
2336
+ pos_x FLOAT,
2337
+ pos_y FLOAT,
2338
+
2339
+ -- Distance from centroid (for ranking within quadrant)
2340
+ distance_from_centroid FLOAT,
2341
+
2342
+ -- Assignment metadata
2343
+ assigned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2344
+ assignment_method VARCHAR(50) DEFAULT 'auto', -- auto, manual, migration
2345
+
2346
+ PRIMARY KEY (memory_id, quadrant_id)
2347
+ );
2348
+
2349
+ CREATE INDEX IF NOT EXISTS idx_memory_quadrant_memory
2350
+ ON memory_quadrant_assignments(memory_id);
2351
+ CREATE INDEX IF NOT EXISTS idx_memory_quadrant_quadrant
2352
+ ON memory_quadrant_assignments(quadrant_id);
2353
+ CREATE INDEX IF NOT EXISTS idx_memory_quadrant_position
2354
+ ON memory_quadrant_assignments(quadrant_id, pos_x, pos_y);
2355
+
2356
+ -- ============================================================
2357
+ -- SEMANTIC CLUSTERS - Auto-forming memory neighborhoods
2358
+ -- Groups related memories using clustering algorithms
2359
+ -- Clusters get auto-generated labels from content themes
2360
+ -- ============================================================
2361
+ CREATE TABLE IF NOT EXISTS memory_clusters (
2362
+ id SERIAL PRIMARY KEY,
2363
+
2364
+ -- Cluster identification
2365
+ name VARCHAR(255), -- Auto-generated from top tags/content
2366
+ description TEXT, -- Summary of what this cluster contains
2367
+ cluster_type VARCHAR(50) NOT NULL DEFAULT 'semantic', -- semantic, temporal, tag_based, manual
2368
+
2369
+ -- Centroid for the cluster
2370
+ -- NOTE: Dimension is auto-detected, unbounded initially
2371
+ centroid vector(384),
2372
+
2373
+ -- Statistics
2374
+ memory_count INTEGER NOT NULL DEFAULT 0,
2375
+ coherence_score FLOAT, -- 0-1 how tight the cluster is
2376
+ silhouette_score FLOAT, -- Cluster quality metric
2377
+
2378
+ -- Top terms/tags in this cluster (auto-extracted)
2379
+ top_tags TEXT[] DEFAULT '{}',
2380
+ top_terms TEXT[] DEFAULT '{}',
2381
+
2382
+ -- Hierarchy support (clusters can nest)
2383
+ parent_cluster_id INTEGER REFERENCES memory_clusters(id) ON DELETE SET NULL,
2384
+ depth INTEGER NOT NULL DEFAULT 0,
2385
+
2386
+ -- Lifecycle
2387
+ last_updated_at TIMESTAMPTZ,
2388
+ last_recomputed_at TIMESTAMPTZ,
2389
+ is_stable BOOLEAN DEFAULT false, -- True if cluster hasn't changed recently
2390
+
2391
+ -- Metadata
2392
+ metadata JSONB NOT NULL DEFAULT '{}',
2393
+
2394
+ -- Timestamps
2395
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2396
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
2397
+ );
2398
+
2399
+ CREATE INDEX IF NOT EXISTS idx_memory_clusters_type
2400
+ ON memory_clusters(cluster_type);
2401
+ CREATE INDEX IF NOT EXISTS idx_memory_clusters_parent
2402
+ ON memory_clusters(parent_cluster_id)
2403
+ WHERE parent_cluster_id IS NOT NULL;
2404
+ CREATE INDEX IF NOT EXISTS idx_memory_clusters_coherence
2405
+ ON memory_clusters(coherence_score DESC)
2406
+ WHERE coherence_score IS NOT NULL;
2407
+
2408
+ -- Memory to cluster assignments (many-to-many - soft clustering)
2409
+ CREATE TABLE IF NOT EXISTS memory_cluster_assignments (
2410
+ memory_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
2411
+ cluster_id INTEGER NOT NULL REFERENCES memory_clusters(id) ON DELETE CASCADE,
2412
+
2413
+ -- Membership strength (0-1, supports soft clustering)
2414
+ membership_score FLOAT NOT NULL DEFAULT 1.0,
2415
+
2416
+ -- Distance from cluster centroid
2417
+ distance_to_centroid FLOAT,
2418
+
2419
+ -- Assignment metadata
2420
+ assigned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2421
+ assignment_method VARCHAR(50) DEFAULT 'auto',
2422
+
2423
+ PRIMARY KEY (memory_id, cluster_id)
2424
+ );
2425
+
2426
+ CREATE INDEX IF NOT EXISTS idx_memory_cluster_assign_memory
2427
+ ON memory_cluster_assignments(memory_id);
2428
+ CREATE INDEX IF NOT EXISTS idx_memory_cluster_assign_cluster
2429
+ ON memory_cluster_assignments(cluster_id);
2430
+ CREATE INDEX IF NOT EXISTS idx_memory_cluster_assign_score
2431
+ ON memory_cluster_assignments(cluster_id, membership_score DESC);
2432
+
2433
+ -- Cluster relationships (which clusters are related)
2434
+ CREATE TABLE IF NOT EXISTS cluster_relations (
2435
+ source_cluster_id INTEGER NOT NULL REFERENCES memory_clusters(id) ON DELETE CASCADE,
2436
+ target_cluster_id INTEGER NOT NULL REFERENCES memory_clusters(id) ON DELETE CASCADE,
2437
+
2438
+ relation_type VARCHAR(50) NOT NULL DEFAULT 'similar', -- similar, parent, child, overlapping, adjacent
2439
+ strength FLOAT NOT NULL DEFAULT 1.0,
2440
+
2441
+ -- Shared memories count
2442
+ shared_memory_count INTEGER DEFAULT 0,
2443
+
2444
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2445
+
2446
+ PRIMARY KEY (source_cluster_id, target_cluster_id, relation_type),
2447
+ CONSTRAINT no_self_cluster_relation CHECK (source_cluster_id != target_cluster_id)
2448
+ );
2449
+
2450
+ CREATE INDEX IF NOT EXISTS idx_cluster_relations_source
2451
+ ON cluster_relations(source_cluster_id);
2452
+ CREATE INDEX IF NOT EXISTS idx_cluster_relations_target
2453
+ ON cluster_relations(target_cluster_id);
2454
+
2455
+ -- ============================================================
2456
+ -- HOT PATH ACCELERATION - Frequently accessed memory chains
2457
+ -- Tracks which memories get accessed together
2458
+ -- Pre-fetches and caches common access patterns
2459
+ -- ============================================================
2460
+ CREATE TABLE IF NOT EXISTS memory_hot_paths (
2461
+ id SERIAL PRIMARY KEY,
2462
+
2463
+ -- Path identification
2464
+ path_name VARCHAR(255),
2465
+ path_hash VARCHAR(64) UNIQUE, -- Hash of ordered memory IDs
2466
+
2467
+ -- Ordered list of memories in this path
2468
+ memory_ids UUID[] NOT NULL,
2469
+ memory_count INTEGER NOT NULL,
2470
+
2471
+ -- Usage statistics
2472
+ access_count INTEGER NOT NULL DEFAULT 0,
2473
+ last_accessed_at TIMESTAMPTZ,
2474
+ first_accessed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2475
+
2476
+ -- Heat score (decays over time, increases with access)
2477
+ heat_score FLOAT NOT NULL DEFAULT 1.0,
2478
+ peak_heat_score FLOAT NOT NULL DEFAULT 1.0,
2479
+
2480
+ -- Cache status
2481
+ is_cached BOOLEAN DEFAULT false,
2482
+ cached_at TIMESTAMPTZ,
2483
+ cache_hits INTEGER DEFAULT 0,
2484
+
2485
+ -- Path characteristics
2486
+ avg_transition_similarity FLOAT, -- How similar adjacent memories are
2487
+ path_coherence FLOAT, -- Overall semantic coherence
2488
+ dominant_tags TEXT[] DEFAULT '{}',
2489
+
2490
+ -- Metadata
2491
+ metadata JSONB NOT NULL DEFAULT '{}',
2492
+
2493
+ -- Timestamps
2494
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2495
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
2496
+ );
2497
+
2498
+ CREATE INDEX IF NOT EXISTS idx_hot_paths_hash
2499
+ ON memory_hot_paths(path_hash);
2500
+ CREATE INDEX IF NOT EXISTS idx_hot_paths_heat
2501
+ ON memory_hot_paths(heat_score DESC);
2502
+ CREATE INDEX IF NOT EXISTS idx_hot_paths_cached
2503
+ ON memory_hot_paths(is_cached)
2504
+ WHERE is_cached = true;
2505
+ CREATE INDEX IF NOT EXISTS idx_hot_paths_accessed
2506
+ ON memory_hot_paths(last_accessed_at DESC);
2507
+ CREATE INDEX IF NOT EXISTS idx_hot_paths_memory_ids
2508
+ ON memory_hot_paths USING GIN(memory_ids);
2509
+
2510
+ -- Access pattern tracking (individual transitions)
2511
+ CREATE TABLE IF NOT EXISTS memory_access_transitions (
2512
+ id BIGSERIAL PRIMARY KEY,
2513
+
2514
+ -- The transition
2515
+ from_memory_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
2516
+ to_memory_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
2517
+
2518
+ -- Statistics
2519
+ transition_count INTEGER NOT NULL DEFAULT 1,
2520
+ last_transition_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2521
+
2522
+ -- Context
2523
+ session_id VARCHAR(255), -- Track transitions within sessions
2524
+ time_between_ms INTEGER, -- Time between accesses
2525
+
2526
+ -- Timestamps
2527
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2528
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
2529
+ );
2530
+
2531
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_access_transitions_pair
2532
+ ON memory_access_transitions(from_memory_id, to_memory_id);
2533
+ CREATE INDEX IF NOT EXISTS idx_access_transitions_from
2534
+ ON memory_access_transitions(from_memory_id);
2535
+ CREATE INDEX IF NOT EXISTS idx_access_transitions_to
2536
+ ON memory_access_transitions(to_memory_id);
2537
+ CREATE INDEX IF NOT EXISTS idx_access_transitions_count
2538
+ ON memory_access_transitions(transition_count DESC);
2539
+ CREATE INDEX IF NOT EXISTS idx_access_transitions_session
2540
+ ON memory_access_transitions(session_id)
2541
+ WHERE session_id IS NOT NULL;
2542
+
2543
+ -- ============================================================
2544
+ -- ENHANCED MEMORY GRAPH - Typed relationships with inference
2545
+ -- Extends basic memory_relations with more graph features
2546
+ -- ============================================================
2547
+
2548
+ -- Add new columns to memory_relations if they don't exist
2549
+ DO $$ BEGIN
2550
+ ALTER TABLE memory_relations
2551
+ ADD COLUMN IF NOT EXISTS relation_category VARCHAR(50) DEFAULT 'explicit'; -- explicit, inferred, temporal
2552
+ EXCEPTION WHEN duplicate_column THEN NULL;
2553
+ END $$;
2554
+
2555
+ DO $$ BEGIN
2556
+ ALTER TABLE memory_relations
2557
+ ADD COLUMN IF NOT EXISTS confidence FLOAT DEFAULT 1.0; -- For inferred relations
2558
+ EXCEPTION WHEN duplicate_column THEN NULL;
2559
+ END $$;
2560
+
2561
+ DO $$ BEGIN
2562
+ ALTER TABLE memory_relations
2563
+ ADD COLUMN IF NOT EXISTS access_count INTEGER DEFAULT 0;
2564
+ EXCEPTION WHEN duplicate_column THEN NULL;
2565
+ END $$;
2566
+
2567
+ DO $$ BEGIN
2568
+ ALTER TABLE memory_relations
2569
+ ADD COLUMN IF NOT EXISTS last_accessed_at TIMESTAMPTZ;
2570
+ EXCEPTION WHEN duplicate_column THEN NULL;
2571
+ END $$;
2572
+
2573
+ -- Inferred relationships table (for transitive closure)
2574
+ CREATE TABLE IF NOT EXISTS memory_inferred_relations (
2575
+ source_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
2576
+ target_id UUID NOT NULL REFERENCES memories(id) ON DELETE CASCADE,
2577
+
2578
+ -- Inference path (how we got here)
2579
+ inference_path UUID[] NOT NULL, -- Path of IDs from source to target
2580
+ hop_count INTEGER NOT NULL, -- Number of hops
2581
+
2582
+ -- Inference details
2583
+ relation_type VARCHAR(50) NOT NULL DEFAULT 'inferred',
2584
+ confidence FLOAT NOT NULL, -- Product of path confidences
2585
+ inference_method VARCHAR(50), -- transitive, similarity, temporal
2586
+
2587
+ -- Timestamps
2588
+ inferred_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2589
+ expires_at TIMESTAMPTZ, -- Inferences can expire
2590
+
2591
+ PRIMARY KEY (source_id, target_id),
2592
+ CONSTRAINT no_self_inference CHECK (source_id != target_id),
2593
+ CONSTRAINT valid_confidence CHECK (confidence >= 0 AND confidence <= 1)
2594
+ );
2595
+
2596
+ CREATE INDEX IF NOT EXISTS idx_inferred_relations_source
2597
+ ON memory_inferred_relations(source_id);
2598
+ CREATE INDEX IF NOT EXISTS idx_inferred_relations_target
2599
+ ON memory_inferred_relations(target_id);
2600
+ CREATE INDEX IF NOT EXISTS idx_inferred_relations_confidence
2601
+ ON memory_inferred_relations(confidence DESC);
2602
+ CREATE INDEX IF NOT EXISTS idx_inferred_relations_expires
2603
+ ON memory_inferred_relations(expires_at)
2604
+ WHERE expires_at IS NOT NULL;
2605
+
2606
+ -- ============================================================
2607
+ -- SPATIAL MEMORY STATS - Materialized view for quick stats
2608
+ -- ============================================================
2609
+ CREATE MATERIALIZED VIEW IF NOT EXISTS spatial_memory_stats AS
2610
+ SELECT
2611
+ (SELECT COUNT(*) FROM semantic_quadrants) as total_quadrants,
2612
+ (SELECT COUNT(*) FROM memory_clusters) as total_clusters,
2613
+ (SELECT COUNT(*) FROM memory_hot_paths) as total_hot_paths,
2614
+ (SELECT COUNT(*) FROM memory_hot_paths WHERE is_cached = true) as cached_hot_paths,
2615
+ (SELECT COUNT(*) FROM memory_access_transitions) as total_transitions,
2616
+ (SELECT AVG(memory_count) FROM semantic_quadrants)::FLOAT as avg_memories_per_quadrant,
2617
+ (SELECT AVG(memory_count) FROM memory_clusters)::FLOAT as avg_memories_per_cluster,
2618
+ (SELECT AVG(heat_score) FROM memory_hot_paths)::FLOAT as avg_heat_score,
2619
+ (SELECT COUNT(*) FROM memory_inferred_relations) as total_inferred_relations,
2620
+ NOW() as computed_at
2621
+ ;
2622
+
2623
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_spatial_memory_stats_singleton
2624
+ ON spatial_memory_stats(computed_at);
2625
+
2626
+ -- Function to refresh spatial stats
2627
+ CREATE OR REPLACE FUNCTION refresh_spatial_memory_stats()
2628
+ RETURNS void AS $$
2629
+ BEGIN
2630
+ REFRESH MATERIALIZED VIEW CONCURRENTLY spatial_memory_stats;
2631
+ END;
2632
+ $$ LANGUAGE plpgsql;
2633
+
2634
+ -- ============================================================
2635
+ -- TRIGGERS for automatic maintenance
2636
+ -- ============================================================
2637
+
2638
+ -- Update quadrant memory count on assignment changes
2639
+ CREATE OR REPLACE FUNCTION update_quadrant_count()
2640
+ RETURNS TRIGGER AS $$
2641
+ BEGIN
2642
+ IF TG_OP = 'INSERT' THEN
2643
+ UPDATE semantic_quadrants
2644
+ SET memory_count = memory_count + 1, updated_at = NOW()
2645
+ WHERE id = NEW.quadrant_id;
2646
+ RETURN NEW;
2647
+ ELSIF TG_OP = 'DELETE' THEN
2648
+ UPDATE semantic_quadrants
2649
+ SET memory_count = memory_count - 1, updated_at = NOW()
2650
+ WHERE id = OLD.quadrant_id;
2651
+ RETURN OLD;
2652
+ END IF;
2653
+ RETURN NULL;
2654
+ END;
2655
+ $$ LANGUAGE plpgsql;
2656
+
2657
+ DROP TRIGGER IF EXISTS quadrant_count_trigger ON memory_quadrant_assignments;
2658
+ CREATE TRIGGER quadrant_count_trigger
2659
+ AFTER INSERT OR DELETE ON memory_quadrant_assignments
2660
+ FOR EACH ROW
2661
+ EXECUTE FUNCTION update_quadrant_count();
2662
+
2663
+ -- Update cluster memory count on assignment changes
2664
+ CREATE OR REPLACE FUNCTION update_cluster_count()
2665
+ RETURNS TRIGGER AS $$
2666
+ BEGIN
2667
+ IF TG_OP = 'INSERT' THEN
2668
+ UPDATE memory_clusters
2669
+ SET memory_count = memory_count + 1, updated_at = NOW()
2670
+ WHERE id = NEW.cluster_id;
2671
+ RETURN NEW;
2672
+ ELSIF TG_OP = 'DELETE' THEN
2673
+ UPDATE memory_clusters
2674
+ SET memory_count = memory_count - 1, updated_at = NOW()
2675
+ WHERE id = OLD.cluster_id;
2676
+ RETURN OLD;
2677
+ END IF;
2678
+ RETURN NULL;
2679
+ END;
2680
+ $$ LANGUAGE plpgsql;
2681
+
2682
+ DROP TRIGGER IF EXISTS cluster_count_trigger ON memory_cluster_assignments;
2683
+ CREATE TRIGGER cluster_count_trigger
2684
+ AFTER INSERT OR DELETE ON memory_cluster_assignments
2685
+ FOR EACH ROW
2686
+ EXECUTE FUNCTION update_cluster_count();
2687
+
2688
+ -- Decay hot path heat scores periodically (run via cron/background job)
2689
+ CREATE OR REPLACE FUNCTION decay_hot_path_heat()
2690
+ RETURNS INTEGER AS $$
2691
+ DECLARE
2692
+ updated_count INTEGER;
2693
+ BEGIN
2694
+ -- Decay factor: multiply by 0.95 for each day since last access
2695
+ UPDATE memory_hot_paths
2696
+ SET heat_score = heat_score * POWER(0.95,
2697
+ EXTRACT(EPOCH FROM (NOW() - COALESCE(last_accessed_at, created_at))) / 86400
2698
+ ),
2699
+ updated_at = NOW()
2700
+ WHERE heat_score > 0.01; -- Don't bother with near-zero scores
2701
+
2702
+ GET DIAGNOSTICS updated_count = ROW_COUNT;
2703
+ RETURN updated_count;
2704
+ END;
2705
+ $$ LANGUAGE plpgsql;
2706
+
2707
+ -- updated_at triggers
2708
+ DROP TRIGGER IF EXISTS semantic_quadrants_updated_at ON semantic_quadrants;
2709
+ CREATE TRIGGER semantic_quadrants_updated_at
2710
+ BEFORE UPDATE ON semantic_quadrants
2711
+ FOR EACH ROW
2712
+ EXECUTE FUNCTION update_updated_at_column();
2713
+
2714
+ DROP TRIGGER IF EXISTS memory_clusters_updated_at ON memory_clusters;
2715
+ CREATE TRIGGER memory_clusters_updated_at
2716
+ BEFORE UPDATE ON memory_clusters
2717
+ FOR EACH ROW
2718
+ EXECUTE FUNCTION update_updated_at_column();
2719
+
2720
+ DROP TRIGGER IF EXISTS memory_hot_paths_updated_at ON memory_hot_paths;
2721
+ CREATE TRIGGER memory_hot_paths_updated_at
2722
+ BEFORE UPDATE ON memory_hot_paths
2723
+ FOR EACH ROW
2724
+ EXECUTE FUNCTION update_updated_at_column();
2725
+
2726
+ DROP TRIGGER IF EXISTS memory_access_transitions_updated_at ON memory_access_transitions;
2727
+ CREATE TRIGGER memory_access_transitions_updated_at
2728
+ BEFORE UPDATE ON memory_access_transitions
2729
+ FOR EACH ROW
2730
+ EXECUTE FUNCTION update_updated_at_column();
2731
+ `,
2732
+ down: `
2733
+ DROP FUNCTION IF EXISTS decay_hot_path_heat();
2734
+ DROP FUNCTION IF EXISTS update_cluster_count();
2735
+ DROP FUNCTION IF EXISTS update_quadrant_count();
2736
+ DROP FUNCTION IF EXISTS refresh_spatial_memory_stats();
2737
+ DROP TRIGGER IF EXISTS memory_access_transitions_updated_at ON memory_access_transitions;
2738
+ DROP TRIGGER IF EXISTS memory_hot_paths_updated_at ON memory_hot_paths;
2739
+ DROP TRIGGER IF EXISTS memory_clusters_updated_at ON memory_clusters;
2740
+ DROP TRIGGER IF EXISTS semantic_quadrants_updated_at ON semantic_quadrants;
2741
+ DROP TRIGGER IF EXISTS cluster_count_trigger ON memory_cluster_assignments;
2742
+ DROP TRIGGER IF EXISTS quadrant_count_trigger ON memory_quadrant_assignments;
2743
+ DROP MATERIALIZED VIEW IF EXISTS spatial_memory_stats;
2744
+ DROP TABLE IF EXISTS memory_inferred_relations CASCADE;
2745
+ DROP TABLE IF EXISTS memory_access_transitions CASCADE;
2746
+ DROP TABLE IF EXISTS memory_hot_paths CASCADE;
2747
+ DROP TABLE IF EXISTS cluster_relations CASCADE;
2748
+ DROP TABLE IF EXISTS memory_cluster_assignments CASCADE;
2749
+ DROP TABLE IF EXISTS memory_clusters CASCADE;
2750
+ DROP TABLE IF EXISTS memory_quadrant_assignments CASCADE;
2751
+ DROP TABLE IF EXISTS semantic_quadrants CASCADE;
2752
+ ALTER TABLE memory_relations DROP COLUMN IF EXISTS relation_category;
2753
+ ALTER TABLE memory_relations DROP COLUMN IF EXISTS confidence;
2754
+ ALTER TABLE memory_relations DROP COLUMN IF EXISTS access_count;
2755
+ ALTER TABLE memory_relations DROP COLUMN IF EXISTS last_accessed_at;
2756
+ `,
2757
+ checksum: this.generateChecksum('create_spatial_memory_tables_v26')
2758
+ },
2759
+ // migration 27: Dashboard Query Optimizations
2760
+ // Adds indexes and materialized views for the SpecMem dashboard
2761
+ // Makes dashboard queries BLAZING fast no cap
2762
+ {
2763
+ version: 27,
2764
+ name: 'dashboard_query_optimizations',
2765
+ up: `
2766
+ -- ============================================================
2767
+ -- DASHBOARD-SPECIFIC INDEXES
2768
+ -- Optimized for common dashboard query patterns
2769
+ -- ============================================================
2770
+
2771
+ -- Composite index for filtered pagination by type + time
2772
+ -- Note: WHERE clause removed - NOW() is not IMMUTABLE and cannot be used in index predicates
2773
+ CREATE INDEX IF NOT EXISTS idx_memories_dashboard_type_time
2774
+ ON memories(memory_type, created_at DESC);
2775
+
2776
+ -- Composite index for importance filtering + time
2777
+ -- Note: WHERE clause removed - NOW() is not IMMUTABLE and cannot be used in index predicates
2778
+ CREATE INDEX IF NOT EXISTS idx_memories_dashboard_importance_time
2779
+ ON memories(importance, created_at DESC);
2780
+
2781
+ -- Index for recent activity queries (last 24h)
2782
+ -- Note: WHERE clause removed - NOW() is not IMMUTABLE and cannot be used in index predicates
2783
+ -- The index still improves performance for time-based queries
2784
+ CREATE INDEX IF NOT EXISTS idx_memories_recent_24h
2785
+ ON memories(created_at DESC);
2786
+
2787
+ -- Covering index for memory list queries (avoids table lookups)
2788
+ -- Includes commonly selected columns for list views
2789
+ -- Note: WHERE clause removed - NOW() is not IMMUTABLE and cannot be used in index predicates
2790
+ CREATE INDEX IF NOT EXISTS idx_memories_dashboard_list
2791
+ ON memories(created_at DESC, id, memory_type, importance)
2792
+ INCLUDE (tags, access_count, updated_at);
2793
+
2794
+ -- Index for tag + type combined filtering
2795
+ CREATE INDEX IF NOT EXISTS idx_memories_tags_type
2796
+ ON memories USING GIN(tags, memory_type);
2797
+
2798
+ -- ============================================================
2799
+ -- ENHANCED MATERIALIZED VIEW FOR DASHBOARD STATS
2800
+ -- More comprehensive than basic memory_stats view
2801
+ -- ============================================================
2802
+
2803
+ DROP MATERIALIZED VIEW IF EXISTS dashboard_stats;
2804
+ CREATE MATERIALIZED VIEW dashboard_stats AS
2805
+ SELECT
2806
+ -- Total counts
2807
+ COUNT(*) as total_memories,
2808
+ COUNT(*) FILTER (WHERE expires_at IS NULL OR expires_at > NOW()) as active_memories,
2809
+
2810
+ -- Type distribution
2811
+ COUNT(*) FILTER (WHERE memory_type = 'episodic') as episodic_count,
2812
+ COUNT(*) FILTER (WHERE memory_type = 'semantic') as semantic_count,
2813
+ COUNT(*) FILTER (WHERE memory_type = 'procedural') as procedural_count,
2814
+ COUNT(*) FILTER (WHERE memory_type = 'working') as working_count,
2815
+ COUNT(*) FILTER (WHERE memory_type = 'consolidated') as consolidated_count,
2816
+
2817
+ -- Importance distribution
2818
+ COUNT(*) FILTER (WHERE importance = 'critical') as critical_count,
2819
+ COUNT(*) FILTER (WHERE importance = 'high') as high_count,
2820
+ COUNT(*) FILTER (WHERE importance = 'medium') as medium_count,
2821
+ COUNT(*) FILTER (WHERE importance = 'low') as low_count,
2822
+ COUNT(*) FILTER (WHERE importance = 'trivial') as trivial_count,
2823
+
2824
+ -- Feature usage
2825
+ COUNT(*) FILTER (WHERE embedding IS NOT NULL) as with_embeddings,
2826
+ COUNT(*) FILTER (WHERE image_data IS NOT NULL) as with_images,
2827
+ COUNT(*) FILTER (WHERE array_length(tags, 1) > 0) as with_tags,
2828
+ COUNT(*) FILTER (WHERE array_length(consolidated_from, 1) > 0) as consolidated,
2829
+
2830
+ -- Expiration stats
2831
+ COUNT(*) FILTER (WHERE expires_at IS NOT NULL AND expires_at < NOW()) as expired_count,
2832
+ COUNT(*) FILTER (WHERE expires_at IS NOT NULL AND expires_at > NOW()) as expiring_soon,
2833
+
2834
+ -- Time-based stats
2835
+ COUNT(*) FILTER (WHERE created_at > NOW() - INTERVAL '24 hours') as created_last_24h,
2836
+ COUNT(*) FILTER (WHERE created_at > NOW() - INTERVAL '7 days') as created_last_7d,
2837
+ COUNT(*) FILTER (WHERE created_at > NOW() - INTERVAL '30 days') as created_last_30d,
2838
+ COUNT(*) FILTER (WHERE updated_at > NOW() - INTERVAL '24 hours') as updated_last_24h,
2839
+
2840
+ -- Aggregates
2841
+ COALESCE(AVG(access_count), 0)::float as avg_access_count,
2842
+ COALESCE(MAX(access_count), 0) as max_access_count,
2843
+ COALESCE(AVG(length(content)), 0)::float as avg_content_length,
2844
+ COALESCE(SUM(length(content)), 0)::bigint as total_content_size,
2845
+
2846
+ -- Time range
2847
+ MIN(created_at) as oldest_memory,
2848
+ MAX(created_at) as newest_memory,
2849
+
2850
+ -- Computed at timestamp
2851
+ NOW() as computed_at
2852
+ FROM memories;
2853
+
2854
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_dashboard_stats_singleton
2855
+ ON dashboard_stats(computed_at);
2856
+
2857
+ -- Function to refresh dashboard stats
2858
+ CREATE OR REPLACE FUNCTION refresh_dashboard_stats()
2859
+ RETURNS void AS $$
2860
+ BEGIN
2861
+ REFRESH MATERIALIZED VIEW CONCURRENTLY dashboard_stats;
2862
+ END;
2863
+ $$ LANGUAGE plpgsql;
2864
+
2865
+ -- ============================================================
2866
+ -- TIME SERIES AGGREGATION TABLE
2867
+ -- Pre-computed daily/weekly/monthly counts for fast charts
2868
+ -- ============================================================
2869
+
2870
+ CREATE TABLE IF NOT EXISTS memory_time_series (
2871
+ id SERIAL PRIMARY KEY,
2872
+ granularity VARCHAR(10) NOT NULL, -- 'hour', 'day', 'week', 'month'
2873
+ period_start TIMESTAMPTZ NOT NULL,
2874
+ period_end TIMESTAMPTZ NOT NULL,
2875
+
2876
+ -- Counts by type
2877
+ total_count INTEGER NOT NULL DEFAULT 0,
2878
+ episodic_count INTEGER DEFAULT 0,
2879
+ semantic_count INTEGER DEFAULT 0,
2880
+ procedural_count INTEGER DEFAULT 0,
2881
+ working_count INTEGER DEFAULT 0,
2882
+ consolidated_count INTEGER DEFAULT 0,
2883
+
2884
+ -- Counts by importance
2885
+ critical_count INTEGER DEFAULT 0,
2886
+ high_count INTEGER DEFAULT 0,
2887
+ medium_count INTEGER DEFAULT 0,
2888
+ low_count INTEGER DEFAULT 0,
2889
+ trivial_count INTEGER DEFAULT 0,
2890
+
2891
+ -- Other metrics
2892
+ with_embeddings INTEGER DEFAULT 0,
2893
+ with_images INTEGER DEFAULT 0,
2894
+ avg_content_length FLOAT,
2895
+
2896
+ -- Metadata
2897
+ computed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
2898
+
2899
+ CONSTRAINT unique_period UNIQUE (granularity, period_start)
2900
+ );
2901
+
2902
+ CREATE INDEX IF NOT EXISTS idx_time_series_lookup
2903
+ ON memory_time_series(granularity, period_start DESC);
2904
+
2905
+ -- Function to populate time series data
2906
+ CREATE OR REPLACE FUNCTION populate_memory_time_series(
2907
+ p_granularity VARCHAR(10),
2908
+ p_days_back INTEGER DEFAULT 90
2909
+ )
2910
+ RETURNS INTEGER AS $$
2911
+ DECLARE
2912
+ inserted_count INTEGER := 0;
2913
+ BEGIN
2914
+ INSERT INTO memory_time_series (
2915
+ granularity, period_start, period_end,
2916
+ total_count, episodic_count, semantic_count, procedural_count, working_count, consolidated_count,
2917
+ critical_count, high_count, medium_count, low_count, trivial_count,
2918
+ with_embeddings, with_images, avg_content_length
2919
+ )
2920
+ SELECT
2921
+ p_granularity,
2922
+ date_trunc(p_granularity, created_at) as period_start,
2923
+ date_trunc(p_granularity, created_at) + CASE
2924
+ WHEN p_granularity = 'hour' THEN INTERVAL '1 hour'
2925
+ WHEN p_granularity = 'day' THEN INTERVAL '1 day'
2926
+ WHEN p_granularity = 'week' THEN INTERVAL '1 week'
2927
+ WHEN p_granularity = 'month' THEN INTERVAL '1 month'
2928
+ END as period_end,
2929
+ COUNT(*),
2930
+ COUNT(*) FILTER (WHERE memory_type = 'episodic'),
2931
+ COUNT(*) FILTER (WHERE memory_type = 'semantic'),
2932
+ COUNT(*) FILTER (WHERE memory_type = 'procedural'),
2933
+ COUNT(*) FILTER (WHERE memory_type = 'working'),
2934
+ COUNT(*) FILTER (WHERE memory_type = 'consolidated'),
2935
+ COUNT(*) FILTER (WHERE importance = 'critical'),
2936
+ COUNT(*) FILTER (WHERE importance = 'high'),
2937
+ COUNT(*) FILTER (WHERE importance = 'medium'),
2938
+ COUNT(*) FILTER (WHERE importance = 'low'),
2939
+ COUNT(*) FILTER (WHERE importance = 'trivial'),
2940
+ COUNT(*) FILTER (WHERE embedding IS NOT NULL),
2941
+ COUNT(*) FILTER (WHERE image_data IS NOT NULL),
2942
+ AVG(length(content))::float
2943
+ FROM memories
2944
+ WHERE created_at > NOW() - (p_days_back || ' days')::INTERVAL
2945
+ GROUP BY date_trunc(p_granularity, created_at)
2946
+ ON CONFLICT (granularity, period_start)
2947
+ DO UPDATE SET
2948
+ total_count = EXCLUDED.total_count,
2949
+ episodic_count = EXCLUDED.episodic_count,
2950
+ semantic_count = EXCLUDED.semantic_count,
2951
+ procedural_count = EXCLUDED.procedural_count,
2952
+ working_count = EXCLUDED.working_count,
2953
+ consolidated_count = EXCLUDED.consolidated_count,
2954
+ critical_count = EXCLUDED.critical_count,
2955
+ high_count = EXCLUDED.high_count,
2956
+ medium_count = EXCLUDED.medium_count,
2957
+ low_count = EXCLUDED.low_count,
2958
+ trivial_count = EXCLUDED.trivial_count,
2959
+ with_embeddings = EXCLUDED.with_embeddings,
2960
+ with_images = EXCLUDED.with_images,
2961
+ avg_content_length = EXCLUDED.avg_content_length,
2962
+ computed_at = NOW();
2963
+
2964
+ GET DIAGNOSTICS inserted_count = ROW_COUNT;
2965
+ RETURN inserted_count;
2966
+ END;
2967
+ $$ LANGUAGE plpgsql;
2968
+
2969
+ -- ============================================================
2970
+ -- TAG STATISTICS TABLE
2971
+ -- Pre-aggregated tag stats for fast dashboard queries
2972
+ -- ============================================================
2973
+
2974
+ CREATE TABLE IF NOT EXISTS tag_statistics (
2975
+ tag_name VARCHAR(255) PRIMARY KEY,
2976
+ memory_count INTEGER NOT NULL DEFAULT 0,
2977
+ first_used TIMESTAMPTZ,
2978
+ last_used TIMESTAMPTZ,
2979
+ avg_importance_rank FLOAT, -- 1=critical, 5=trivial
2980
+ top_memory_types TEXT[],
2981
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
2982
+ );
2983
+
2984
+ CREATE INDEX IF NOT EXISTS idx_tag_stats_count
2985
+ ON tag_statistics(memory_count DESC);
2986
+
2987
+ -- Function to refresh tag statistics
2988
+ CREATE OR REPLACE FUNCTION refresh_tag_statistics()
2989
+ RETURNS INTEGER AS $$
2990
+ DECLARE
2991
+ updated_count INTEGER := 0;
2992
+ BEGIN
2993
+ INSERT INTO tag_statistics (tag_name, memory_count, first_used, last_used, updated_at)
2994
+ SELECT
2995
+ unnest(tags) as tag_name,
2996
+ COUNT(*),
2997
+ MIN(created_at),
2998
+ MAX(created_at),
2999
+ NOW()
3000
+ FROM memories
3001
+ WHERE array_length(tags, 1) > 0
3002
+ GROUP BY unnest(tags)
3003
+ ON CONFLICT (tag_name)
3004
+ DO UPDATE SET
3005
+ memory_count = EXCLUDED.memory_count,
3006
+ first_used = EXCLUDED.first_used,
3007
+ last_used = EXCLUDED.last_used,
3008
+ updated_at = NOW();
3009
+
3010
+ GET DIAGNOSTICS updated_count = ROW_COUNT;
3011
+ RETURN updated_count;
3012
+ END;
3013
+ $$ LANGUAGE plpgsql;
3014
+
3015
+ -- ============================================================
3016
+ -- DASHBOARD CACHE TABLE
3017
+ -- For caching expensive dashboard query results
3018
+ -- ============================================================
3019
+
3020
+ CREATE TABLE IF NOT EXISTS dashboard_cache (
3021
+ cache_key VARCHAR(255) PRIMARY KEY,
3022
+ cache_value JSONB NOT NULL,
3023
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
3024
+ expires_at TIMESTAMPTZ NOT NULL,
3025
+ hit_count INTEGER DEFAULT 0,
3026
+ last_accessed_at TIMESTAMPTZ
3027
+ );
3028
+
3029
+ CREATE INDEX IF NOT EXISTS idx_dashboard_cache_expires
3030
+ ON dashboard_cache(expires_at);
3031
+
3032
+ -- Function to get or set cache
3033
+ CREATE OR REPLACE FUNCTION dashboard_cache_get(
3034
+ p_key VARCHAR(255)
3035
+ )
3036
+ RETURNS JSONB AS $$
3037
+ DECLARE
3038
+ v_result JSONB;
3039
+ BEGIN
3040
+ UPDATE dashboard_cache
3041
+ SET hit_count = hit_count + 1, last_accessed_at = NOW()
3042
+ WHERE cache_key = p_key AND expires_at > NOW()
3043
+ RETURNING cache_value INTO v_result;
3044
+
3045
+ RETURN v_result;
3046
+ END;
3047
+ $$ LANGUAGE plpgsql;
3048
+
3049
+ CREATE OR REPLACE FUNCTION dashboard_cache_set(
3050
+ p_key VARCHAR(255),
3051
+ p_value JSONB,
3052
+ p_ttl_seconds INTEGER DEFAULT 300
3053
+ )
3054
+ RETURNS void AS $$
3055
+ BEGIN
3056
+ INSERT INTO dashboard_cache (cache_key, cache_value, expires_at)
3057
+ VALUES (p_key, p_value, NOW() + (p_ttl_seconds || ' seconds')::INTERVAL)
3058
+ ON CONFLICT (cache_key)
3059
+ DO UPDATE SET
3060
+ cache_value = EXCLUDED.cache_value,
3061
+ expires_at = EXCLUDED.expires_at,
3062
+ created_at = NOW(),
3063
+ hit_count = 0;
3064
+ END;
3065
+ $$ LANGUAGE plpgsql;
3066
+
3067
+ -- Cleanup expired cache entries
3068
+ CREATE OR REPLACE FUNCTION dashboard_cache_cleanup()
3069
+ RETURNS INTEGER AS $$
3070
+ DECLARE
3071
+ deleted_count INTEGER;
3072
+ BEGIN
3073
+ DELETE FROM dashboard_cache WHERE expires_at < NOW();
3074
+ GET DIAGNOSTICS deleted_count = ROW_COUNT;
3075
+ RETURN deleted_count;
3076
+ END;
3077
+ $$ LANGUAGE plpgsql;
3078
+
3079
+ -- Initial population
3080
+ SELECT populate_memory_time_series('day', 90);
3081
+ SELECT populate_memory_time_series('week', 365);
3082
+ SELECT refresh_tag_statistics();
3083
+ `,
3084
+ down: `
3085
+ DROP FUNCTION IF EXISTS dashboard_cache_cleanup();
3086
+ DROP FUNCTION IF EXISTS dashboard_cache_set(VARCHAR, JSONB, INTEGER);
3087
+ DROP FUNCTION IF EXISTS dashboard_cache_get(VARCHAR);
3088
+ DROP TABLE IF EXISTS dashboard_cache CASCADE;
3089
+ DROP FUNCTION IF EXISTS refresh_tag_statistics();
3090
+ DROP TABLE IF EXISTS tag_statistics CASCADE;
3091
+ DROP FUNCTION IF EXISTS populate_memory_time_series(VARCHAR, INTEGER);
3092
+ DROP TABLE IF EXISTS memory_time_series CASCADE;
3093
+ DROP FUNCTION IF EXISTS refresh_dashboard_stats();
3094
+ DROP MATERIALIZED VIEW IF EXISTS dashboard_stats;
3095
+ DROP INDEX IF EXISTS idx_memories_tags_type;
3096
+ DROP INDEX IF EXISTS idx_memories_dashboard_list;
3097
+ DROP INDEX IF EXISTS idx_memories_recent_24h;
3098
+ DROP INDEX IF EXISTS idx_memories_dashboard_importance_time;
3099
+ DROP INDEX IF EXISTS idx_memories_dashboard_type_time;
3100
+ `,
3101
+ checksum: this.generateChecksum('dashboard_query_optimizations_v27')
3102
+ },
3103
+ // migration 28: API Endpoint Data Migration
3104
+ // Moves all JSON-based API data storage to PostgreSQL
3105
+ // Includes: endpoints, bans, oauth, security events, admin sessions
3106
+ {
3107
+ version: 28,
3108
+ name: 'create_api_data_tables',
3109
+ up: `
3110
+ -- ============================================================
3111
+ -- API ENDPOINTS TABLE
3112
+ -- Stores endpoint configuration, rate limits, and access control
3113
+ -- Replaces data/api-endpoints/endpoints.json
3114
+ -- ============================================================
3115
+ CREATE TABLE IF NOT EXISTS api_endpoints (
3116
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
3117
+
3118
+ -- Endpoint identification
3119
+ path VARCHAR(500) NOT NULL,
3120
+ method VARCHAR(10) NOT NULL DEFAULT 'GET',
3121
+ name VARCHAR(255) NOT NULL,
3122
+ description TEXT,
3123
+
3124
+ -- Rate limiting configuration
3125
+ rate_limit_max INTEGER NOT NULL DEFAULT 100,
3126
+ rate_limit_window_ms INTEGER NOT NULL DEFAULT 60000,
3127
+ rate_limit_skip_localhost BOOLEAN DEFAULT true,
3128
+
3129
+ -- Authentication and access control
3130
+ requires_auth BOOLEAN DEFAULT true,
3131
+ allowed_roles TEXT[] DEFAULT '{}',
3132
+ allowed_ips TEXT[] DEFAULT '{}',
3133
+ blocked_ips TEXT[] DEFAULT '{}',
3134
+
3135
+ -- Status and monitoring
3136
+ is_enabled BOOLEAN DEFAULT true,
3137
+ is_deprecated BOOLEAN DEFAULT false,
3138
+ deprecation_message TEXT,
3139
+
3140
+ -- Usage statistics
3141
+ total_requests BIGINT DEFAULT 0,
3142
+ successful_requests BIGINT DEFAULT 0,
3143
+ failed_requests BIGINT DEFAULT 0,
3144
+ last_request_at TIMESTAMPTZ,
3145
+
3146
+ -- Metadata
3147
+ tags TEXT[] DEFAULT '{}',
3148
+ metadata JSONB NOT NULL DEFAULT '{}',
3149
+
3150
+ -- Timestamps
3151
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
3152
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
3153
+
3154
+ -- Constraints
3155
+ CONSTRAINT valid_method CHECK (
3156
+ method IN ('GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD')
3157
+ ),
3158
+ CONSTRAINT unique_endpoint UNIQUE (path, method)
3159
+ );
3160
+
3161
+ -- Indexes for endpoint lookups
3162
+ CREATE INDEX IF NOT EXISTS idx_api_endpoints_path
3163
+ ON api_endpoints(path);
3164
+ CREATE INDEX IF NOT EXISTS idx_api_endpoints_method
3165
+ ON api_endpoints(method);
3166
+ CREATE INDEX IF NOT EXISTS idx_api_endpoints_enabled
3167
+ ON api_endpoints(is_enabled)
3168
+ WHERE is_enabled = true;
3169
+ CREATE INDEX IF NOT EXISTS idx_api_endpoints_auth
3170
+ ON api_endpoints(requires_auth);
3171
+ CREATE INDEX IF NOT EXISTS idx_api_endpoints_tags
3172
+ ON api_endpoints USING GIN(tags);
3173
+
3174
+ -- Trigger for updated_at
3175
+ DROP TRIGGER IF EXISTS api_endpoints_updated_at ON api_endpoints;
3176
+ CREATE TRIGGER api_endpoints_updated_at
3177
+ BEFORE UPDATE ON api_endpoints
3178
+ FOR EACH ROW
3179
+ EXECUTE FUNCTION update_updated_at_column();
3180
+
3181
+ -- ============================================================
3182
+ -- BANS TABLE
3183
+ -- Stores IP bans and autoban configuration
3184
+ -- Replaces data/bans/data.json and data/bans/autoban-config.json
3185
+ -- ============================================================
3186
+ CREATE TABLE IF NOT EXISTS ip_bans (
3187
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
3188
+
3189
+ -- Ban identification
3190
+ ip_address VARCHAR(45) NOT NULL, -- Supports IPv4 and IPv6
3191
+ ip_range VARCHAR(50), -- CIDR notation for range bans
3192
+
3193
+ -- Ban details
3194
+ reason TEXT NOT NULL,
3195
+ ban_type VARCHAR(50) NOT NULL DEFAULT 'manual',
3196
+ severity VARCHAR(20) DEFAULT 'medium',
3197
+
3198
+ -- Duration
3199
+ is_permanent BOOLEAN DEFAULT false,
3200
+ expires_at TIMESTAMPTZ,
3201
+
3202
+ -- Context
3203
+ user_agent TEXT,
3204
+ fingerprint VARCHAR(255),
3205
+ country VARCHAR(100),
3206
+
3207
+ -- Violation tracking
3208
+ violation_count INTEGER DEFAULT 1,
3209
+ violations JSONB DEFAULT '[]',
3210
+
3211
+ -- Status
3212
+ is_active BOOLEAN DEFAULT true,
3213
+ lifted_at TIMESTAMPTZ,
3214
+ lifted_by VARCHAR(255),
3215
+ lift_reason TEXT,
3216
+
3217
+ -- Metadata
3218
+ metadata JSONB NOT NULL DEFAULT '{}',
3219
+
3220
+ -- Timestamps
3221
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
3222
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
3223
+
3224
+ -- Constraints
3225
+ CONSTRAINT valid_ban_type CHECK (
3226
+ ban_type IN ('manual', 'auto', 'vpn', 'rate_limit', 'security', 'abuse')
3227
+ ),
3228
+ CONSTRAINT valid_severity CHECK (
3229
+ severity IN ('low', 'medium', 'high', 'critical')
3230
+ )
3231
+ );
3232
+
3233
+ -- Indexes for ban lookups
3234
+ CREATE INDEX IF NOT EXISTS idx_ip_bans_ip
3235
+ ON ip_bans(ip_address);
3236
+ CREATE INDEX IF NOT EXISTS idx_ip_bans_active
3237
+ ON ip_bans(is_active)
3238
+ WHERE is_active = true;
3239
+ CREATE INDEX IF NOT EXISTS idx_ip_bans_expires
3240
+ ON ip_bans(expires_at)
3241
+ WHERE expires_at IS NOT NULL AND is_active = true;
3242
+ CREATE INDEX IF NOT EXISTS idx_ip_bans_type
3243
+ ON ip_bans(ban_type);
3244
+ CREATE INDEX IF NOT EXISTS idx_ip_bans_created
3245
+ ON ip_bans(created_at DESC);
3246
+
3247
+ -- Trigger for updated_at
3248
+ DROP TRIGGER IF EXISTS ip_bans_updated_at ON ip_bans;
3249
+ CREATE TRIGGER ip_bans_updated_at
3250
+ BEFORE UPDATE ON ip_bans
3251
+ FOR EACH ROW
3252
+ EXECUTE FUNCTION update_updated_at_column();
3253
+
3254
+ -- Autoban configuration table
3255
+ CREATE TABLE IF NOT EXISTS autoban_config (
3256
+ id SERIAL PRIMARY KEY,
3257
+
3258
+ -- Configuration
3259
+ is_enabled BOOLEAN DEFAULT true,
3260
+ threshold INTEGER NOT NULL DEFAULT 10,
3261
+ duration_ms INTEGER NOT NULL DEFAULT 300000,
3262
+ window_ms INTEGER NOT NULL DEFAULT 86400000,
3263
+
3264
+ -- Violation types to track
3265
+ tracked_violations TEXT[] DEFAULT ARRAY['vpn', 'rate_limit', 'security'],
3266
+
3267
+ -- Exclusions
3268
+ excluded_ips TEXT[] DEFAULT '{}',
3269
+ excluded_countries TEXT[] DEFAULT '{}',
3270
+
3271
+ -- Metadata
3272
+ metadata JSONB NOT NULL DEFAULT '{}',
3273
+
3274
+ -- Timestamps
3275
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
3276
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
3277
+ );
3278
+
3279
+ -- Trigger for updated_at
3280
+ DROP TRIGGER IF EXISTS autoban_config_updated_at ON autoban_config;
3281
+ CREATE TRIGGER autoban_config_updated_at
3282
+ BEFORE UPDATE ON autoban_config
3283
+ FOR EACH ROW
3284
+ EXECUTE FUNCTION update_updated_at_column();
3285
+
3286
+ -- Insert default autoban config
3287
+ INSERT INTO autoban_config (is_enabled, threshold, duration_ms, window_ms)
3288
+ VALUES (true, 10, 300000, 86400000)
3289
+ ON CONFLICT DO NOTHING;
3290
+
3291
+ -- ============================================================
3292
+ -- OAUTH PROVIDERS TABLE
3293
+ -- Stores OAuth provider configurations
3294
+ -- Replaces data/oauth/providers.json
3295
+ -- ============================================================
3296
+ CREATE TABLE IF NOT EXISTS oauth_providers (
3297
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
3298
+
3299
+ -- Provider identification
3300
+ provider_name VARCHAR(100) NOT NULL UNIQUE,
3301
+ display_name VARCHAR(255),
3302
+
3303
+ -- OAuth configuration (encrypted in application layer)
3304
+ client_id TEXT,
3305
+ client_secret_encrypted TEXT,
3306
+ authorization_url TEXT,
3307
+ token_url TEXT,
3308
+ userinfo_url TEXT,
3309
+ scope TEXT DEFAULT 'openid profile email',
3310
+
3311
+ -- Provider settings
3312
+ is_enabled BOOLEAN DEFAULT false,
3313
+ is_configured BOOLEAN DEFAULT false,
3314
+
3315
+ -- Callback configuration
3316
+ redirect_uri TEXT,
3317
+
3318
+ -- Metadata
3319
+ icon_url TEXT,
3320
+ metadata JSONB NOT NULL DEFAULT '{}',
3321
+
3322
+ -- Timestamps
3323
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
3324
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
3325
+ );
3326
+
3327
+ -- Trigger for updated_at
3328
+ DROP TRIGGER IF EXISTS oauth_providers_updated_at ON oauth_providers;
3329
+ CREATE TRIGGER oauth_providers_updated_at
3330
+ BEFORE UPDATE ON oauth_providers
3331
+ FOR EACH ROW
3332
+ EXECUTE FUNCTION update_updated_at_column();
3333
+
3334
+ -- ============================================================
3335
+ -- SECURITY EVENTS TABLE
3336
+ -- Stores VPN violations, security events, and audit logs
3337
+ -- Replaces data/events/vpn.json and data/vpn_violations/*.json
3338
+ -- ============================================================
3339
+ CREATE TABLE IF NOT EXISTS security_events (
3340
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
3341
+
3342
+ -- Event identification
3343
+ event_type VARCHAR(50) NOT NULL,
3344
+ event_action VARCHAR(255) NOT NULL,
3345
+ category VARCHAR(50) NOT NULL DEFAULT 'violation',
3346
+
3347
+ -- Source identification
3348
+ ip_address VARCHAR(45),
3349
+ user_agent TEXT,
3350
+ fingerprint VARCHAR(255),
3351
+ session_id VARCHAR(255),
3352
+
3353
+ -- Event details
3354
+ details JSONB NOT NULL DEFAULT '{}',
3355
+
3356
+ -- Classification
3357
+ severity VARCHAR(20) NOT NULL DEFAULT 'medium',
3358
+ threat_score INTEGER DEFAULT 0,
3359
+
3360
+ -- Geographic info
3361
+ country VARCHAR(100),
3362
+ region VARCHAR(255),
3363
+ city VARCHAR(255),
3364
+
3365
+ -- Detection flags
3366
+ is_vpn BOOLEAN DEFAULT false,
3367
+ is_proxy BOOLEAN DEFAULT false,
3368
+ is_tor BOOLEAN DEFAULT false,
3369
+ is_data_center BOOLEAN DEFAULT false,
3370
+ is_government BOOLEAN DEFAULT false,
3371
+ is_federal_facility BOOLEAN DEFAULT false,
3372
+
3373
+ -- Resolution
3374
+ is_resolved BOOLEAN DEFAULT false,
3375
+ resolved_at TIMESTAMPTZ,
3376
+ resolved_by VARCHAR(255),
3377
+ resolution_notes TEXT,
3378
+
3379
+ -- Metadata
3380
+ metadata JSONB NOT NULL DEFAULT '{}',
3381
+
3382
+ -- Timestamps
3383
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
3384
+
3385
+ -- Constraints
3386
+ CONSTRAINT valid_event_category CHECK (
3387
+ category IN ('violation', 'warning', 'info', 'audit', 'error')
3388
+ ),
3389
+ CONSTRAINT valid_event_severity CHECK (
3390
+ severity IN ('low', 'medium', 'high', 'critical')
3391
+ )
3392
+ );
3393
+
3394
+ -- Indexes for security event queries
3395
+ CREATE INDEX IF NOT EXISTS idx_security_events_type
3396
+ ON security_events(event_type);
3397
+ CREATE INDEX IF NOT EXISTS idx_security_events_category
3398
+ ON security_events(category);
3399
+ CREATE INDEX IF NOT EXISTS idx_security_events_ip
3400
+ ON security_events(ip_address)
3401
+ WHERE ip_address IS NOT NULL;
3402
+ CREATE INDEX IF NOT EXISTS idx_security_events_severity
3403
+ ON security_events(severity);
3404
+ CREATE INDEX IF NOT EXISTS idx_security_events_created
3405
+ ON security_events(created_at DESC);
3406
+ CREATE INDEX IF NOT EXISTS idx_security_events_vpn
3407
+ ON security_events(is_vpn)
3408
+ WHERE is_vpn = true;
3409
+ CREATE INDEX IF NOT EXISTS idx_security_events_unresolved
3410
+ ON security_events(is_resolved, created_at DESC)
3411
+ WHERE is_resolved = false;
3412
+ CREATE INDEX IF NOT EXISTS idx_security_events_details
3413
+ ON security_events USING GIN(details jsonb_path_ops);
3414
+
3415
+ -- Partitioning for security events (by month for efficient cleanup)
3416
+ -- Note: Partitioning requires PostgreSQL 10+
3417
+
3418
+ -- ============================================================
3419
+ -- ADMIN SESSIONS TABLE
3420
+ -- Stores admin session data
3421
+ -- Replaces data/admin_sessions/data.json
3422
+ -- ============================================================
3423
+ CREATE TABLE IF NOT EXISTS admin_sessions (
3424
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
3425
+
3426
+ -- Session identification
3427
+ session_token VARCHAR(255) NOT NULL UNIQUE,
3428
+
3429
+ -- User identification
3430
+ username VARCHAR(255),
3431
+ ip_address VARCHAR(45),
3432
+ user_agent TEXT,
3433
+
3434
+ -- Session details
3435
+ is_active BOOLEAN DEFAULT true,
3436
+
3437
+ -- Timestamps
3438
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
3439
+ last_activity_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
3440
+ expires_at TIMESTAMPTZ,
3441
+ ended_at TIMESTAMPTZ,
3442
+
3443
+ -- Session data
3444
+ session_data JSONB NOT NULL DEFAULT '{}'
3445
+ );
3446
+
3447
+ -- Indexes for admin session queries
3448
+ CREATE INDEX IF NOT EXISTS idx_admin_sessions_token
3449
+ ON admin_sessions(session_token);
3450
+ CREATE INDEX IF NOT EXISTS idx_admin_sessions_active
3451
+ ON admin_sessions(is_active)
3452
+ WHERE is_active = true;
3453
+ CREATE INDEX IF NOT EXISTS idx_admin_sessions_expires
3454
+ ON admin_sessions(expires_at)
3455
+ WHERE expires_at IS NOT NULL;
3456
+
3457
+ -- ============================================================
3458
+ -- GOVERNMENT FACILITIES TABLE
3459
+ -- Stores known government IP ranges and facilities
3460
+ -- Replaces data/security/government-facilities.json
3461
+ -- ============================================================
3462
+ CREATE TABLE IF NOT EXISTS government_facilities (
3463
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
3464
+
3465
+ -- Facility identification
3466
+ name VARCHAR(255) NOT NULL,
3467
+ facility_type VARCHAR(100),
3468
+ country VARCHAR(100),
3469
+
3470
+ -- IP ranges
3471
+ ip_ranges TEXT[] DEFAULT '{}',
3472
+
3473
+ -- Classification
3474
+ classification VARCHAR(50) DEFAULT 'government',
3475
+ threat_level VARCHAR(20) DEFAULT 'high',
3476
+
3477
+ -- Detection settings
3478
+ should_block BOOLEAN DEFAULT false,
3479
+ should_log BOOLEAN DEFAULT true,
3480
+ alert_on_access BOOLEAN DEFAULT true,
3481
+
3482
+ -- Metadata
3483
+ metadata JSONB NOT NULL DEFAULT '{}',
3484
+
3485
+ -- Timestamps
3486
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
3487
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
3488
+ );
3489
+
3490
+ -- Trigger for updated_at
3491
+ DROP TRIGGER IF EXISTS government_facilities_updated_at ON government_facilities;
3492
+ CREATE TRIGGER government_facilities_updated_at
3493
+ BEFORE UPDATE ON government_facilities
3494
+ FOR EACH ROW
3495
+ EXECUTE FUNCTION update_updated_at_column();
3496
+
3497
+ -- ============================================================
3498
+ -- API STATS MATERIALIZED VIEW
3499
+ -- Pre-computed statistics for API usage
3500
+ -- ============================================================
3501
+ CREATE MATERIALIZED VIEW IF NOT EXISTS api_stats AS
3502
+ SELECT
3503
+ COUNT(*) as total_endpoints,
3504
+ COUNT(*) FILTER (WHERE is_enabled = true) as enabled_endpoints,
3505
+ COUNT(*) FILTER (WHERE requires_auth = true) as auth_required_endpoints,
3506
+ COUNT(*) FILTER (WHERE is_deprecated = true) as deprecated_endpoints,
3507
+ SUM(total_requests) as total_api_requests,
3508
+ SUM(successful_requests) as total_successful_requests,
3509
+ SUM(failed_requests) as total_failed_requests,
3510
+ MAX(last_request_at) as last_api_request,
3511
+ NOW() as computed_at
3512
+ FROM api_endpoints;
3513
+
3514
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_api_stats_singleton
3515
+ ON api_stats(computed_at);
3516
+
3517
+ -- Function to refresh API stats
3518
+ CREATE OR REPLACE FUNCTION refresh_api_stats()
3519
+ RETURNS void AS $$
3520
+ BEGIN
3521
+ REFRESH MATERIALIZED VIEW CONCURRENTLY api_stats;
3522
+ END;
3523
+ $$ LANGUAGE plpgsql;
3524
+
3525
+ -- ============================================================
3526
+ -- SECURITY STATS MATERIALIZED VIEW
3527
+ -- Pre-computed security event statistics
3528
+ -- ============================================================
3529
+ CREATE MATERIALIZED VIEW IF NOT EXISTS security_stats AS
3530
+ SELECT
3531
+ COUNT(*) as total_events,
3532
+ COUNT(*) FILTER (WHERE event_type = 'vpn') as vpn_events,
3533
+ COUNT(*) FILTER (WHERE severity = 'critical') as critical_events,
3534
+ COUNT(*) FILTER (WHERE severity = 'high') as high_severity_events,
3535
+ COUNT(*) FILTER (WHERE is_resolved = false) as unresolved_events,
3536
+ COUNT(*) FILTER (WHERE created_at > NOW() - INTERVAL '24 hours') as events_last_24h,
3537
+ COUNT(*) FILTER (WHERE created_at > NOW() - INTERVAL '7 days') as events_last_7d,
3538
+ COUNT(DISTINCT ip_address) as unique_ips,
3539
+ COUNT(DISTINCT country) as unique_countries,
3540
+ NOW() as computed_at
3541
+ FROM security_events;
3542
+
3543
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_security_stats_singleton
3544
+ ON security_stats(computed_at);
3545
+
3546
+ -- Function to refresh security stats
3547
+ CREATE OR REPLACE FUNCTION refresh_security_stats()
3548
+ RETURNS void AS $$
3549
+ BEGIN
3550
+ REFRESH MATERIALIZED VIEW CONCURRENTLY security_stats;
3551
+ END;
3552
+ $$ LANGUAGE plpgsql;
3553
+
3554
+ -- ============================================================
3555
+ -- BAN STATS MATERIALIZED VIEW
3556
+ -- Pre-computed ban statistics
3557
+ -- ============================================================
3558
+ CREATE MATERIALIZED VIEW IF NOT EXISTS ban_stats AS
3559
+ SELECT
3560
+ COUNT(*) as total_bans,
3561
+ COUNT(*) FILTER (WHERE is_active = true) as active_bans,
3562
+ COUNT(*) FILTER (WHERE is_permanent = true) as permanent_bans,
3563
+ COUNT(*) FILTER (WHERE ban_type = 'auto') as auto_bans,
3564
+ COUNT(*) FILTER (WHERE ban_type = 'manual') as manual_bans,
3565
+ COUNT(*) FILTER (WHERE ban_type = 'vpn') as vpn_bans,
3566
+ COUNT(*) FILTER (WHERE created_at > NOW() - INTERVAL '24 hours') as bans_last_24h,
3567
+ COUNT(*) FILTER (WHERE created_at > NOW() - INTERVAL '7 days') as bans_last_7d,
3568
+ NOW() as computed_at
3569
+ FROM ip_bans;
3570
+
3571
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_ban_stats_singleton
3572
+ ON ban_stats(computed_at);
3573
+
3574
+ -- Function to refresh ban stats
3575
+ CREATE OR REPLACE FUNCTION refresh_ban_stats()
3576
+ RETURNS void AS $$
3577
+ BEGIN
3578
+ REFRESH MATERIALIZED VIEW CONCURRENTLY ban_stats;
3579
+ END;
3580
+ $$ LANGUAGE plpgsql;
3581
+
3582
+ -- ============================================================
3583
+ -- CLEANUP FUNCTION FOR EXPIRED DATA
3584
+ -- ============================================================
3585
+ CREATE OR REPLACE FUNCTION cleanup_expired_api_data()
3586
+ RETURNS TABLE(
3587
+ expired_bans INTEGER,
3588
+ expired_sessions INTEGER,
3589
+ old_events INTEGER
3590
+ ) AS $$
3591
+ DECLARE
3592
+ v_bans INTEGER;
3593
+ v_sessions INTEGER;
3594
+ v_events INTEGER;
3595
+ BEGIN
3596
+ -- Deactivate expired bans
3597
+ UPDATE ip_bans
3598
+ SET is_active = false, updated_at = NOW()
3599
+ WHERE is_active = true
3600
+ AND is_permanent = false
3601
+ AND expires_at IS NOT NULL
3602
+ AND expires_at < NOW();
3603
+ GET DIAGNOSTICS v_bans = ROW_COUNT;
3604
+
3605
+ -- End expired admin sessions
3606
+ UPDATE admin_sessions
3607
+ SET is_active = false, ended_at = NOW()
3608
+ WHERE is_active = true
3609
+ AND expires_at IS NOT NULL
3610
+ AND expires_at < NOW();
3611
+ GET DIAGNOSTICS v_sessions = ROW_COUNT;
3612
+
3613
+ -- Delete very old security events (> 90 days) that are resolved
3614
+ DELETE FROM security_events
3615
+ WHERE is_resolved = true
3616
+ AND created_at < NOW() - INTERVAL '90 days';
3617
+ GET DIAGNOSTICS v_events = ROW_COUNT;
3618
+
3619
+ RETURN QUERY SELECT v_bans, v_sessions, v_events;
3620
+ END;
3621
+ $$ LANGUAGE plpgsql;
3622
+ `,
3623
+ down: `
3624
+ DROP FUNCTION IF EXISTS cleanup_expired_api_data();
3625
+ DROP FUNCTION IF EXISTS refresh_ban_stats();
3626
+ DROP MATERIALIZED VIEW IF EXISTS ban_stats;
3627
+ DROP FUNCTION IF EXISTS refresh_security_stats();
3628
+ DROP MATERIALIZED VIEW IF EXISTS security_stats;
3629
+ DROP FUNCTION IF EXISTS refresh_api_stats();
3630
+ DROP MATERIALIZED VIEW IF EXISTS api_stats;
3631
+ DROP TRIGGER IF EXISTS government_facilities_updated_at ON government_facilities;
3632
+ DROP TABLE IF EXISTS government_facilities CASCADE;
3633
+ DROP TABLE IF EXISTS admin_sessions CASCADE;
3634
+ DROP TABLE IF EXISTS security_events CASCADE;
3635
+ DROP TRIGGER IF EXISTS oauth_providers_updated_at ON oauth_providers;
3636
+ DROP TABLE IF EXISTS oauth_providers CASCADE;
3637
+ DROP TRIGGER IF EXISTS autoban_config_updated_at ON autoban_config;
3638
+ DROP TABLE IF EXISTS autoban_config CASCADE;
3639
+ DROP TRIGGER IF EXISTS ip_bans_updated_at ON ip_bans;
3640
+ DROP TABLE IF EXISTS ip_bans CASCADE;
3641
+ DROP TRIGGER IF EXISTS api_endpoints_updated_at ON api_endpoints;
3642
+ DROP TABLE IF EXISTS api_endpoints CASCADE;
3643
+ `,
3644
+ checksum: this.generateChecksum('create_api_data_tables_v28')
3645
+ },
3646
+ // migration 29: Add unique constraint on codebase_files.absolute_path
3647
+ // Prevents duplicate entries for the same file path
3648
+ {
3649
+ version: 29,
3650
+ name: 'add_codebase_files_absolute_path_unique',
3651
+ up: `
3652
+ -- Remove any duplicate entries first (keep the most recently updated one)
3653
+ DELETE FROM codebase_files a USING codebase_files b
3654
+ WHERE a.id < b.id AND a.absolute_path = b.absolute_path;
3655
+
3656
+ -- Create unique index on absolute_path to prevent duplicates
3657
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_codebase_files_absolute_path_unique
3658
+ ON codebase_files(absolute_path);
3659
+ `,
3660
+ down: `
3661
+ DROP INDEX IF EXISTS idx_codebase_files_absolute_path_unique;
3662
+ `,
3663
+ checksum: this.generateChecksum('add_codebase_files_absolute_path_unique_v29')
3664
+ },
3665
+ // migration 30: Add indexes for session pairing metadata fields
3666
+ // Required for efficient find_memory Strategies 1-8 (user/claude message pairing)
3667
+ {
3668
+ version: 30,
3669
+ name: 'add_session_pairing_indexes',
3670
+ up: `
3671
+ -- Index for sessionId lookups (Strategy 1: same session pairing)
3672
+ CREATE INDEX IF NOT EXISTS idx_memories_metadata_session_id
3673
+ ON memories ((metadata->>'sessionId'))
3674
+ WHERE metadata->>'sessionId' IS NOT NULL;
3675
+
3676
+ -- Index for role filtering (all strategies use role filtering)
3677
+ CREATE INDEX IF NOT EXISTS idx_memories_metadata_role
3678
+ ON memories ((metadata->>'role'))
3679
+ WHERE metadata->>'role' IS NOT NULL;
3680
+
3681
+ -- Index for timestamp ordering (Strategies 1-8 use timestamp-based ordering)
3682
+ CREATE INDEX IF NOT EXISTS idx_memories_metadata_timestamp
3683
+ ON memories ((metadata->>'timestamp'))
3684
+ WHERE metadata->>'timestamp' IS NOT NULL;
3685
+
3686
+ -- Index for project_path filtering (Strategies 2-6 use project_path)
3687
+ CREATE INDEX IF NOT EXISTS idx_memories_metadata_project_path
3688
+ ON memories ((metadata->>'project_path'))
3689
+ WHERE metadata->>'project_path' IS NOT NULL;
3690
+
3691
+ -- Composite index for efficient session+role+timestamp queries (Strategy 1)
3692
+ CREATE INDEX IF NOT EXISTS idx_memories_session_role_timestamp
3693
+ ON memories (
3694
+ (metadata->>'sessionId'),
3695
+ (metadata->>'role'),
3696
+ (metadata->>'timestamp')
3697
+ )
3698
+ WHERE metadata->>'sessionId' IS NOT NULL
3699
+ AND metadata->>'role' IS NOT NULL
3700
+ AND metadata->>'timestamp' IS NOT NULL;
3701
+
3702
+ -- Composite index for project+role+timestamp queries (Strategies 2-6)
3703
+ CREATE INDEX IF NOT EXISTS idx_memories_project_role_timestamp
3704
+ ON memories (
3705
+ (metadata->>'project_path'),
3706
+ (metadata->>'role'),
3707
+ (metadata->>'timestamp')
3708
+ )
3709
+ WHERE metadata->>'project_path' IS NOT NULL
3710
+ AND metadata->>'role' IS NOT NULL
3711
+ AND metadata->>'timestamp' IS NOT NULL;
3712
+ `,
3713
+ down: `
3714
+ DROP INDEX IF EXISTS idx_memories_project_role_timestamp;
3715
+ DROP INDEX IF EXISTS idx_memories_session_role_timestamp;
3716
+ DROP INDEX IF EXISTS idx_memories_metadata_project_path;
3717
+ DROP INDEX IF EXISTS idx_memories_metadata_timestamp;
3718
+ DROP INDEX IF EXISTS idx_memories_metadata_role;
3719
+ DROP INDEX IF EXISTS idx_memories_metadata_session_id;
3720
+ `,
3721
+ checksum: this.generateChecksum('add_session_pairing_indexes_v30')
3722
+ },
3723
+ // migration 31: Project Namespacing - Per-Instance Database Isolation
3724
+ // Adds project_id FK column to ALL data tables for multi-project isolation
3725
+ // CRITICAL: This enables separate SpecMem instances to share one PostgreSQL
3726
+ // without leaking memories, team messages, or claims across projects
3727
+ {
3728
+ version: 31,
3729
+ name: 'project_namespacing_isolation',
3730
+ up: `
3731
+ -- ============================================================================
3732
+ -- PROJECTS REGISTRY TABLE
3733
+ -- ============================================================================
3734
+ -- Central registry mapping project paths to UUIDs
3735
+ -- Uses UPSERT pattern for race-condition-free registration
3736
+ CREATE TABLE IF NOT EXISTS projects (
3737
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
3738
+ path VARCHAR(500) NOT NULL UNIQUE,
3739
+ name VARCHAR(255),
3740
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
3741
+ last_accessed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
3742
+ );
3743
+
3744
+ CREATE INDEX IF NOT EXISTS idx_projects_path ON projects(path);
3745
+ CREATE INDEX IF NOT EXISTS idx_projects_created_at ON projects(created_at);
3746
+
3747
+ -- Insert default project for backfilling existing data
3748
+ INSERT INTO projects (id, path, name, created_at, last_accessed_at)
3749
+ VALUES (
3750
+ '00000000-0000-0000-0000-000000000000'::uuid,
3751
+ '/',
3752
+ 'Default Project',
3753
+ NOW(),
3754
+ NOW()
3755
+ )
3756
+ ON CONFLICT (path) DO NOTHING;
3757
+
3758
+ -- ============================================================================
3759
+ -- ADD project_id TO memories TABLE
3760
+ -- ============================================================================
3761
+ DO $$ BEGIN
3762
+ ALTER TABLE memories
3763
+ ADD COLUMN IF NOT EXISTS project_id UUID DEFAULT '00000000-0000-0000-0000-000000000000'::uuid;
3764
+ EXCEPTION WHEN duplicate_column THEN NULL;
3765
+ END $$;
3766
+
3767
+ DO $$ BEGIN
3768
+ ALTER TABLE memories
3769
+ ADD CONSTRAINT fk_memories_project_id
3770
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET DEFAULT;
3771
+ EXCEPTION WHEN duplicate_object THEN NULL;
3772
+ END $$;
3773
+
3774
+ CREATE INDEX IF NOT EXISTS idx_memories_project_id ON memories(project_id);
3775
+ CREATE INDEX IF NOT EXISTS idx_memories_project_created ON memories(project_id, created_at DESC);
3776
+ CREATE INDEX IF NOT EXISTS idx_memories_project_importance ON memories(project_id, importance);
3777
+
3778
+ -- ============================================================================
3779
+ -- ADD project_id TO codebase_files TABLE
3780
+ -- ============================================================================
3781
+ DO $$ BEGIN
3782
+ ALTER TABLE codebase_files
3783
+ ADD COLUMN IF NOT EXISTS project_id UUID DEFAULT '00000000-0000-0000-0000-000000000000'::uuid;
3784
+ EXCEPTION WHEN duplicate_column THEN NULL;
3785
+ END $$;
3786
+
3787
+ DO $$ BEGIN
3788
+ ALTER TABLE codebase_files
3789
+ ADD CONSTRAINT fk_codebase_files_project_id
3790
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET DEFAULT;
3791
+ EXCEPTION WHEN duplicate_object THEN NULL;
3792
+ END $$;
3793
+
3794
+ CREATE INDEX IF NOT EXISTS idx_codebase_files_project_id ON codebase_files(project_id);
3795
+ CREATE INDEX IF NOT EXISTS idx_codebase_files_project_path ON codebase_files(project_id, file_path);
3796
+
3797
+ -- ============================================================================
3798
+ -- ADD project_id TO code_definitions TABLE
3799
+ -- ============================================================================
3800
+ DO $$ BEGIN
3801
+ ALTER TABLE code_definitions
3802
+ ADD COLUMN IF NOT EXISTS project_id UUID DEFAULT '00000000-0000-0000-0000-000000000000'::uuid;
3803
+ EXCEPTION WHEN duplicate_column THEN NULL;
3804
+ END $$;
3805
+
3806
+ DO $$ BEGIN
3807
+ ALTER TABLE code_definitions
3808
+ ADD CONSTRAINT fk_code_definitions_project_id
3809
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET DEFAULT;
3810
+ EXCEPTION WHEN duplicate_object THEN NULL;
3811
+ END $$;
3812
+
3813
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_project_id ON code_definitions(project_id);
3814
+ CREATE INDEX IF NOT EXISTS idx_code_definitions_project_name ON code_definitions(project_id, name);
3815
+
3816
+ -- ============================================================================
3817
+ -- ADD project_id TO code_dependencies TABLE
3818
+ -- ============================================================================
3819
+ DO $$ BEGIN
3820
+ ALTER TABLE code_dependencies
3821
+ ADD COLUMN IF NOT EXISTS project_id UUID DEFAULT '00000000-0000-0000-0000-000000000000'::uuid;
3822
+ EXCEPTION WHEN duplicate_column THEN NULL;
3823
+ END $$;
3824
+
3825
+ DO $$ BEGIN
3826
+ ALTER TABLE code_dependencies
3827
+ ADD CONSTRAINT fk_code_dependencies_project_id
3828
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET DEFAULT;
3829
+ EXCEPTION WHEN duplicate_object THEN NULL;
3830
+ END $$;
3831
+
3832
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_project_id ON code_dependencies(project_id);
3833
+
3834
+ -- ============================================================================
3835
+ -- ADD project_id TO codebase_pointers TABLE (if exists)
3836
+ -- ============================================================================
3837
+ DO $$ BEGIN
3838
+ ALTER TABLE codebase_pointers
3839
+ ADD COLUMN IF NOT EXISTS project_id UUID DEFAULT '00000000-0000-0000-0000-000000000000'::uuid;
3840
+ EXCEPTION WHEN duplicate_column THEN NULL;
3841
+ WHEN undefined_table THEN NULL;
3842
+ END $$;
3843
+
3844
+ DO $$ BEGIN
3845
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'codebase_pointers') THEN
3846
+ ALTER TABLE codebase_pointers
3847
+ ADD CONSTRAINT fk_codebase_pointers_project_id
3848
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET DEFAULT;
3849
+ END IF;
3850
+ EXCEPTION WHEN duplicate_object THEN NULL;
3851
+ END $$;
3852
+
3853
+ DO $$ BEGIN
3854
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'codebase_pointers') THEN
3855
+ EXECUTE 'CREATE INDEX IF NOT EXISTS idx_codebase_pointers_project_id ON codebase_pointers(project_id)';
3856
+ END IF;
3857
+ END $$;
3858
+
3859
+ -- ============================================================================
3860
+ -- ADD pointer_type TO codebase_pointers TABLE (if exists)
3861
+ -- ============================================================================
3862
+ DO $$ BEGIN
3863
+ ALTER TABLE codebase_pointers
3864
+ ADD COLUMN IF NOT EXISTS pointer_type VARCHAR(50) DEFAULT 'reference';
3865
+ EXCEPTION WHEN duplicate_column THEN NULL;
3866
+ WHEN undefined_table THEN NULL;
3867
+ END $$;
3868
+
3869
+ -- ============================================================================
3870
+ -- ADD project_id TO team_messages TABLE (if exists)
3871
+ -- ============================================================================
3872
+ DO $$ BEGIN
3873
+ ALTER TABLE team_messages
3874
+ ADD COLUMN IF NOT EXISTS project_id UUID DEFAULT '00000000-0000-0000-0000-000000000000'::uuid;
3875
+ EXCEPTION WHEN duplicate_column THEN NULL;
3876
+ WHEN undefined_table THEN NULL;
3877
+ END $$;
3878
+
3879
+ DO $$ BEGIN
3880
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'team_messages') THEN
3881
+ ALTER TABLE team_messages
3882
+ ADD CONSTRAINT fk_team_messages_project_id
3883
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET DEFAULT;
3884
+ END IF;
3885
+ EXCEPTION WHEN duplicate_object THEN NULL;
3886
+ END $$;
3887
+
3888
+ DO $$ BEGIN
3889
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'team_messages') THEN
3890
+ EXECUTE 'CREATE INDEX IF NOT EXISTS idx_team_messages_project_id ON team_messages(project_id)';
3891
+ EXECUTE 'CREATE INDEX IF NOT EXISTS idx_team_messages_project_channel ON team_messages(project_id, channel_id, created_at DESC)';
3892
+ END IF;
3893
+ END $$;
3894
+
3895
+ -- ============================================================================
3896
+ -- ADD project_id TO task_claims TABLE (if exists)
3897
+ -- ============================================================================
3898
+ DO $$ BEGIN
3899
+ ALTER TABLE task_claims
3900
+ ADD COLUMN IF NOT EXISTS project_id UUID DEFAULT '00000000-0000-0000-0000-000000000000'::uuid;
3901
+ EXCEPTION WHEN duplicate_column THEN NULL;
3902
+ WHEN undefined_table THEN NULL;
3903
+ END $$;
3904
+
3905
+ DO $$ BEGIN
3906
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'task_claims') THEN
3907
+ ALTER TABLE task_claims
3908
+ ADD CONSTRAINT fk_task_claims_project_id
3909
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET DEFAULT;
3910
+ END IF;
3911
+ EXCEPTION WHEN duplicate_object THEN NULL;
3912
+ END $$;
3913
+
3914
+ DO $$ BEGIN
3915
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'task_claims') THEN
3916
+ EXECUTE 'CREATE INDEX IF NOT EXISTS idx_task_claims_project_id ON task_claims(project_id)';
3917
+ EXECUTE 'CREATE INDEX IF NOT EXISTS idx_task_claims_project_status ON task_claims(project_id, status)';
3918
+ END IF;
3919
+ END $$;
3920
+
3921
+ -- ============================================================================
3922
+ -- ADD project_id TO team_channels TABLE (if exists)
3923
+ -- ============================================================================
3924
+ DO $$ BEGIN
3925
+ ALTER TABLE team_channels
3926
+ ADD COLUMN IF NOT EXISTS project_id UUID DEFAULT '00000000-0000-0000-0000-000000000000'::uuid;
3927
+ EXCEPTION WHEN duplicate_column THEN NULL;
3928
+ WHEN undefined_table THEN NULL;
3929
+ END $$;
3930
+
3931
+ DO $$ BEGIN
3932
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'team_channels') THEN
3933
+ ALTER TABLE team_channels
3934
+ ADD CONSTRAINT fk_team_channels_project_id
3935
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET DEFAULT;
3936
+ END IF;
3937
+ EXCEPTION WHEN duplicate_object THEN NULL;
3938
+ END $$;
3939
+
3940
+ DO $$ BEGIN
3941
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'team_channels') THEN
3942
+ EXECUTE 'CREATE INDEX IF NOT EXISTS idx_team_channels_project_id ON team_channels(project_id)';
3943
+ END IF;
3944
+ END $$;
3945
+
3946
+ -- ============================================================================
3947
+ -- ADD project_id TO help_requests TABLE (if exists)
3948
+ -- ============================================================================
3949
+ DO $$ BEGIN
3950
+ ALTER TABLE help_requests
3951
+ ADD COLUMN IF NOT EXISTS project_id UUID DEFAULT '00000000-0000-0000-0000-000000000000'::uuid;
3952
+ EXCEPTION WHEN duplicate_column THEN NULL;
3953
+ WHEN undefined_table THEN NULL;
3954
+ END $$;
3955
+
3956
+ DO $$ BEGIN
3957
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'help_requests') THEN
3958
+ ALTER TABLE help_requests
3959
+ ADD CONSTRAINT fk_help_requests_project_id
3960
+ FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET DEFAULT;
3961
+ END IF;
3962
+ EXCEPTION WHEN duplicate_object THEN NULL;
3963
+ END $$;
3964
+
3965
+ DO $$ BEGIN
3966
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'help_requests') THEN
3967
+ EXECUTE 'CREATE INDEX IF NOT EXISTS idx_help_requests_project_id ON help_requests(project_id)';
3968
+ END IF;
3969
+ END $$;
3970
+
3971
+ -- ============================================================================
3972
+ -- RACE-CONDITION-FREE PROJECT REGISTRATION FUNCTION
3973
+ -- ============================================================================
3974
+ CREATE OR REPLACE FUNCTION register_project(
3975
+ p_path VARCHAR(500),
3976
+ p_name VARCHAR(255) DEFAULT NULL
3977
+ )
3978
+ RETURNS UUID AS $$
3979
+ DECLARE
3980
+ v_project_id UUID;
3981
+ BEGIN
3982
+ INSERT INTO projects (path, name)
3983
+ VALUES (p_path, COALESCE(p_name, p_path))
3984
+ ON CONFLICT (path) DO UPDATE SET
3985
+ last_accessed_at = NOW(),
3986
+ name = COALESCE(EXCLUDED.name, projects.name)
3987
+ RETURNING id INTO v_project_id;
3988
+
3989
+ RETURN v_project_id;
3990
+ END;
3991
+ $$ LANGUAGE plpgsql;
3992
+
3993
+ -- ============================================================================
3994
+ -- HELPER: Get project ID by path
3995
+ -- ============================================================================
3996
+ CREATE OR REPLACE FUNCTION get_project_id(p_path VARCHAR(500))
3997
+ RETURNS UUID AS $$
3998
+ DECLARE
3999
+ v_project_id UUID;
4000
+ BEGIN
4001
+ SELECT id INTO v_project_id
4002
+ FROM projects
4003
+ WHERE path = p_path;
4004
+
4005
+ IF v_project_id IS NULL THEN
4006
+ v_project_id := register_project(p_path);
4007
+ ELSE
4008
+ UPDATE projects SET last_accessed_at = NOW() WHERE id = v_project_id;
4009
+ END IF;
4010
+
4011
+ RETURN v_project_id;
4012
+ END;
4013
+ $$ LANGUAGE plpgsql;
4014
+
4015
+ -- ============================================================================
4016
+ -- BACKFILL: Assign all existing data to default project
4017
+ -- ============================================================================
4018
+ UPDATE memories SET project_id = '00000000-0000-0000-0000-000000000000'::uuid WHERE project_id IS NULL;
4019
+ UPDATE codebase_files SET project_id = '00000000-0000-0000-0000-000000000000'::uuid WHERE project_id IS NULL;
4020
+ UPDATE code_definitions SET project_id = '00000000-0000-0000-0000-000000000000'::uuid WHERE project_id IS NULL;
4021
+ UPDATE code_dependencies SET project_id = '00000000-0000-0000-0000-000000000000'::uuid WHERE project_id IS NULL;
4022
+
4023
+ -- Backfill codebase_pointers if it exists
4024
+ DO $$ BEGIN
4025
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'codebase_pointers') THEN
4026
+ EXECUTE 'UPDATE codebase_pointers SET project_id = ''00000000-0000-0000-0000-000000000000''::uuid WHERE project_id IS NULL';
4027
+ END IF;
4028
+ END $$;
4029
+
4030
+ -- Backfill team tables if they exist
4031
+ DO $$ BEGIN
4032
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'team_messages') THEN
4033
+ EXECUTE 'UPDATE team_messages SET project_id = ''00000000-0000-0000-0000-000000000000''::uuid WHERE project_id IS NULL';
4034
+ END IF;
4035
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'task_claims') THEN
4036
+ EXECUTE 'UPDATE task_claims SET project_id = ''00000000-0000-0000-0000-000000000000''::uuid WHERE project_id IS NULL';
4037
+ END IF;
4038
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'team_channels') THEN
4039
+ EXECUTE 'UPDATE team_channels SET project_id = ''00000000-0000-0000-0000-000000000000''::uuid WHERE project_id IS NULL';
4040
+ END IF;
4041
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'help_requests') THEN
4042
+ EXECUTE 'UPDATE help_requests SET project_id = ''00000000-0000-0000-0000-000000000000''::uuid WHERE project_id IS NULL';
4043
+ END IF;
4044
+ END $$;
4045
+ `,
4046
+ down: `
4047
+ -- WARNING: Rolling back project namespacing may break multi-project isolation!
4048
+ -- We only drop the FK constraints and indexes, keeping the data intact
4049
+
4050
+ -- Drop FK constraints
4051
+ ALTER TABLE memories DROP CONSTRAINT IF EXISTS fk_memories_project_id;
4052
+ ALTER TABLE codebase_files DROP CONSTRAINT IF EXISTS fk_codebase_files_project_id;
4053
+ ALTER TABLE code_definitions DROP CONSTRAINT IF EXISTS fk_code_definitions_project_id;
4054
+ ALTER TABLE code_dependencies DROP CONSTRAINT IF EXISTS fk_code_dependencies_project_id;
4055
+ ALTER TABLE codebase_pointers DROP CONSTRAINT IF EXISTS fk_codebase_pointers_project_id;
4056
+
4057
+ DO $$ BEGIN
4058
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'team_messages') THEN
4059
+ ALTER TABLE team_messages DROP CONSTRAINT IF EXISTS fk_team_messages_project_id;
4060
+ END IF;
4061
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'task_claims') THEN
4062
+ ALTER TABLE task_claims DROP CONSTRAINT IF EXISTS fk_task_claims_project_id;
4063
+ END IF;
4064
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'team_channels') THEN
4065
+ ALTER TABLE team_channels DROP CONSTRAINT IF EXISTS fk_team_channels_project_id;
4066
+ END IF;
4067
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'help_requests') THEN
4068
+ ALTER TABLE help_requests DROP CONSTRAINT IF EXISTS fk_help_requests_project_id;
4069
+ END IF;
4070
+ END $$;
4071
+
4072
+ -- Drop indexes
4073
+ DROP INDEX IF EXISTS idx_memories_project_id;
4074
+ DROP INDEX IF EXISTS idx_memories_project_created;
4075
+ DROP INDEX IF EXISTS idx_memories_project_importance;
4076
+ DROP INDEX IF EXISTS idx_codebase_files_project_id;
4077
+ DROP INDEX IF EXISTS idx_codebase_files_project_path;
4078
+ DROP INDEX IF EXISTS idx_code_definitions_project_id;
4079
+ DROP INDEX IF EXISTS idx_code_definitions_project_name;
4080
+ DROP INDEX IF EXISTS idx_code_dependencies_project_id;
4081
+ DROP INDEX IF EXISTS idx_codebase_pointers_project_id;
4082
+ DROP INDEX IF EXISTS idx_team_messages_project_id;
4083
+ DROP INDEX IF EXISTS idx_team_messages_project_channel;
4084
+ DROP INDEX IF EXISTS idx_task_claims_project_id;
4085
+ DROP INDEX IF EXISTS idx_task_claims_project_status;
4086
+ DROP INDEX IF EXISTS idx_team_channels_project_id;
4087
+ DROP INDEX IF EXISTS idx_help_requests_project_id;
4088
+
4089
+ -- Drop functions
4090
+ DROP FUNCTION IF EXISTS register_project(VARCHAR, VARCHAR);
4091
+ DROP FUNCTION IF EXISTS get_project_id(VARCHAR);
4092
+
4093
+ -- NOTE: We intentionally keep the project_id columns and projects table
4094
+ -- to preserve data. Remove them manually if needed:
4095
+ -- ALTER TABLE memories DROP COLUMN IF EXISTS project_id;
4096
+ -- DROP TABLE IF EXISTS projects;
4097
+ `,
4098
+ checksum: this.generateChecksum('project_namespacing_isolation_v31')
4099
+ },
4100
+ // migration 32: Add project_path to code_chunks for per-project isolation
4101
+ // CRITICAL: code_chunks was missed in the original project namespacing migration
4102
+ // This enables find_code_pointers to work correctly per-project
4103
+ {
4104
+ version: 32,
4105
+ name: 'code_chunks_project_path',
4106
+ up: `
4107
+ -- Add project_path to code_chunks for project isolation
4108
+ DO $$ BEGIN
4109
+ ALTER TABLE code_chunks
4110
+ ADD COLUMN IF NOT EXISTS project_path TEXT DEFAULT '/';
4111
+ EXCEPTION WHEN duplicate_column THEN NULL;
4112
+ END $$;
4113
+
4114
+ -- Index for project_path filtering - critical for per-project queries
4115
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_project_path
4116
+ ON code_chunks(project_path);
4117
+
4118
+ -- Composite index for project + file lookups
4119
+ CREATE INDEX IF NOT EXISTS idx_code_chunks_project_file
4120
+ ON code_chunks(project_path, file_path);
4121
+ `,
4122
+ down: `
4123
+ DROP INDEX IF EXISTS idx_code_chunks_project_file;
4124
+ DROP INDEX IF EXISTS idx_code_chunks_project_path;
4125
+ ALTER TABLE code_chunks DROP COLUMN IF EXISTS project_path;
4126
+ `,
4127
+ checksum: this.generateChecksum('code_chunks_project_path_v32')
4128
+ },
4129
+ // migration 33: Add project_path to code_dependencies for per-project isolation
4130
+ // CRITICAL: This table also needs project_path for codebase indexer to work per-project
4131
+ {
4132
+ version: 33,
4133
+ name: 'code_dependencies_project_path',
4134
+ up: `
4135
+ -- Add project_path to code_dependencies for project isolation
4136
+ DO $$ BEGIN
4137
+ ALTER TABLE code_dependencies
4138
+ ADD COLUMN IF NOT EXISTS project_path TEXT DEFAULT '/';
4139
+ EXCEPTION WHEN duplicate_column THEN NULL;
4140
+ END $$;
4141
+
4142
+ -- Index for project_path filtering
4143
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_project_path
4144
+ ON code_dependencies(project_path);
4145
+
4146
+ -- Composite index for project + source lookups
4147
+ CREATE INDEX IF NOT EXISTS idx_code_dependencies_project_source
4148
+ ON code_dependencies(project_path, source_file_id);
4149
+ `,
4150
+ down: `
4151
+ DROP INDEX IF EXISTS idx_code_dependencies_project_source;
4152
+ DROP INDEX IF EXISTS idx_code_dependencies_project_path;
4153
+ ALTER TABLE code_dependencies DROP COLUMN IF EXISTS project_path;
4154
+ `,
4155
+ checksum: this.generateChecksum('code_dependencies_project_path_v33')
4156
+ },
4157
+ // migration 34: Add project_path to code_complexity for per-project isolation
4158
+ // CRITICAL: This table also needs project_path for codebase metrics per-project
4159
+ {
4160
+ version: 34,
4161
+ name: 'code_complexity_project_path',
4162
+ up: `
4163
+ -- Add project_path to code_complexity for project isolation
4164
+ DO $$ BEGIN
4165
+ ALTER TABLE code_complexity
4166
+ ADD COLUMN IF NOT EXISTS project_path TEXT DEFAULT '/';
4167
+ EXCEPTION WHEN duplicate_column THEN NULL;
4168
+ END $$;
4169
+
4170
+ -- Index for project_path filtering
4171
+ CREATE INDEX IF NOT EXISTS idx_code_complexity_project_path
4172
+ ON code_complexity(project_path);
4173
+
4174
+ -- Composite index for project + file lookups
4175
+ CREATE INDEX IF NOT EXISTS idx_code_complexity_project_file
4176
+ ON code_complexity(project_path, file_id);
4177
+ `,
4178
+ down: `
4179
+ DROP INDEX IF EXISTS idx_code_complexity_project_file;
4180
+ DROP INDEX IF EXISTS idx_code_complexity_project_path;
4181
+ ALTER TABLE code_complexity DROP COLUMN IF EXISTS project_path;
4182
+ `,
4183
+ checksum: this.generateChecksum('code_complexity_project_path_v34')
4184
+ },
4185
+ // migration 35: Add composite indexes for common project_path query patterns
4186
+ // CRITICAL: Queries use project_path (TEXT) not project_id (UUID) - need matching indexes
4187
+ {
4188
+ version: 35,
4189
+ name: 'composite_project_path_indexes',
4190
+ up: `
4191
+ -- Composite index for project + created_at (recent memories query)
4192
+ -- Used by: find_memory with recencyBoost, getStatsRealtime
4193
+ CREATE INDEX IF NOT EXISTS idx_memories_project_path_created
4194
+ ON memories(project_path, created_at DESC);
4195
+
4196
+ -- Composite index for project + importance (priority lookup)
4197
+ -- Used by: find_memory with importance filter
4198
+ CREATE INDEX IF NOT EXISTS idx_memories_project_path_importance
4199
+ ON memories(project_path, importance);
4200
+
4201
+ -- Composite index for project + memory_type (filtered searches)
4202
+ -- Used by: find_memory with memoryTypes filter
4203
+ CREATE INDEX IF NOT EXISTS idx_memories_project_path_type
4204
+ ON memories(project_path, memory_type);
4205
+
4206
+ -- Composite index for codebase_files project + file_path
4207
+ -- Used by: codebaseTools queries filtering by project_path and file_path
4208
+ CREATE INDEX IF NOT EXISTS idx_codebase_files_project_path_file
4209
+ ON codebase_files(project_path, file_path);
4210
+
4211
+ -- Composite index for codebase_files project + content_hash (dedup check)
4212
+ -- Used by: codebaseIndexer for hash lookups per project
4213
+ CREATE INDEX IF NOT EXISTS idx_codebase_files_project_path_hash
4214
+ ON codebase_files(project_path, content_hash);
4215
+
4216
+ -- Composite index for memories project + content_hash (dedup check)
4217
+ -- Used by: yeetStuffInDb for duplicate memory detection
4218
+ CREATE INDEX IF NOT EXISTS idx_memories_project_path_hash
4219
+ ON memories(project_path, content_hash);
4220
+ `,
4221
+ down: `
4222
+ DROP INDEX IF EXISTS idx_memories_project_path_created;
4223
+ DROP INDEX IF EXISTS idx_memories_project_path_importance;
4224
+ DROP INDEX IF EXISTS idx_memories_project_path_type;
4225
+ DROP INDEX IF EXISTS idx_codebase_files_project_path_file;
4226
+ DROP INDEX IF EXISTS idx_codebase_files_project_path_hash;
4227
+ DROP INDEX IF EXISTS idx_memories_project_path_hash;
4228
+ `,
4229
+ checksum: this.generateChecksum('composite_project_path_indexes_v35')
4230
+ }
4231
+ ];
4232
+ }
4233
+ // validates all migration checksums to detect tampering
4234
+ async validateMigrations() {
4235
+ const applied = await this.getAppliedMigrations();
4236
+ const migrations = this.getMigrations();
4237
+ const issues = [];
4238
+ for (const record of applied) {
4239
+ const migration = migrations.find(m => m.version === record.version);
4240
+ if (!migration) {
4241
+ issues.push(`migration ${record.version} (${record.name}) not found in codebase`);
4242
+ continue;
4243
+ }
4244
+ if (migration.checksum !== record.checksum) {
4245
+ issues.push(`checksum mismatch for migration ${record.version}: ` +
4246
+ `expected ${record.checksum}, got ${migration.checksum}`);
4247
+ }
4248
+ }
4249
+ return {
4250
+ valid: issues.length === 0,
4251
+ issues
4252
+ };
4253
+ }
4254
+ // gets migration status
4255
+ async getStatus() {
4256
+ await this.ensureMigrationTable();
4257
+ const applied = await this.getAppliedMigrations();
4258
+ const allMigrations = this.getMigrations();
4259
+ return {
4260
+ applied,
4261
+ pending: allMigrations.filter(m => !applied.some(a => a.version === m.version)),
4262
+ lastApplied: applied[applied.length - 1] ?? null
4263
+ };
4264
+ }
4265
+ }
4266
+ //# sourceMappingURL=bigBrainMigrations.js.map