shieldcortex 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +282 -0
  3. package/dashboard/components.json +22 -0
  4. package/dashboard/eslint.config.mjs +42 -0
  5. package/dashboard/next.config.ts +7 -0
  6. package/dashboard/package-lock.json +8053 -0
  7. package/dashboard/package.json +44 -0
  8. package/dashboard/postcss.config.mjs +7 -0
  9. package/dashboard/public/file.svg +1 -0
  10. package/dashboard/public/globe.svg +1 -0
  11. package/dashboard/public/next.svg +1 -0
  12. package/dashboard/public/vercel.svg +1 -0
  13. package/dashboard/public/window.svg +1 -0
  14. package/dashboard/scripts/ensure-api.mjs +76 -0
  15. package/dashboard/src/app/error.tsx +49 -0
  16. package/dashboard/src/app/favicon.ico +0 -0
  17. package/dashboard/src/app/globals.css +130 -0
  18. package/dashboard/src/app/layout.tsx +35 -0
  19. package/dashboard/src/app/page.tsx +364 -0
  20. package/dashboard/src/components/Providers.tsx +27 -0
  21. package/dashboard/src/components/brain/ActivityPulseSystem.tsx +229 -0
  22. package/dashboard/src/components/brain/BrainMesh.tsx +133 -0
  23. package/dashboard/src/components/brain/BrainRegions.tsx +254 -0
  24. package/dashboard/src/components/brain/BrainScene.tsx +255 -0
  25. package/dashboard/src/components/brain/CategoryLabels.tsx +103 -0
  26. package/dashboard/src/components/brain/CoreSphere.tsx +215 -0
  27. package/dashboard/src/components/brain/DataFlowParticles.tsx +123 -0
  28. package/dashboard/src/components/brain/DataStreamRings.tsx +161 -0
  29. package/dashboard/src/components/brain/ElectronFlow.tsx +323 -0
  30. package/dashboard/src/components/brain/HolographicGrid.tsx +235 -0
  31. package/dashboard/src/components/brain/MemoryLinks.tsx +271 -0
  32. package/dashboard/src/components/brain/MemoryNode.tsx +245 -0
  33. package/dashboard/src/components/brain/NeuralPathways.tsx +441 -0
  34. package/dashboard/src/components/brain/SynapseNodes.tsx +312 -0
  35. package/dashboard/src/components/brain/TimelineControls.tsx +205 -0
  36. package/dashboard/src/components/chip/ChipScene.tsx +497 -0
  37. package/dashboard/src/components/chip/ChipSubstrate.tsx +238 -0
  38. package/dashboard/src/components/chip/CortexCore.tsx +210 -0
  39. package/dashboard/src/components/chip/DataBus.tsx +416 -0
  40. package/dashboard/src/components/chip/MemoryCell.tsx +225 -0
  41. package/dashboard/src/components/chip/MemoryGrid.tsx +328 -0
  42. package/dashboard/src/components/chip/QuantumCell.tsx +316 -0
  43. package/dashboard/src/components/chip/SectionLabel.tsx +113 -0
  44. package/dashboard/src/components/chip/index.ts +14 -0
  45. package/dashboard/src/components/controls/ControlPanel.tsx +106 -0
  46. package/dashboard/src/components/controls/VersionPanel.tsx +185 -0
  47. package/dashboard/src/components/dashboard/StatsPanel.tsx +164 -0
  48. package/dashboard/src/components/debug/ActivityLog.tsx +250 -0
  49. package/dashboard/src/components/debug/DebugPanel.tsx +101 -0
  50. package/dashboard/src/components/debug/QueryTester.tsx +192 -0
  51. package/dashboard/src/components/debug/RelationshipGraph.tsx +403 -0
  52. package/dashboard/src/components/debug/SqlConsole.tsx +319 -0
  53. package/dashboard/src/components/graph/KnowledgeGraph.tsx +230 -0
  54. package/dashboard/src/components/graph/OntologyGraph.tsx +631 -0
  55. package/dashboard/src/components/insights/ActivityHeatmap.tsx +131 -0
  56. package/dashboard/src/components/insights/InsightsView.tsx +46 -0
  57. package/dashboard/src/components/insights/KnowledgeMapPanel.tsx +80 -0
  58. package/dashboard/src/components/insights/QualityPanel.tsx +116 -0
  59. package/dashboard/src/components/memories/MemoriesView.tsx +150 -0
  60. package/dashboard/src/components/memories/MemoryCard.tsx +103 -0
  61. package/dashboard/src/components/memory/MemoryDetail.tsx +325 -0
  62. package/dashboard/src/components/nav/NavRail.tsx +54 -0
  63. package/dashboard/src/components/ui/button.tsx +62 -0
  64. package/dashboard/src/components/ui/card.tsx +92 -0
  65. package/dashboard/src/components/ui/input.tsx +21 -0
  66. package/dashboard/src/hooks/useDebouncedValue.ts +24 -0
  67. package/dashboard/src/hooks/useMemories.ts +458 -0
  68. package/dashboard/src/hooks/useSuggestions.ts +46 -0
  69. package/dashboard/src/lib/category-colors.ts +84 -0
  70. package/dashboard/src/lib/position-algorithm.ts +177 -0
  71. package/dashboard/src/lib/simplex-noise.ts +217 -0
  72. package/dashboard/src/lib/store.ts +88 -0
  73. package/dashboard/src/lib/utils.ts +6 -0
  74. package/dashboard/src/lib/websocket.ts +249 -0
  75. package/dashboard/src/types/memory.ts +73 -0
  76. package/dashboard/tsconfig.json +34 -0
  77. package/dist/__tests__/consolidation-merge.test.d.ts +9 -0
  78. package/dist/__tests__/consolidation-merge.test.d.ts.map +1 -0
  79. package/dist/__tests__/consolidation-merge.test.js +137 -0
  80. package/dist/__tests__/consolidation-merge.test.js.map +1 -0
  81. package/dist/__tests__/contradictions.test.d.ts +8 -0
  82. package/dist/__tests__/contradictions.test.d.ts.map +1 -0
  83. package/dist/__tests__/contradictions.test.js +78 -0
  84. package/dist/__tests__/contradictions.test.js.map +1 -0
  85. package/dist/__tests__/salience-evolution.test.d.ts +7 -0
  86. package/dist/__tests__/salience-evolution.test.d.ts.map +1 -0
  87. package/dist/__tests__/salience-evolution.test.js +151 -0
  88. package/dist/__tests__/salience-evolution.test.js.map +1 -0
  89. package/dist/__tests__/store.test.d.ts +7 -0
  90. package/dist/__tests__/store.test.d.ts.map +1 -0
  91. package/dist/__tests__/store.test.js +582 -0
  92. package/dist/__tests__/store.test.js.map +1 -0
  93. package/dist/api/control.d.ts +27 -0
  94. package/dist/api/control.d.ts.map +1 -0
  95. package/dist/api/control.js +60 -0
  96. package/dist/api/control.js.map +1 -0
  97. package/dist/api/events.d.ts +159 -0
  98. package/dist/api/events.d.ts.map +1 -0
  99. package/dist/api/events.js +155 -0
  100. package/dist/api/events.js.map +1 -0
  101. package/dist/api/version.d.ts +36 -0
  102. package/dist/api/version.d.ts.map +1 -0
  103. package/dist/api/version.js +146 -0
  104. package/dist/api/version.js.map +1 -0
  105. package/dist/api/visualization-server.d.ts +11 -0
  106. package/dist/api/visualization-server.d.ts.map +1 -0
  107. package/dist/api/visualization-server.js +1186 -0
  108. package/dist/api/visualization-server.js.map +1 -0
  109. package/dist/context/project-context.d.ts +57 -0
  110. package/dist/context/project-context.d.ts.map +1 -0
  111. package/dist/context/project-context.js +135 -0
  112. package/dist/context/project-context.js.map +1 -0
  113. package/dist/database/init.d.ts +49 -0
  114. package/dist/database/init.d.ts.map +1 -0
  115. package/dist/database/init.js +567 -0
  116. package/dist/database/init.js.map +1 -0
  117. package/dist/defence/__tests__/firewall.test.d.ts +8 -0
  118. package/dist/defence/__tests__/firewall.test.d.ts.map +1 -0
  119. package/dist/defence/__tests__/firewall.test.js +123 -0
  120. package/dist/defence/__tests__/firewall.test.js.map +1 -0
  121. package/dist/defence/__tests__/fragmentation.test.d.ts +7 -0
  122. package/dist/defence/__tests__/fragmentation.test.d.ts.map +1 -0
  123. package/dist/defence/__tests__/fragmentation.test.js +51 -0
  124. package/dist/defence/__tests__/fragmentation.test.js.map +1 -0
  125. package/dist/defence/__tests__/pipeline.test.d.ts +8 -0
  126. package/dist/defence/__tests__/pipeline.test.d.ts.map +1 -0
  127. package/dist/defence/__tests__/pipeline.test.js +61 -0
  128. package/dist/defence/__tests__/pipeline.test.js.map +1 -0
  129. package/dist/defence/__tests__/sensitivity.test.d.ts +7 -0
  130. package/dist/defence/__tests__/sensitivity.test.d.ts.map +1 -0
  131. package/dist/defence/__tests__/sensitivity.test.js +61 -0
  132. package/dist/defence/__tests__/sensitivity.test.js.map +1 -0
  133. package/dist/defence/__tests__/trust.test.d.ts +7 -0
  134. package/dist/defence/__tests__/trust.test.d.ts.map +1 -0
  135. package/dist/defence/__tests__/trust.test.js +49 -0
  136. package/dist/defence/__tests__/trust.test.js.map +1 -0
  137. package/dist/defence/audit/index.d.ts +4 -0
  138. package/dist/defence/audit/index.d.ts.map +1 -0
  139. package/dist/defence/audit/index.js +3 -0
  140. package/dist/defence/audit/index.js.map +1 -0
  141. package/dist/defence/audit/logger.d.ts +14 -0
  142. package/dist/defence/audit/logger.d.ts.map +1 -0
  143. package/dist/defence/audit/logger.js +54 -0
  144. package/dist/defence/audit/logger.js.map +1 -0
  145. package/dist/defence/audit/queries.d.ts +33 -0
  146. package/dist/defence/audit/queries.d.ts.map +1 -0
  147. package/dist/defence/audit/queries.js +103 -0
  148. package/dist/defence/audit/queries.js.map +1 -0
  149. package/dist/defence/firewall/anomaly-scorer.d.ts +8 -0
  150. package/dist/defence/firewall/anomaly-scorer.d.ts.map +1 -0
  151. package/dist/defence/firewall/anomaly-scorer.js +58 -0
  152. package/dist/defence/firewall/anomaly-scorer.js.map +1 -0
  153. package/dist/defence/firewall/encoding-detector.d.ts +13 -0
  154. package/dist/defence/firewall/encoding-detector.d.ts.map +1 -0
  155. package/dist/defence/firewall/encoding-detector.js +120 -0
  156. package/dist/defence/firewall/encoding-detector.js.map +1 -0
  157. package/dist/defence/firewall/index.d.ts +21 -0
  158. package/dist/defence/firewall/index.d.ts.map +1 -0
  159. package/dist/defence/firewall/index.js +133 -0
  160. package/dist/defence/firewall/index.js.map +1 -0
  161. package/dist/defence/firewall/instruction-detector.d.ts +12 -0
  162. package/dist/defence/firewall/instruction-detector.d.ts.map +1 -0
  163. package/dist/defence/firewall/instruction-detector.js +99 -0
  164. package/dist/defence/firewall/instruction-detector.js.map +1 -0
  165. package/dist/defence/firewall/privilege-detector.d.ts +13 -0
  166. package/dist/defence/firewall/privilege-detector.d.ts.map +1 -0
  167. package/dist/defence/firewall/privilege-detector.js +89 -0
  168. package/dist/defence/firewall/privilege-detector.js.map +1 -0
  169. package/dist/defence/fragmentation/assembly-detector.d.ts +18 -0
  170. package/dist/defence/fragmentation/assembly-detector.d.ts.map +1 -0
  171. package/dist/defence/fragmentation/assembly-detector.js +72 -0
  172. package/dist/defence/fragmentation/assembly-detector.js.map +1 -0
  173. package/dist/defence/fragmentation/entity-extractor.d.ts +19 -0
  174. package/dist/defence/fragmentation/entity-extractor.d.ts.map +1 -0
  175. package/dist/defence/fragmentation/entity-extractor.js +86 -0
  176. package/dist/defence/fragmentation/entity-extractor.js.map +1 -0
  177. package/dist/defence/fragmentation/index.d.ts +23 -0
  178. package/dist/defence/fragmentation/index.d.ts.map +1 -0
  179. package/dist/defence/fragmentation/index.js +49 -0
  180. package/dist/defence/fragmentation/index.js.map +1 -0
  181. package/dist/defence/fragmentation/temporal-analyzer.d.ts +28 -0
  182. package/dist/defence/fragmentation/temporal-analyzer.d.ts.map +1 -0
  183. package/dist/defence/fragmentation/temporal-analyzer.js +41 -0
  184. package/dist/defence/fragmentation/temporal-analyzer.js.map +1 -0
  185. package/dist/defence/index.d.ts +12 -0
  186. package/dist/defence/index.d.ts.map +1 -0
  187. package/dist/defence/index.js +18 -0
  188. package/dist/defence/index.js.map +1 -0
  189. package/dist/defence/pipeline.d.ts +9 -0
  190. package/dist/defence/pipeline.d.ts.map +1 -0
  191. package/dist/defence/pipeline.js +115 -0
  192. package/dist/defence/pipeline.js.map +1 -0
  193. package/dist/defence/scanner/index.d.ts +5 -0
  194. package/dist/defence/scanner/index.d.ts.map +1 -0
  195. package/dist/defence/scanner/index.js +5 -0
  196. package/dist/defence/scanner/index.js.map +1 -0
  197. package/dist/defence/scanner/scan-existing.d.ts +34 -0
  198. package/dist/defence/scanner/scan-existing.d.ts.map +1 -0
  199. package/dist/defence/scanner/scan-existing.js +136 -0
  200. package/dist/defence/scanner/scan-existing.js.map +1 -0
  201. package/dist/defence/sensitivity/classifier.d.ts +6 -0
  202. package/dist/defence/sensitivity/classifier.d.ts.map +1 -0
  203. package/dist/defence/sensitivity/classifier.js +50 -0
  204. package/dist/defence/sensitivity/classifier.js.map +1 -0
  205. package/dist/defence/sensitivity/index.d.ts +11 -0
  206. package/dist/defence/sensitivity/index.d.ts.map +1 -0
  207. package/dist/defence/sensitivity/index.js +13 -0
  208. package/dist/defence/sensitivity/index.js.map +1 -0
  209. package/dist/defence/sensitivity/patterns.d.ts +14 -0
  210. package/dist/defence/sensitivity/patterns.d.ts.map +1 -0
  211. package/dist/defence/sensitivity/patterns.js +67 -0
  212. package/dist/defence/sensitivity/patterns.js.map +1 -0
  213. package/dist/defence/sensitivity/redaction.d.ts +17 -0
  214. package/dist/defence/sensitivity/redaction.d.ts.map +1 -0
  215. package/dist/defence/sensitivity/redaction.js +47 -0
  216. package/dist/defence/sensitivity/redaction.js.map +1 -0
  217. package/dist/defence/trust/index.d.ts +3 -0
  218. package/dist/defence/trust/index.d.ts.map +1 -0
  219. package/dist/defence/trust/index.js +3 -0
  220. package/dist/defence/trust/index.js.map +1 -0
  221. package/dist/defence/trust/recall-filter.d.ts +10 -0
  222. package/dist/defence/trust/recall-filter.d.ts.map +1 -0
  223. package/dist/defence/trust/recall-filter.js +38 -0
  224. package/dist/defence/trust/recall-filter.js.map +1 -0
  225. package/dist/defence/trust/source-scorer.d.ts +6 -0
  226. package/dist/defence/trust/source-scorer.d.ts.map +1 -0
  227. package/dist/defence/trust/source-scorer.js +34 -0
  228. package/dist/defence/trust/source-scorer.js.map +1 -0
  229. package/dist/defence/types.d.ts +88 -0
  230. package/dist/defence/types.d.ts.map +1 -0
  231. package/dist/defence/types.js +15 -0
  232. package/dist/defence/types.js.map +1 -0
  233. package/dist/embeddings/generator.d.ts +20 -0
  234. package/dist/embeddings/generator.d.ts.map +1 -0
  235. package/dist/embeddings/generator.js +83 -0
  236. package/dist/embeddings/generator.js.map +1 -0
  237. package/dist/embeddings/index.d.ts +2 -0
  238. package/dist/embeddings/index.d.ts.map +1 -0
  239. package/dist/embeddings/index.js +2 -0
  240. package/dist/embeddings/index.js.map +1 -0
  241. package/dist/errors.d.ts +74 -0
  242. package/dist/errors.d.ts.map +1 -0
  243. package/dist/errors.js +131 -0
  244. package/dist/errors.js.map +1 -0
  245. package/dist/graph/backfill.d.ts +6 -0
  246. package/dist/graph/backfill.d.ts.map +1 -0
  247. package/dist/graph/backfill.js +33 -0
  248. package/dist/graph/backfill.js.map +1 -0
  249. package/dist/graph/extract.d.ts +21 -0
  250. package/dist/graph/extract.d.ts.map +1 -0
  251. package/dist/graph/extract.js +231 -0
  252. package/dist/graph/extract.js.map +1 -0
  253. package/dist/graph/resolve.d.ts +6 -0
  254. package/dist/graph/resolve.d.ts.map +1 -0
  255. package/dist/graph/resolve.js +126 -0
  256. package/dist/graph/resolve.js.map +1 -0
  257. package/dist/index.d.ts +31 -0
  258. package/dist/index.d.ts.map +1 -0
  259. package/dist/index.js +248 -0
  260. package/dist/index.js.map +1 -0
  261. package/dist/memory/activation.d.ts +69 -0
  262. package/dist/memory/activation.d.ts.map +1 -0
  263. package/dist/memory/activation.js +168 -0
  264. package/dist/memory/activation.js.map +1 -0
  265. package/dist/memory/consolidate.d.ts +98 -0
  266. package/dist/memory/consolidate.d.ts.map +1 -0
  267. package/dist/memory/consolidate.js +511 -0
  268. package/dist/memory/consolidate.js.map +1 -0
  269. package/dist/memory/contradiction.d.ts +69 -0
  270. package/dist/memory/contradiction.d.ts.map +1 -0
  271. package/dist/memory/contradiction.js +286 -0
  272. package/dist/memory/contradiction.js.map +1 -0
  273. package/dist/memory/decay.d.ts +62 -0
  274. package/dist/memory/decay.d.ts.map +1 -0
  275. package/dist/memory/decay.js +184 -0
  276. package/dist/memory/decay.js.map +1 -0
  277. package/dist/memory/salience.d.ts +36 -0
  278. package/dist/memory/salience.d.ts.map +1 -0
  279. package/dist/memory/salience.js +216 -0
  280. package/dist/memory/salience.js.map +1 -0
  281. package/dist/memory/similarity.d.ts +57 -0
  282. package/dist/memory/similarity.d.ts.map +1 -0
  283. package/dist/memory/similarity.js +114 -0
  284. package/dist/memory/similarity.js.map +1 -0
  285. package/dist/memory/store.d.ts +179 -0
  286. package/dist/memory/store.d.ts.map +1 -0
  287. package/dist/memory/store.js +1184 -0
  288. package/dist/memory/store.js.map +1 -0
  289. package/dist/memory/types.d.ts +97 -0
  290. package/dist/memory/types.d.ts.map +1 -0
  291. package/dist/memory/types.js +30 -0
  292. package/dist/memory/types.js.map +1 -0
  293. package/dist/server.d.ts +12 -0
  294. package/dist/server.d.ts.map +1 -0
  295. package/dist/server.js +568 -0
  296. package/dist/server.js.map +1 -0
  297. package/dist/service/install.d.ts +15 -0
  298. package/dist/service/install.d.ts.map +1 -0
  299. package/dist/service/install.js +178 -0
  300. package/dist/service/install.js.map +1 -0
  301. package/dist/service/templates.d.ts +13 -0
  302. package/dist/service/templates.d.ts.map +1 -0
  303. package/dist/service/templates.js +58 -0
  304. package/dist/service/templates.js.map +1 -0
  305. package/dist/setup/claude-md.d.ts +12 -0
  306. package/dist/setup/claude-md.d.ts.map +1 -0
  307. package/dist/setup/claude-md.js +68 -0
  308. package/dist/setup/claude-md.js.map +1 -0
  309. package/dist/setup/clawdbot.d.ts +15 -0
  310. package/dist/setup/clawdbot.d.ts.map +1 -0
  311. package/dist/setup/clawdbot.js +118 -0
  312. package/dist/setup/clawdbot.js.map +1 -0
  313. package/dist/setup/doctor.d.ts +5 -0
  314. package/dist/setup/doctor.d.ts.map +1 -0
  315. package/dist/setup/doctor.js +141 -0
  316. package/dist/setup/doctor.js.map +1 -0
  317. package/dist/setup/hooks.d.ts +6 -0
  318. package/dist/setup/hooks.d.ts.map +1 -0
  319. package/dist/setup/hooks.js +36 -0
  320. package/dist/setup/hooks.js.map +1 -0
  321. package/dist/setup/migrate.d.ts +16 -0
  322. package/dist/setup/migrate.d.ts.map +1 -0
  323. package/dist/setup/migrate.js +164 -0
  324. package/dist/setup/migrate.js.map +1 -0
  325. package/dist/setup/settings-hooks.d.ts +7 -0
  326. package/dist/setup/settings-hooks.d.ts.map +1 -0
  327. package/dist/setup/settings-hooks.js +83 -0
  328. package/dist/setup/settings-hooks.js.map +1 -0
  329. package/dist/setup/uninstall.d.ts +12 -0
  330. package/dist/setup/uninstall.d.ts.map +1 -0
  331. package/dist/setup/uninstall.js +125 -0
  332. package/dist/setup/uninstall.js.map +1 -0
  333. package/dist/tools/context.d.ts +135 -0
  334. package/dist/tools/context.d.ts.map +1 -0
  335. package/dist/tools/context.js +273 -0
  336. package/dist/tools/context.js.map +1 -0
  337. package/dist/tools/forget.d.ts +53 -0
  338. package/dist/tools/forget.d.ts.map +1 -0
  339. package/dist/tools/forget.js +179 -0
  340. package/dist/tools/forget.js.map +1 -0
  341. package/dist/tools/graph.d.ts +46 -0
  342. package/dist/tools/graph.d.ts.map +1 -0
  343. package/dist/tools/graph.js +206 -0
  344. package/dist/tools/graph.js.map +1 -0
  345. package/dist/tools/recall.d.ts +79 -0
  346. package/dist/tools/recall.d.ts.map +1 -0
  347. package/dist/tools/recall.js +156 -0
  348. package/dist/tools/recall.js.map +1 -0
  349. package/dist/tools/remember.d.ts +83 -0
  350. package/dist/tools/remember.d.ts.map +1 -0
  351. package/dist/tools/remember.js +151 -0
  352. package/dist/tools/remember.js.map +1 -0
  353. package/dist/worker/brain-worker.d.ts +100 -0
  354. package/dist/worker/brain-worker.d.ts.map +1 -0
  355. package/dist/worker/brain-worker.js +283 -0
  356. package/dist/worker/brain-worker.js.map +1 -0
  357. package/dist/worker/link-discovery.d.ts +47 -0
  358. package/dist/worker/link-discovery.d.ts.map +1 -0
  359. package/dist/worker/link-discovery.js +103 -0
  360. package/dist/worker/link-discovery.js.map +1 -0
  361. package/dist/worker/predictive-consolidation.d.ts +46 -0
  362. package/dist/worker/predictive-consolidation.d.ts.map +1 -0
  363. package/dist/worker/predictive-consolidation.js +110 -0
  364. package/dist/worker/predictive-consolidation.js.map +1 -0
  365. package/dist/worker/types.d.ts +91 -0
  366. package/dist/worker/types.d.ts.map +1 -0
  367. package/dist/worker/types.js +22 -0
  368. package/dist/worker/types.js.map +1 -0
  369. package/hooks/clawdbot/cortex-memory/HOOK.md +71 -0
  370. package/hooks/clawdbot/cortex-memory/handler.js +279 -0
  371. package/package.json +73 -0
  372. package/scripts/pre-compact-hook.mjs +716 -0
  373. package/scripts/session-end-hook.mjs +548 -0
  374. package/scripts/session-start-hook.mjs +221 -0
  375. package/scripts/start-dashboard.sh +41 -0
  376. package/scripts/stop-dashboard.sh +21 -0
  377. package/scripts/stop-hook.mjs +163 -0
@@ -0,0 +1,548 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Session-end hook for ShieldCortex - Automatic Memory Extraction on Exit
4
+ *
5
+ * This script runs when a Claude Code session ends and:
6
+ * 1. Reads the session transcript from the JSONL file
7
+ * 2. Analyzes conversation content for important information
8
+ * 3. Auto-extracts high-salience items (decisions, patterns, errors, etc.)
9
+ * 4. Saves them to the memory database automatically
10
+ *
11
+ * NOTE: SessionEnd doesn't always fire reliably (e.g. terminal killed, SSH drops).
12
+ * PreCompact remains the primary safety net for context preservation.
13
+ *
14
+ * Input (stdin JSON):
15
+ * {
16
+ * "session_id": "abc123",
17
+ * "transcript_path": "~/.claude/projects/.../abc.jsonl",
18
+ * "cwd": "/path/to/project",
19
+ * "hook_event_name": "SessionEnd",
20
+ * "reason": "exit" | "clear" | "logout" | "prompt_input_exit" | "other"
21
+ * }
22
+ */
23
+
24
+ import Database from 'better-sqlite3';
25
+ import { existsSync, mkdirSync, readFileSync } from 'fs';
26
+ import { join } from 'path';
27
+ import { homedir } from 'os';
28
+
29
+ // Database paths (with legacy fallback)
30
+ const NEW_DB_DIR = join(homedir(), '.shieldcortex');
31
+ const LEGACY_DB_DIR = join(homedir(), '.claude-cortex');
32
+
33
+ function getDbPath() {
34
+ const newPath = join(NEW_DB_DIR, 'memories.db');
35
+ const legacyPath = join(LEGACY_DB_DIR, 'memories.db');
36
+ if (existsSync(newPath) || !existsSync(legacyPath)) {
37
+ return { dir: NEW_DB_DIR, path: newPath };
38
+ }
39
+ return { dir: LEGACY_DB_DIR, path: legacyPath };
40
+ }
41
+
42
+ const { dir: DB_DIR, path: DB_PATH } = getDbPath();
43
+
44
+ // Memory limits
45
+ const MAX_SHORT_TERM_MEMORIES = 100;
46
+ const MAX_LONG_TERM_MEMORIES = 1000;
47
+ const BASE_THRESHOLD = 0.35;
48
+ const MAX_AUTO_MEMORIES = 5;
49
+
50
+ const CATEGORY_EXTRACTION_THRESHOLDS = {
51
+ architecture: 0.28,
52
+ error: 0.30,
53
+ context: 0.32,
54
+ learning: 0.32,
55
+ pattern: 0.35,
56
+ preference: 0.38,
57
+ note: 0.42,
58
+ todo: 0.40,
59
+ relationship: 0.35,
60
+ custom: 0.35,
61
+ };
62
+
63
+ // ==================== PROJECT DETECTION ====================
64
+
65
+ const SKIP_DIRECTORIES = [
66
+ 'src', 'lib', 'dist', 'build', 'out',
67
+ 'node_modules', '.git', '.next', '.cache',
68
+ 'test', 'tests', '__tests__', 'spec',
69
+ 'bin', 'scripts', 'config', 'public', 'static',
70
+ ];
71
+
72
+ function extractProjectFromPath(path) {
73
+ if (!path) return null;
74
+ const segments = path.split(/[/\\]/).filter(Boolean);
75
+ if (segments.length === 0) return null;
76
+ for (let i = segments.length - 1; i >= 0; i--) {
77
+ const segment = segments[i];
78
+ if (!SKIP_DIRECTORIES.includes(segment.toLowerCase())) {
79
+ if (segment.startsWith('.')) continue;
80
+ return segment;
81
+ }
82
+ }
83
+ return null;
84
+ }
85
+
86
+ // ==================== DYNAMIC THRESHOLD ====================
87
+
88
+ function getMemoryStats(db) {
89
+ try {
90
+ const stats = db.prepare(`
91
+ SELECT
92
+ COUNT(*) as total,
93
+ SUM(CASE WHEN type = 'short_term' THEN 1 ELSE 0 END) as shortTerm,
94
+ SUM(CASE WHEN type = 'long_term' THEN 1 ELSE 0 END) as longTerm
95
+ FROM memories
96
+ `).get();
97
+ return stats || { total: 0, shortTerm: 0, longTerm: 0 };
98
+ } catch {
99
+ return { total: 0, shortTerm: 0, longTerm: 0 };
100
+ }
101
+ }
102
+
103
+ function getDynamicThreshold(memoryCount, maxMemories) {
104
+ const fullness = memoryCount / maxMemories;
105
+ if (fullness > 0.8) return 0.50;
106
+ if (fullness > 0.6) return 0.42;
107
+ if (fullness > 0.4) return 0.35;
108
+ if (fullness > 0.2) return 0.30;
109
+ return 0.25;
110
+ }
111
+
112
+ function getExtractionThreshold(category, dynamicThreshold) {
113
+ const categoryThreshold = CATEGORY_EXTRACTION_THRESHOLDS[category] || BASE_THRESHOLD;
114
+ return Math.min(categoryThreshold, dynamicThreshold);
115
+ }
116
+
117
+ // ==================== SALIENCE DETECTION ====================
118
+
119
+ const ARCHITECTURE_KEYWORDS = [
120
+ 'architecture', 'design', 'pattern', 'structure', 'system',
121
+ 'database', 'api', 'schema', 'model', 'framework', 'stack',
122
+ 'microservice', 'monolith', 'serverless', 'infrastructure'
123
+ ];
124
+
125
+ const ERROR_KEYWORDS = [
126
+ 'error', 'bug', 'fix', 'issue', 'problem', 'crash', 'fail',
127
+ 'exception', 'debug', 'resolve', 'solution', 'workaround'
128
+ ];
129
+
130
+ const PREFERENCE_KEYWORDS = [
131
+ 'prefer', 'always', 'never', 'style', 'convention', 'standard',
132
+ 'like', 'want', 'should', 'must', 'require'
133
+ ];
134
+
135
+ const PATTERN_KEYWORDS = [
136
+ 'pattern', 'practice', 'approach', 'method', 'technique',
137
+ 'implementation', 'strategy', 'algorithm', 'workflow'
138
+ ];
139
+
140
+ const DECISION_KEYWORDS = [
141
+ 'decided', 'decision', 'chose', 'chosen', 'selected', 'going with',
142
+ 'will use', 'opted for', 'settled on', 'agreed'
143
+ ];
144
+
145
+ const LEARNING_KEYWORDS = [
146
+ 'learned', 'discovered', 'realized', 'found out', 'turns out',
147
+ 'TIL', 'now know', 'understand now', 'figured out'
148
+ ];
149
+
150
+ const EMOTIONAL_MARKERS = [
151
+ 'important', 'critical', 'crucial', 'essential', 'key',
152
+ 'finally', 'breakthrough', 'eureka', 'aha', 'got it',
153
+ 'frustrating', 'annoying', 'tricky', 'remember'
154
+ ];
155
+
156
+ const CODE_REFERENCE_PATTERNS = [
157
+ /\b[A-Z][a-zA-Z]*\.[a-zA-Z]+\b/,
158
+ /\b[a-z_][a-zA-Z0-9_]*\.(ts|js|py|go|rs)\b/,
159
+ /`[^`]+`/,
160
+ /\b(function|class|interface|type|const|let|var)\s+\w+/i,
161
+ /\bline\s*\d+\b/i,
162
+ /\b(src|lib|app|components?)\/\S+/,
163
+ ];
164
+
165
+ function detectKeywords(text, keywords) {
166
+ const lower = text.toLowerCase();
167
+ return keywords.some(keyword => lower.includes(keyword.toLowerCase()));
168
+ }
169
+
170
+ function detectCodeReferences(content) {
171
+ return CODE_REFERENCE_PATTERNS.some(pattern => pattern.test(content));
172
+ }
173
+
174
+ function detectExplicitRequest(text) {
175
+ const patterns = [
176
+ /\bremember\s+(this|that)\b/i,
177
+ /\bdon'?t\s+forget\b/i,
178
+ /\bkeep\s+(in\s+)?mind\b/i,
179
+ /\bnote\s+(this|that)\b/i,
180
+ /\bsave\s+(this|that)\b/i,
181
+ /\bimportant[:\s]/i,
182
+ /\bfor\s+future\s+reference\b/i,
183
+ ];
184
+ return patterns.some(pattern => pattern.test(text));
185
+ }
186
+
187
+ function calculateSalience(text) {
188
+ let score = 0.25;
189
+ if (detectExplicitRequest(text)) score += 0.5;
190
+ if (detectKeywords(text, ARCHITECTURE_KEYWORDS)) score += 0.4;
191
+ if (detectKeywords(text, ERROR_KEYWORDS)) score += 0.35;
192
+ if (detectKeywords(text, DECISION_KEYWORDS)) score += 0.35;
193
+ if (detectKeywords(text, LEARNING_KEYWORDS)) score += 0.3;
194
+ if (detectKeywords(text, PATTERN_KEYWORDS)) score += 0.25;
195
+ if (detectKeywords(text, PREFERENCE_KEYWORDS)) score += 0.25;
196
+ if (detectCodeReferences(text)) score += 0.15;
197
+ if (detectKeywords(text, EMOTIONAL_MARKERS)) score += 0.2;
198
+ return Math.min(1.0, score);
199
+ }
200
+
201
+ function suggestCategory(text) {
202
+ const lower = text.toLowerCase();
203
+ if (detectKeywords(lower, ARCHITECTURE_KEYWORDS)) return 'architecture';
204
+ if (detectKeywords(lower, ERROR_KEYWORDS)) return 'error';
205
+ if (detectKeywords(lower, DECISION_KEYWORDS)) return 'context';
206
+ if (detectKeywords(lower, LEARNING_KEYWORDS)) return 'learning';
207
+ if (detectKeywords(lower, PREFERENCE_KEYWORDS)) return 'preference';
208
+ if (detectKeywords(lower, PATTERN_KEYWORDS)) return 'pattern';
209
+ if (/\b(todo|fixme|hack|xxx)\b/i.test(lower)) return 'todo';
210
+ return 'note';
211
+ }
212
+
213
+ function extractTags(text, extractorName = null) {
214
+ const tags = new Set();
215
+ const hashtagMatches = text.match(/#[a-zA-Z][a-zA-Z0-9_-]*/g);
216
+ if (hashtagMatches) {
217
+ hashtagMatches.forEach(tag => tags.add(tag.slice(1).toLowerCase()));
218
+ }
219
+ const techTerms = [
220
+ 'react', 'vue', 'angular', 'node', 'python', 'typescript', 'javascript',
221
+ 'api', 'database', 'sql', 'mongodb', 'postgresql', 'mysql',
222
+ 'docker', 'kubernetes', 'aws', 'git', 'testing', 'auth', 'security'
223
+ ];
224
+ const lowerText = text.toLowerCase();
225
+ techTerms.forEach(term => {
226
+ if (lowerText.includes(term)) tags.add(term);
227
+ });
228
+ tags.add('auto-extracted');
229
+ tags.add('session-end');
230
+ if (extractorName) {
231
+ tags.add(`source:${extractorName}`);
232
+ }
233
+ return Array.from(tags).slice(0, 12);
234
+ }
235
+
236
+ function calculateFrequencyBoost(segment, allSegments) {
237
+ const commonWords = new Set([
238
+ 'about', 'after', 'before', 'being', 'between', 'could', 'during',
239
+ 'every', 'found', 'through', 'would', 'should', 'which', 'where',
240
+ 'there', 'these', 'their', 'other', 'using', 'because', 'without'
241
+ ]);
242
+ const words = segment.content.toLowerCase().split(/\s+/);
243
+ const keyTerms = words.filter(w =>
244
+ w.length > 5 && !commonWords.has(w) && /^[a-z]+$/.test(w)
245
+ );
246
+ let boost = 0;
247
+ const seenTerms = new Set();
248
+ for (const term of keyTerms) {
249
+ if (seenTerms.has(term)) continue;
250
+ seenTerms.add(term);
251
+ const mentions = allSegments.filter(s =>
252
+ s !== segment && s.content.toLowerCase().includes(term)
253
+ ).length;
254
+ if (mentions > 1) {
255
+ boost += 0.03 * Math.min(mentions, 5);
256
+ }
257
+ }
258
+ return Math.min(0.15, boost);
259
+ }
260
+
261
+ // ==================== CONTENT EXTRACTION ====================
262
+
263
+ function extractMemorableSegments(conversationText) {
264
+ const segments = [];
265
+ const extractors = [
266
+ {
267
+ name: 'decision',
268
+ patterns: [
269
+ /(?:we\s+)?decided\s+(?:to\s+)?(.{15,200})/gi,
270
+ /(?:going|went)\s+with\s+(.{15,150})/gi,
271
+ /(?:chose|chosen|selected)\s+(.{15,150})/gi,
272
+ /the\s+(?:approach|solution|fix)\s+(?:is|was)\s+(.{15,200})/gi,
273
+ /(?:using|will\s+use)\s+(.{15,150})/gi,
274
+ /(?:opted\s+for|settled\s+on)\s+(.{15,150})/gi,
275
+ ],
276
+ titlePrefix: 'Decision: ',
277
+ },
278
+ {
279
+ name: 'error-fix',
280
+ patterns: [
281
+ /(?:fixed|solved|resolved)\s+(?:by\s+)?(.{15,200})/gi,
282
+ /the\s+(?:fix|solution|workaround)\s+(?:is|was)\s+(.{15,200})/gi,
283
+ /(?:root\s+cause|issue)\s+(?:is|was)\s+(.{15,200})/gi,
284
+ /(?:error|bug)\s+(?:was\s+)?caused\s+by\s+(.{15,200})/gi,
285
+ /(?:problem|issue)\s+was\s+(.{15,150})/gi,
286
+ /(?:the\s+)?bug\s+(?:is|was)\s+(.{15,150})/gi,
287
+ /(?:debugging|debugged)\s+(.{15,150})/gi,
288
+ ],
289
+ titlePrefix: 'Fix: ',
290
+ },
291
+ {
292
+ name: 'learning',
293
+ patterns: [
294
+ /(?:learned|discovered|realized|found\s+out)\s+(?:that\s+)?(.{15,200})/gi,
295
+ /turns\s+out\s+(?:that\s+)?(.{15,200})/gi,
296
+ /(?:TIL|today\s+I\s+learned)[:\s]+(.{15,200})/gi,
297
+ /(?:now\s+)?(?:understand|know)\s+(?:that\s+)?(.{15,150})/gi,
298
+ /(?:figured\s+out|worked\s+out)\s+(.{15,150})/gi,
299
+ ],
300
+ titlePrefix: 'Learned: ',
301
+ },
302
+ {
303
+ name: 'architecture',
304
+ patterns: [
305
+ /the\s+architecture\s+(?:is|uses|consists\s+of)\s+(.{15,200})/gi,
306
+ /(?:design|pattern)\s+(?:is|uses)\s+(.{15,200})/gi,
307
+ /(?:system|api|database)\s+(?:structure|design)\s+(?:is|uses)\s+(.{15,200})/gi,
308
+ /(?:created|added|implemented|built)\s+(?:a\s+)?(.{15,200})/gi,
309
+ /(?:refactored|updated|changed)\s+(?:the\s+)?(.{15,150})/gi,
310
+ ],
311
+ titlePrefix: 'Architecture: ',
312
+ },
313
+ {
314
+ name: 'preference',
315
+ patterns: [
316
+ /(?:always|never)\s+(.{10,150})/gi,
317
+ /(?:prefer|want)\s+to\s+(.{10,150})/gi,
318
+ /(?:should|must)\s+(?:always\s+)?(.{10,150})/gi,
319
+ ],
320
+ titlePrefix: 'Preference: ',
321
+ },
322
+ {
323
+ name: 'important-note',
324
+ patterns: [
325
+ /important[:\s]+(.{15,200})/gi,
326
+ /(?:note|remember)[:\s]+(.{15,200})/gi,
327
+ /(?:key|critical)\s+(?:point|thing)[:\s]+(.{15,200})/gi,
328
+ /(?:this\s+is\s+)?(?:crucial|essential)[:\s]+(.{15,150})/gi,
329
+ /(?:don't\s+forget|keep\s+in\s+mind)[:\s]+(.{15,150})/gi,
330
+ ],
331
+ titlePrefix: 'Note: ',
332
+ },
333
+ ];
334
+
335
+ for (const extractor of extractors) {
336
+ for (const pattern of extractor.patterns) {
337
+ let match;
338
+ while ((match = pattern.exec(conversationText)) !== null) {
339
+ const content = match[1].trim();
340
+ if (content.length >= 20) {
341
+ const titleContent = content.slice(0, 50).replace(/\s+/g, ' ').trim();
342
+ const title = extractor.titlePrefix + (titleContent.length < 50 ? titleContent : titleContent + '...');
343
+ segments.push({
344
+ title,
345
+ content: content.slice(0, 500),
346
+ extractorType: extractor.name,
347
+ });
348
+ }
349
+ }
350
+ }
351
+ }
352
+
353
+ return segments;
354
+ }
355
+
356
+ function processSegments(segments, dynamicThreshold = BASE_THRESHOLD) {
357
+ const unique = [];
358
+ for (const seg of segments) {
359
+ const isDupe = unique.some(existing => {
360
+ const overlap = calculateOverlap(existing.content, seg.content);
361
+ return overlap > 0.8;
362
+ });
363
+ if (!isDupe) {
364
+ const text = seg.title + ' ' + seg.content;
365
+ const baseSalience = calculateSalience(text);
366
+ const category = suggestCategory(text);
367
+ unique.push({
368
+ ...seg,
369
+ baseSalience,
370
+ category,
371
+ tags: extractTags(text, seg.extractorType),
372
+ });
373
+ }
374
+ }
375
+
376
+ for (const seg of unique) {
377
+ const frequencyBoost = calculateFrequencyBoost(seg, unique);
378
+ seg.salience = Math.min(1.0, seg.baseSalience + frequencyBoost);
379
+ seg.frequencyBoost = frequencyBoost;
380
+ }
381
+
382
+ unique.sort((a, b) => b.salience - a.salience);
383
+
384
+ const filtered = unique.filter(seg => {
385
+ const threshold = getExtractionThreshold(seg.category, dynamicThreshold);
386
+ return seg.salience >= threshold;
387
+ });
388
+
389
+ return filtered.slice(0, MAX_AUTO_MEMORIES);
390
+ }
391
+
392
+ function calculateOverlap(text1, text2) {
393
+ const words1 = new Set(text1.toLowerCase().split(/\s+/));
394
+ const words2 = new Set(text2.toLowerCase().split(/\s+/));
395
+ const intersection = new Set([...words1].filter(w => words2.has(w)));
396
+ const union = new Set([...words1, ...words2]);
397
+ return intersection.size / union.size;
398
+ }
399
+
400
+ // ==================== DATABASE OPERATIONS ====================
401
+
402
+ function saveMemory(db, memory, project) {
403
+ const timestamp = new Date().toISOString();
404
+ const stmt = db.prepare(`
405
+ INSERT INTO memories (title, content, type, category, salience, tags, project, created_at, last_accessed)
406
+ VALUES (?, ?, 'short_term', ?, ?, ?, ?, ?, ?)
407
+ `);
408
+ stmt.run(
409
+ memory.title,
410
+ memory.content,
411
+ memory.category,
412
+ memory.salience,
413
+ JSON.stringify(memory.tags),
414
+ project || null,
415
+ timestamp,
416
+ timestamp
417
+ );
418
+ }
419
+
420
+ // ==================== TRANSCRIPT READING ====================
421
+
422
+ /**
423
+ * Read conversation text from the session transcript JSONL file.
424
+ */
425
+ function readTranscript(transcriptPath) {
426
+ if (!transcriptPath) return '';
427
+
428
+ // Expand ~ to homedir
429
+ const resolvedPath = transcriptPath.replace(/^~/, homedir());
430
+
431
+ if (!existsSync(resolvedPath)) {
432
+ console.error(`[session-end] Transcript not found: ${resolvedPath}`);
433
+ return '';
434
+ }
435
+
436
+ try {
437
+ const content = readFileSync(resolvedPath, 'utf-8');
438
+ const lines = content.trim().split('\n');
439
+
440
+ // Read last 50 lines to get recent conversation
441
+ const recentLines = lines.slice(-50);
442
+ const messages = [];
443
+
444
+ for (const line of recentLines) {
445
+ try {
446
+ const entry = JSON.parse(line);
447
+ const role = entry.type || entry.message?.role;
448
+ const msgContent = entry.message?.content;
449
+ if ((role === 'user' || role === 'assistant') && msgContent) {
450
+ const text = Array.isArray(msgContent)
451
+ ? msgContent.filter(c => c.type === 'text').map(c => c.text).join('\n')
452
+ : msgContent;
453
+ if (text && !text.startsWith('/')) {
454
+ messages.push(text);
455
+ }
456
+ }
457
+ } catch {
458
+ // Skip invalid lines
459
+ }
460
+ }
461
+
462
+ const result = messages.join('\n\n');
463
+ console.error(`[session-end] Read ${messages.length} messages from transcript (${result.length} chars)`);
464
+ return result;
465
+ } catch (err) {
466
+ console.error(`[session-end] Failed to read transcript: ${err.message}`);
467
+ return '';
468
+ }
469
+ }
470
+
471
+ // ==================== MAIN HOOK LOGIC ====================
472
+
473
+ let input = '';
474
+ process.stdin.setEncoding('utf8');
475
+
476
+ process.stdin.on('readable', () => {
477
+ let chunk;
478
+ while ((chunk = process.stdin.read()) !== null) {
479
+ input += chunk;
480
+ }
481
+ });
482
+
483
+ process.stdin.on('end', () => {
484
+ try {
485
+ const hookData = JSON.parse(input || '{}');
486
+
487
+ const reason = hookData.reason || 'unknown';
488
+ const project = extractProjectFromPath(hookData.cwd);
489
+
490
+ // Skip extraction on /clear — session is being intentionally wiped
491
+ if (reason === 'clear') {
492
+ console.error('[session-end] Session cleared, skipping extraction');
493
+ process.exit(0);
494
+ }
495
+
496
+ // Read conversation from transcript_path (provided by Claude Code)
497
+ const conversationText = readTranscript(hookData.transcript_path);
498
+
499
+ if (!conversationText || conversationText.length < 100) {
500
+ console.error('[session-end] Not enough conversation content to extract from');
501
+ process.exit(0);
502
+ }
503
+
504
+ // Ensure database directory exists
505
+ if (!existsSync(DB_DIR)) {
506
+ mkdirSync(DB_DIR, { recursive: true });
507
+ }
508
+
509
+ if (!existsSync(DB_PATH)) {
510
+ console.error('[session-end] Memory database not found, skipping extraction');
511
+ process.exit(0);
512
+ }
513
+
514
+ const db = new Database(DB_PATH, { timeout: 5000 });
515
+
516
+ const stats = getMemoryStats(db);
517
+ const totalMemories = stats.shortTerm + stats.longTerm;
518
+ const maxMemories = MAX_SHORT_TERM_MEMORIES + MAX_LONG_TERM_MEMORIES;
519
+ const dynamicThreshold = getDynamicThreshold(totalMemories, maxMemories);
520
+
521
+ console.error(`[session-end] Memory status: ${totalMemories}/${maxMemories} (${(totalMemories/maxMemories*100).toFixed(0)}% full)`);
522
+ console.error(`[session-end] Reason: ${reason}, Dynamic threshold: ${dynamicThreshold.toFixed(2)}`);
523
+
524
+ // Extract memorable segments
525
+ const segments = extractMemorableSegments(conversationText);
526
+ const processedSegments = processSegments(segments, dynamicThreshold);
527
+
528
+ let autoExtractedCount = 0;
529
+ for (const memory of processedSegments) {
530
+ try {
531
+ saveMemory(db, memory, project);
532
+ autoExtractedCount++;
533
+ const boostInfo = memory.frequencyBoost > 0 ? ` +${memory.frequencyBoost.toFixed(2)} boost` : '';
534
+ console.error(`[session-end] Saved: ${memory.title} (salience: ${memory.salience.toFixed(2)}${boostInfo}, category: ${memory.category})`);
535
+ } catch (err) {
536
+ console.error(`[session-end] Failed to save "${memory.title}": ${err.message}`);
537
+ }
538
+ }
539
+
540
+ console.error(`[session-end] Complete: ${autoExtractedCount} memories auto-extracted on session ${reason}`);
541
+
542
+ db.close();
543
+ process.exit(0);
544
+ } catch (error) {
545
+ console.error(`[session-end] Error: ${error.message}`);
546
+ process.exit(0); // Don't block session exit on errors
547
+ }
548
+ });