shieldcortex 4.28.1 → 4.29.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 (249) hide show
  1. package/dashboard/.next/standalone/dashboard/.next/BUILD_ID +1 -1
  2. package/dashboard/.next/standalone/dashboard/.next/build-manifest.json +2 -2
  3. package/dashboard/.next/standalone/dashboard/.next/prerender-manifest.json +3 -3
  4. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.html +2 -2
  5. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.rsc +1 -1
  6. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  7. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  8. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  9. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  10. package/dashboard/.next/standalone/dashboard/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  11. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.html +2 -2
  12. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.rsc +1 -1
  13. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  14. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  15. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  16. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  17. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  18. package/dashboard/.next/standalone/dashboard/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  19. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.html +1 -1
  20. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.rsc +1 -1
  21. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin/__PAGE__.segment.rsc +1 -1
  22. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk/admin.segment.rsc +1 -1
  23. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  24. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_full.segment.rsc +1 -1
  25. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_head.segment.rsc +1 -1
  26. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_index.segment.rsc +1 -1
  27. package/dashboard/.next/standalone/dashboard/.next/server/app/admin.segments/_tree.segment.rsc +1 -1
  28. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.html +1 -1
  29. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.rsc +1 -1
  30. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud/__PAGE__.segment.rsc +1 -1
  31. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk/cloud.segment.rsc +1 -1
  32. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  33. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_full.segment.rsc +1 -1
  34. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_head.segment.rsc +1 -1
  35. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_index.segment.rsc +1 -1
  36. package/dashboard/.next/standalone/dashboard/.next/server/app/cloud.segments/_tree.segment.rsc +1 -1
  37. package/dashboard/.next/standalone/dashboard/.next/server/app/index.html +1 -1
  38. package/dashboard/.next/standalone/dashboard/.next/server/app/index.rsc +1 -1
  39. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  40. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_full.segment.rsc +1 -1
  41. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_head.segment.rsc +1 -1
  42. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_index.segment.rsc +1 -1
  43. package/dashboard/.next/standalone/dashboard/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  44. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.html +1 -1
  45. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.rsc +1 -1
  46. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture/__PAGE__.segment.rsc +1 -1
  47. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory/capture.segment.rsc +1 -1
  48. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  49. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  50. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_full.segment.rsc +1 -1
  51. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_head.segment.rsc +1 -1
  52. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_index.segment.rsc +1 -1
  53. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/capture.segments/_tree.segment.rsc +1 -1
  54. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.html +1 -1
  55. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.rsc +1 -1
  56. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph/__PAGE__.segment.rsc +1 -1
  57. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory/graph.segment.rsc +1 -1
  58. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  59. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  60. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_full.segment.rsc +1 -1
  61. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_head.segment.rsc +1 -1
  62. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_index.segment.rsc +1 -1
  63. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/graph.segments/_tree.segment.rsc +1 -1
  64. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.html +1 -1
  65. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.rsc +1 -1
  66. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall/__PAGE__.segment.rsc +1 -1
  67. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory/recall.segment.rsc +1 -1
  68. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  69. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  70. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_full.segment.rsc +1 -1
  71. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_head.segment.rsc +1 -1
  72. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_index.segment.rsc +1 -1
  73. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/recall.segments/_tree.segment.rsc +1 -1
  74. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.html +2 -2
  75. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.rsc +1 -1
  76. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay/__PAGE__.segment.rsc +1 -1
  77. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory/replay.segment.rsc +1 -1
  78. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  79. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  80. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_full.segment.rsc +1 -1
  81. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_head.segment.rsc +1 -1
  82. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_index.segment.rsc +1 -1
  83. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/replay.segments/_tree.segment.rsc +1 -1
  84. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.html +1 -1
  85. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.rsc +1 -1
  86. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review/__PAGE__.segment.rsc +1 -1
  87. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory/review.segment.rsc +1 -1
  88. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  89. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  90. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_full.segment.rsc +1 -1
  91. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_head.segment.rsc +1 -1
  92. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_index.segment.rsc +1 -1
  93. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/review.segments/_tree.segment.rsc +1 -1
  94. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.html +1 -1
  95. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.rsc +1 -1
  96. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline/__PAGE__.segment.rsc +1 -1
  97. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory/timeline.segment.rsc +1 -1
  98. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  99. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  100. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_full.segment.rsc +1 -1
  101. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_head.segment.rsc +1 -1
  102. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_index.segment.rsc +1 -1
  103. package/dashboard/.next/standalone/dashboard/.next/server/app/memory/timeline.segments/_tree.segment.rsc +1 -1
  104. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.html +2 -2
  105. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.rsc +1 -1
  106. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory/__PAGE__.segment.rsc +1 -1
  107. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk/memory.segment.rsc +1 -1
  108. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  109. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_full.segment.rsc +1 -1
  110. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_head.segment.rsc +1 -1
  111. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_index.segment.rsc +1 -1
  112. package/dashboard/.next/standalone/dashboard/.next/server/app/memory.segments/_tree.segment.rsc +1 -1
  113. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.html +2 -2
  114. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.rsc +1 -1
  115. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview/__PAGE__.segment.rsc +1 -1
  116. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk/overview.segment.rsc +1 -1
  117. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  118. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_full.segment.rsc +1 -1
  119. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_head.segment.rsc +1 -1
  120. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_index.segment.rsc +1 -1
  121. package/dashboard/.next/standalone/dashboard/.next/server/app/overview.segments/_tree.segment.rsc +1 -1
  122. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.html +1 -1
  123. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.rsc +1 -1
  124. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit/__PAGE__.segment.rsc +1 -1
  125. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection/audit.segment.rsc +1 -1
  126. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  127. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  128. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_full.segment.rsc +1 -1
  129. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_head.segment.rsc +1 -1
  130. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_index.segment.rsc +1 -1
  131. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/audit.segments/_tree.segment.rsc +1 -1
  132. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.html +1 -1
  133. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.rsc +1 -1
  134. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts/__PAGE__.segment.rsc +1 -1
  135. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection/intercepts.segment.rsc +1 -1
  136. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  137. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  138. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_full.segment.rsc +1 -1
  139. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_head.segment.rsc +1 -1
  140. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_index.segment.rsc +1 -1
  141. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/intercepts.segments/_tree.segment.rsc +1 -1
  142. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.html +1 -1
  143. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.rsc +1 -1
  144. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome/__PAGE__.segment.rsc +1 -1
  145. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection/iron-dome.segment.rsc +1 -1
  146. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  147. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  148. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_full.segment.rsc +1 -1
  149. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_head.segment.rsc +1 -1
  150. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_index.segment.rsc +1 -1
  151. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/iron-dome.segments/_tree.segment.rsc +1 -1
  152. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.html +1 -1
  153. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.rsc +1 -1
  154. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies/__PAGE__.segment.rsc +1 -1
  155. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection/policies.segment.rsc +1 -1
  156. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  157. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  158. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_full.segment.rsc +1 -1
  159. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_head.segment.rsc +1 -1
  160. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_index.segment.rsc +1 -1
  161. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/policies.segments/_tree.segment.rsc +1 -1
  162. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.html +1 -1
  163. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.rsc +1 -1
  164. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine/__PAGE__.segment.rsc +1 -1
  165. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection/quarantine.segment.rsc +1 -1
  166. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  167. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  168. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_full.segment.rsc +1 -1
  169. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_head.segment.rsc +1 -1
  170. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_index.segment.rsc +1 -1
  171. package/dashboard/.next/standalone/dashboard/.next/server/app/protection/quarantine.segments/_tree.segment.rsc +1 -1
  172. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.html +2 -2
  173. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.rsc +1 -1
  174. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection/__PAGE__.segment.rsc +1 -1
  175. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk/protection.segment.rsc +1 -1
  176. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  177. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_full.segment.rsc +1 -1
  178. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_head.segment.rsc +1 -1
  179. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_index.segment.rsc +1 -1
  180. package/dashboard/.next/standalone/dashboard/.next/server/app/protection.segments/_tree.segment.rsc +1 -1
  181. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.html +2 -2
  182. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.rsc +1 -1
  183. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings/__PAGE__.segment.rsc +1 -1
  184. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk/settings.segment.rsc +1 -1
  185. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  186. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  187. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  188. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  189. package/dashboard/.next/standalone/dashboard/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  190. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.html +1 -1
  191. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.rsc +1 -1
  192. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray/__PAGE__.segment.rsc +1 -1
  193. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain/xray.segment.rsc +1 -1
  194. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
  195. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  196. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_full.segment.rsc +1 -1
  197. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_head.segment.rsc +1 -1
  198. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_index.segment.rsc +1 -1
  199. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain/xray.segments/_tree.segment.rsc +1 -1
  200. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.html +1 -1
  201. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.rsc +1 -1
  202. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain/__PAGE__.segment.rsc +1 -1
  203. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk/supply-chain.segment.rsc +1 -1
  204. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  205. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_full.segment.rsc +1 -1
  206. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_head.segment.rsc +1 -1
  207. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_index.segment.rsc +1 -1
  208. package/dashboard/.next/standalone/dashboard/.next/server/app/supply-chain.segments/_tree.segment.rsc +1 -1
  209. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.html +2 -2
  210. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.rsc +1 -1
  211. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray/__PAGE__.segment.rsc +1 -1
  212. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk/xray.segment.rsc +1 -1
  213. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/!KGRhc2hib2FyZCk.segment.rsc +1 -1
  214. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_full.segment.rsc +1 -1
  215. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_head.segment.rsc +1 -1
  216. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_index.segment.rsc +1 -1
  217. package/dashboard/.next/standalone/dashboard/.next/server/app/xray.segments/_tree.segment.rsc +1 -1
  218. package/dashboard/.next/standalone/dashboard/.next/server/pages/404.html +2 -2
  219. package/dashboard/.next/standalone/dashboard/.next/server/pages/500.html +2 -2
  220. package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.js +1 -1
  221. package/dashboard/.next/standalone/dashboard/.next/server/server-reference-manifest.json +1 -1
  222. package/dist/cli/doctor.d.ts +17 -0
  223. package/dist/cli/doctor.js +44 -0
  224. package/dist/cli/memory.d.ts +23 -0
  225. package/dist/cli/memory.js +101 -0
  226. package/dist/database/init.d.ts +9 -0
  227. package/dist/database/init.js +32 -4
  228. package/dist/database/migrations.js +126 -0
  229. package/dist/memory/consolidate.d.ts +82 -6
  230. package/dist/memory/consolidate.js +287 -117
  231. package/dist/setup/openclaw.d.ts +26 -0
  232. package/dist/setup/openclaw.js +61 -0
  233. package/dist/tools/remember.js +24 -3
  234. package/hooks/openclaw/cortex-memory/handler.ts +223 -171
  235. package/hooks/openclaw/cortex-memory/runtime.mjs +64 -0
  236. package/package.json +1 -1
  237. package/scripts/lib/dedup.mjs +99 -0
  238. package/scripts/lib/openclaw-extract.mjs +129 -0
  239. package/scripts/lib/recall-log.mjs +16 -1
  240. package/scripts/lib/recall-relevance.mjs +191 -0
  241. package/scripts/lib/salience.mjs +8 -3
  242. package/scripts/lib/save-memory.mjs +62 -6
  243. package/scripts/lib/session-context.mjs +30 -0
  244. package/scripts/postinstall.mjs +29 -10
  245. package/scripts/prompt-recall-hook.mjs +118 -15
  246. package/scripts/session-start-hook.mjs +17 -6
  247. /package/dashboard/.next/standalone/dashboard/.next/static/{N9XiRuuRX4eTtiJFa43tY → 0HpUm8SRvm9fnWVO0OBB2}/_buildManifest.js +0 -0
  248. /package/dashboard/.next/standalone/dashboard/.next/static/{N9XiRuuRX4eTtiJFa43tY → 0HpUm8SRvm9fnWVO0OBB2}/_clientMiddlewareManifest.json +0 -0
  249. /package/dashboard/.next/standalone/dashboard/.next/static/{N9XiRuuRX4eTtiJFa43tY → 0HpUm8SRvm9fnWVO0OBB2}/_ssgManifest.js +0 -0
@@ -209,6 +209,67 @@ function legacyHookDirs(hooksDir) {
209
209
  function hasRequiredHookFiles(dir) {
210
210
  return HOOK_FILES.every(file => fs.existsSync(path.join(dir, file)));
211
211
  }
212
+ /**
213
+ * The standard installed-hook destination: `~/.openclaw/hooks/cortex-memory`.
214
+ * Resolves the real user's home (sudo-aware) so doctor/postinstall agree with
215
+ * the install path.
216
+ */
217
+ export function defaultHookDestDir() {
218
+ return path.join(resolveUserHome(), '.openclaw', 'hooks', HOOK_NAME);
219
+ }
220
+ /**
221
+ * Single source of truth for "the installed hook copy is out of date".
222
+ *
223
+ * The cortex-memory hook is installed by FILE COPY (see `copyHookFiles`) into
224
+ * `~/.openclaw/hooks/cortex-memory/`. A package update does NOT automatically
225
+ * re-copy it, so the installed `handler.ts` / `runtime.mjs` can drift behind
226
+ * the package's `HOOK_SOURCE` version. This compares every HOOK_FILE in
227
+ * `destDir` against the packaged source by content.
228
+ *
229
+ * Pure + synchronous (fs reads only, no writes, no side effects). Returns
230
+ * `true` if any required file is missing from `destDir` OR differs byte-for-byte
231
+ * from the packaged source. Returns `false` only when every file is present and
232
+ * identical. On any unexpected read error it returns `true` (fail toward
233
+ * "refresh needed") so a half-readable install is never reported as current.
234
+ *
235
+ * If the package's own `HOOK_SOURCE` is missing (corrupt/partial package), the
236
+ * comparison is impossible, so this returns `false` — we can't claim the
237
+ * install is stale relative to a source we can't read.
238
+ */
239
+ export function hookFilesStale(destDir = defaultHookDestDir()) {
240
+ // No installed copy at all → definitely needs (re)install.
241
+ if (!fs.existsSync(destDir))
242
+ return true;
243
+ // No packaged source to compare against → can't prove staleness.
244
+ if (!fs.existsSync(HOOK_SOURCE))
245
+ return false;
246
+ for (const file of HOOK_FILES) {
247
+ const srcPath = path.join(HOOK_SOURCE, file);
248
+ const destPath = path.join(destDir, file);
249
+ try {
250
+ if (!fs.existsSync(srcPath)) {
251
+ // Packaged source is missing this file — can't compare it; skip.
252
+ continue;
253
+ }
254
+ if (!fs.existsSync(destPath))
255
+ return true; // installed copy missing a file
256
+ const srcBuf = fs.readFileSync(srcPath);
257
+ const destBuf = fs.readFileSync(destPath);
258
+ if (!srcBuf.equals(destBuf))
259
+ return true; // content differs → stale
260
+ }
261
+ catch {
262
+ // Unreadable file on either side — treat as stale so the user re-copies.
263
+ // DELIBERATE ASYMMETRY with the inline staleness loop in
264
+ // hooks/openclaw/cortex-memory/handler.ts (selfCheckAndHeal), which does
265
+ // NOT flip `stale` on a read error: that runs in the long-lived gateway
266
+ // and must stay quiet on transient errors. This path backs `doctor`, which
267
+ // SHOULD nag on a half-readable install. Keep them divergent.
268
+ return true;
269
+ }
270
+ }
271
+ return false;
272
+ }
212
273
  function copyHookFiles(sourceDir, destDir) {
213
274
  fs.mkdirSync(destDir, { recursive: true });
214
275
  for (const file of HOOK_FILES) {
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { z } from 'zod';
7
7
  import { addMemory, searchMemories, detectRelationships, createMemoryLink, getLastTruncationInfo } from '../memory/store.js';
8
- import { analyzeSalienceFactors, explainSalience } from '../memory/salience.js';
8
+ import { calculateSalience, analyzeSalienceFactors, explainSalience } from '../memory/salience.js';
9
9
  import { formatErrorForMcp } from '../errors.js';
10
10
  import { resolveProject } from '../context/project-context.js';
11
11
  import { shouldFilterMemory } from '../memory/save-filter.js';
@@ -116,7 +116,7 @@ export async function executeRemember(input) {
116
116
  error: `Memory filtered: ${filterResult.reason}${filterResult.warning ? ' — ' + filterResult.warning : ''}`,
117
117
  };
118
118
  }
119
- const memory = addMemory({
119
+ const memoryInput = {
120
120
  title,
121
121
  content,
122
122
  category: input.category,
@@ -129,7 +129,28 @@ export async function executeRemember(input) {
129
129
  metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
130
130
  memoryPurpose: input.memoryPurpose,
131
131
  memoryScope: input.memoryScope,
132
- }, undefined, derivedSource ?? { type: 'cli', identifier: 'mcp' });
132
+ };
133
+ // Defence-in-depth against the "salience wall": automated/hook callers
134
+ // (e.g. the OpenClaw hook, which shells out `remember` with importance:"high"
135
+ // /"critical" and sourceType:"hook") must not mint 0.8/1.0-salience memories
136
+ // the way a human deliberately saving something can. Cap the FINAL resolved
137
+ // salience — covering BOTH the importance-derived override and the
138
+ // calculateSalience fall-through — at the same 0.6 the dedicated auto-extract
139
+ // writer enforces, so even a stale/un-refactored hook can't exceed it by ANY
140
+ // path. Interactive remembers (no source, or a user/cli/agent source) stay
141
+ // uncapped — deliberate intent is honoured. Resolve salience exactly as
142
+ // addMemory does, from the SAME memoryInput object, so there is no input-shape
143
+ // drift, then clamp and pass it verbatim.
144
+ //
145
+ // Canonical constant: scripts/lib/extract-memorable-segments.mjs:24
146
+ // (AUTO_EXTRACT_SALIENCE_CAP = 0.6). It lives in a build-script .mjs outside
147
+ // the compiled src/ surface, so the value is mirrored here.
148
+ if (derivedSource?.type === 'hook') {
149
+ const AUTO_EXTRACT_SALIENCE_CAP = 0.6;
150
+ const effective = memoryInput.salience ?? calculateSalience(memoryInput);
151
+ memoryInput.salience = Math.min(effective, AUTO_EXTRACT_SALIENCE_CAP);
152
+ }
153
+ const memory = addMemory(memoryInput, undefined, derivedSource ?? { type: 'cli', identifier: 'mcp' });
133
154
  // Auto-detect and create relationships with existing memories
134
155
  let linksCreated = 0;
135
156
  try {
@@ -10,14 +10,34 @@ import { createHash } from "node:crypto";
10
10
  import fs from "node:fs/promises";
11
11
  import { homedir } from "node:os";
12
12
  import path from "node:path";
13
+ import { fileURLToPath } from "node:url";
13
14
  import { createOpenClawRuntime } from "./runtime.mjs";
14
15
 
15
16
  // ==================== SERVER COMMAND RESOLUTION ====================
16
17
 
18
+ // Transcript line format shared by the producer (getRecentMessages builds
19
+ // `${role}: ${text}`) and the consumer (assistantConversationText filters on
20
+ // this prefix). Centralised so a format change can't silently break the filter.
21
+ const ASSISTANT_PREFIX = "assistant:";
22
+
23
+ // Process-global by design: these one-shot notice flags and the load-null
24
+ // cache live for the lifetime of the long-lived gateway process. A gateway
25
+ // restart is the intended upgrade boundary that resets them.
17
26
  let _autoMemoryNoticeShown = false;
27
+ let _noExtractNoticeShown = false;
18
28
  const runtime = createOpenClawRuntime({ logPrefix: "[cortex-memory]" });
19
29
  const loadShieldConfig = runtime.loadShieldConfig;
20
30
  const callCortex = runtime.callCortex;
31
+ // Pure chunker wrapper loader (resolves the local install's hardened
32
+ // extractor). Returns null when no local install is resolvable — in which
33
+ // case auto-capture is simply skipped (we do NOT regrow the old high-salience
34
+ // bespoke-extractor path). The wrapper imports nothing native; persistence
35
+ // still flows only through callCortex's mcporter shell-out.
36
+ const loadOpenClawExtract = runtime.loadOpenClawExtract;
37
+ // Resolves the ShieldCortex package root from the resolved server binary (no
38
+ // DB access). Used by selfCheckAndHeal to compare the running hook against the
39
+ // packaged source for staleness — warn-only, never re-copies from the gateway.
40
+ const resolvePackageRoot = runtime.resolvePackageRoot;
21
41
 
22
42
  async function isOpenClawAutoMemoryEnabled() {
23
43
  const config = await loadShieldConfig();
@@ -251,67 +271,29 @@ async function scanInstalledHooks() {
251
271
  }
252
272
 
253
273
  // ==================== CONTENT EXTRACTION ====================
254
-
255
- const PATTERNS = {
256
- architecture: [
257
- /\b(?:architecture|designed|structured|pattern|approach)\b.*?(?:uses?|is|with)\b/i,
258
- /\b(?:created|implemented|refactored|built|set up)\b/i,
259
- /\b(?:decided?\s+to|going\s+with|chose|opted?\s+for|using)\b/i,
260
- ],
261
- error: [
262
- /\b(?:fixed|resolved|solved)\s+(?:by|with|using)\b/i,
263
- /\b(?:the\s+)?(?:solution|fix|root\s*cause|bug)\s+(?:was|is)\b/i,
264
- ],
265
- learning: [
266
- /\b(?:learned|discovered|turns?\s+out|figured\s+out|realized)\b/i,
267
- /\b(?:TIL|today\s+I\s+learned)\b/i,
268
- ],
269
- preference: [
270
- /\b(?:I|we|you\s+should)\s+(?:always|never)\b/i,
271
- /\b(?:always\s+use|never\s+use|never\s+commit)\b/i,
272
- /\bprefer(?:\s+to)?\s+\w+/i,
273
- /\bshould\s+always\b/i,
274
- ],
275
- note: [
276
- /\b(?:important|remember|key\s+point|crucial|note)\s*:/i,
277
- ],
278
- };
274
+ //
275
+ // Extraction is delegated to the hardened centralized chunker via the pure
276
+ // `openclaw-extract` wrapper (resolved through runtime.loadOpenClawExtract).
277
+ // The old bespoke regex extractor lived here and mislabelled categories,
278
+ // produced clause fragments, and minted high/critical-salience memories (the
279
+ // "salience wall"). It is intentionally gone — the chunker is now the single
280
+ // source of truth for extraction quality and taxonomy. Persistence below is
281
+ // uniformly importance:"normal" (0.5, capped well under the wall).
279
282
 
280
283
  /**
281
- * Extract high-salience content from session messages
282
- * @param {string[]} messages - Array of "role: content" strings
283
- * @returns {Array<{title: string, content: string, category: string}>}
284
+ * Join transcript lines into conversation text, keeping ONLY assistant-authored
285
+ * lines. getRecentMessages returns "role: content" strings for both user and
286
+ * assistant turns; for the first ship we extract from assistant text only
287
+ * (lowest-risk: don't mine user-typed prose). Returns "" if nothing qualifies.
284
288
  */
285
- function extractMemories(messages) {
286
- const extracted = [];
287
- const seen = new Set();
288
-
289
+ function assistantConversationText(messages: string[]): string {
290
+ const parts: string[] = [];
289
291
  for (const msg of messages) {
290
- if (!msg.startsWith("assistant:")) continue;
291
- const text = msg.slice("assistant:".length).trim();
292
- if (text.length < 20) continue;
293
-
294
- for (const [category, patterns] of Object.entries(PATTERNS)) {
295
- for (const pattern of patterns) {
296
- if (pattern.test(text)) {
297
- const title = text.slice(0, 80).replace(/["\n]/g, " ").trim();
298
- if (seen.has(title)) break;
299
- seen.add(title);
300
-
301
- extracted.push({
302
- title,
303
- content: text.slice(0, 500),
304
- category,
305
- });
306
- break;
307
- }
308
- }
309
- if (extracted.length >= 5) break;
310
- }
311
- if (extracted.length >= 5) break;
292
+ if (typeof msg !== "string" || !msg.startsWith(ASSISTANT_PREFIX)) continue;
293
+ const text = msg.slice(ASSISTANT_PREFIX.length).trim();
294
+ if (text.length > 0) parts.push(text);
312
295
  }
313
-
314
- return extracted;
296
+ return parts.join("\n");
315
297
  }
316
298
 
317
299
  // ==================== SESSION FILE READER ====================
@@ -338,7 +320,11 @@ async function getRecentMessages(sessionFilePath) {
338
320
  ? msg.content.find((c) => c.type === "text")?.text
339
321
  : msg.content;
340
322
  if (text && !text.startsWith("/")) {
341
- messages.push(`${msg.role}: ${text}`);
323
+ // Producer side of the transcript line format. The assistant
324
+ // prefix is tied to ASSISTANT_PREFIX so the consumer
325
+ // (assistantConversationText) filter can't silently drift.
326
+ const prefix = msg.role === "assistant" ? ASSISTANT_PREFIX : `${msg.role}:`;
327
+ messages.push(`${prefix} ${text}`);
342
328
  }
343
329
  }
344
330
  }
@@ -355,9 +341,16 @@ async function getRecentMessages(sessionFilePath) {
355
341
  // ==================== EVENT HANDLERS ====================
356
342
 
357
343
  /**
358
- * Handle command:new extract memories from ending session
344
+ * Shared session-extraction routine for both /new (onSessionEnd) and
345
+ * /stop|/clear|/exit (onSessionStop). They were ~95% identical; the only
346
+ * differences are which sessionEntry to read, the persisted tags +
347
+ * source-identifier, and the user-facing "done" message. Behaviour is
348
+ * otherwise identical — gateway-safe persistence via callCortex only.
349
+ *
350
+ * @param {object} event
351
+ * @param {{ sessionEntry: object, tags: string, sourceIdentifier: string, doneMessage: (n: number) => string }} opts
359
352
  */
360
- async function onSessionEnd(event) {
353
+ async function runSessionExtraction(event, { sessionEntry, tags, sourceIdentifier, doneMessage }) {
361
354
  if (!(await isOpenClawAutoMemoryEnabled())) {
362
355
  if (!_autoMemoryNoticeShown) {
363
356
  console.log("[cortex-memory] Auto memory extraction disabled (set openclawAutoMemory=true to enable)");
@@ -367,7 +360,6 @@ async function onSessionEnd(event) {
367
360
  }
368
361
 
369
362
  const context = event.context || {};
370
- const sessionEntry = context.previousSessionEntry || context.sessionEntry || {};
371
363
  const sessionFile = sessionEntry.sessionFile;
372
364
 
373
365
  if (!sessionFile) {
@@ -381,7 +373,22 @@ async function onSessionEnd(event) {
381
373
  return;
382
374
  }
383
375
 
384
- const memories = extractMemories(messages);
376
+ const conversationText = assistantConversationText(messages);
377
+ if (conversationText.length === 0) {
378
+ console.log("[cortex-memory] No assistant content to extract");
379
+ return;
380
+ }
381
+
382
+ const extract = await loadOpenClawExtract();
383
+ if (!extract) {
384
+ if (!_noExtractNoticeShown) {
385
+ console.log("[cortex-memory] No resolvable local install — skipping auto-extraction (no fallback)");
386
+ _noExtractNoticeShown = true;
387
+ }
388
+ return;
389
+ }
390
+
391
+ const memories = extract.extractSessionMemories(conversationText);
385
392
  if (memories.length === 0) {
386
393
  console.log("[cortex-memory] No high-salience content found");
387
394
  return;
@@ -401,12 +408,13 @@ async function onSessionEnd(event) {
401
408
  title: mem.title,
402
409
  content: mem.content,
403
410
  category: mem.category,
411
+ memoryPurpose: mem.memoryPurpose,
404
412
  project: "openclaw",
405
413
  scope: "global",
406
- importance: "high",
407
- tags: "auto-extracted,openclaw-hook",
414
+ importance: "normal",
415
+ tags,
408
416
  sourceType: "hook",
409
- sourceIdentifier: "openclaw-session-end",
417
+ sourceIdentifier,
410
418
  workspaceDir: context.workspaceDir || "",
411
419
  });
412
420
  if (result) {
@@ -420,79 +428,37 @@ async function onSessionEnd(event) {
420
428
 
421
429
  // Provide visible feedback to user
422
430
  if (saved > 0 && event.messages) {
423
- event.messages.push(`🧠 ShieldCortex: Saved ${saved} memor${saved === 1 ? 'y' : 'ies'} from this session`);
431
+ event.messages.push(doneMessage(saved));
424
432
  }
425
433
  }
426
434
 
435
+ /**
436
+ * Handle command:new — extract memories from ending session
437
+ */
438
+ async function onSessionEnd(event) {
439
+ const context = event.context || {};
440
+ await runSessionExtraction(event, {
441
+ sessionEntry: context.previousSessionEntry || context.sessionEntry || {},
442
+ tags: "auto-extracted,openclaw-hook",
443
+ sourceIdentifier: "openclaw-session-end",
444
+ doneMessage: (n) =>
445
+ `🧠 ShieldCortex: Saved ${n} memor${n === 1 ? "y" : "ies"} from this session`,
446
+ });
447
+ }
448
+
427
449
  /**
428
450
  * Handle command:stop — extract memories before session ends
429
451
  * This fires when user explicitly calls /stop
430
452
  */
431
453
  async function onSessionStop(event) {
432
- if (!(await isOpenClawAutoMemoryEnabled())) {
433
- if (!_autoMemoryNoticeShown) {
434
- console.log("[cortex-memory] Auto memory extraction disabled (set openclawAutoMemory=true to enable)");
435
- _autoMemoryNoticeShown = true;
436
- }
437
- return;
438
- }
439
-
440
454
  const context = event.context || {};
441
- const sessionEntry = context.sessionEntry || {};
442
- const sessionFile = sessionEntry.sessionFile;
443
-
444
- if (!sessionFile) {
445
- console.log("[cortex-memory] No session file found for stop, skipping extraction");
446
- return;
447
- }
448
-
449
- const messages = await getRecentMessages(sessionFile);
450
- if (messages.length === 0) {
451
- console.log("[cortex-memory] No messages to extract on stop");
452
- return;
453
- }
454
-
455
- const memories = extractMemories(messages);
456
- if (memories.length === 0) {
457
- console.log("[cortex-memory] No high-salience content found on stop");
458
- return;
459
- }
460
-
461
- const noveltyGate = await getSharedNoveltyGate();
462
- let saved = 0;
463
- let skipped = 0;
464
- for (const mem of memories) {
465
- const novelty = noveltyGate.inspect(mem.content);
466
- if (!novelty.allow) {
467
- skipped++;
468
- continue;
469
- }
470
-
471
- const result = await callCortex("remember", {
472
- title: mem.title,
473
- content: mem.content,
474
- category: mem.category,
475
- project: "openclaw",
476
- scope: "global",
477
- importance: "high",
478
- tags: "auto-extracted,openclaw-hook,session-stop",
479
- sourceType: "hook",
480
- sourceIdentifier: "openclaw-session-stop",
481
- workspaceDir: context.workspaceDir || "",
482
- });
483
- if (result) {
484
- saved++;
485
- noveltyGate.remember(mem, novelty);
486
- }
487
- }
488
- await noveltyGate.flush();
489
-
490
- console.log(`[cortex-memory] Saved ${saved}/${memories.length} memories on session stop (${skipped} skipped as duplicates)`);
491
-
492
- // Provide visible feedback to user
493
- if (saved > 0 && event.messages) {
494
- event.messages.push(`🧠 ShieldCortex: Saved ${saved} memor${saved === 1 ? 'y' : 'ies'} before session end`);
495
- }
455
+ await runSessionExtraction(event, {
456
+ sessionEntry: context.sessionEntry || {},
457
+ tags: "auto-extracted,openclaw-hook,session-stop",
458
+ sourceIdentifier: "openclaw-session-stop",
459
+ doneMessage: (n) =>
460
+ `🧠 ShieldCortex: Saved ${n} memor${n === 1 ? "y" : "ies"} before session end`,
461
+ });
496
462
  }
497
463
 
498
464
  /**
@@ -531,43 +497,54 @@ async function onBootstrap(event) {
531
497
  }
532
498
 
533
499
  /**
534
- * Keyword triggers with their categories and importance levels
535
- * Order matters: more specific triggers should come first
500
+ * Keyword trigger phrases. Order matters: more specific triggers should come
501
+ * first (the first match wins). Each entry carries the AUTHORITATIVE chunker
502
+ * extractorType for its phrase — the trigger phrase is the classification
503
+ * signal ("the fix was" → error-fix, "i prefer" → preference), so we pass it
504
+ * straight into extractKeywordMemory rather than re-guessing from content
505
+ * (which collapsed everything to `note`). Salience stays uniform across all
506
+ * triggers (importance:"normal" → 0.5, capped well under the wall); the old
507
+ * per-trigger category/importance fields are gone — they minted high/critical
508
+ * salience and mislabelled categories.
509
+ *
510
+ * extractorType must be one of the chunker's keys (EXTRACTOR_TO_CATEGORY /
511
+ * EXTRACTOR_TO_PURPOSE in extract-memorable-segments.mjs):
512
+ * decision | error-fix | learning | architecture | preference | important-note
536
513
  */
537
514
  const KEYWORD_TRIGGERS = [
538
515
  // Learning triggers
539
- { phrase: "lesson learned", category: "learning", importance: "high" },
540
- { phrase: "i learned", category: "learning", importance: "normal" },
541
- { phrase: "til:", category: "learning", importance: "normal" },
542
- { phrase: "today i learned", category: "learning", importance: "normal" },
543
-
516
+ { phrase: "lesson learned", extractorType: "learning" },
517
+ { phrase: "i learned", extractorType: "learning" },
518
+ { phrase: "til:", extractorType: "learning" },
519
+ { phrase: "today i learned", extractorType: "learning" },
520
+
544
521
  // Error/prevention triggers
545
- { phrase: "never again", category: "error", importance: "critical" },
546
- { phrase: "root cause was", category: "error", importance: "high" },
547
- { phrase: "the fix was", category: "error", importance: "high" },
548
-
522
+ { phrase: "never again", extractorType: "error-fix" },
523
+ { phrase: "root cause was", extractorType: "error-fix" },
524
+ { phrase: "the fix was", extractorType: "error-fix" },
525
+
549
526
  // Preference triggers
550
- { phrase: "always do", category: "preference", importance: "high" },
551
- { phrase: "never do", category: "preference", importance: "high" },
552
- { phrase: "i prefer", category: "preference", importance: "normal" },
553
- { phrase: "we should always", category: "preference", importance: "high" },
554
-
527
+ { phrase: "always do", extractorType: "preference" },
528
+ { phrase: "never do", extractorType: "preference" },
529
+ { phrase: "i prefer", extractorType: "preference" },
530
+ { phrase: "we should always", extractorType: "preference" },
531
+
555
532
  // Architecture/decision triggers
556
- { phrase: "we decided", category: "architecture", importance: "high" },
557
- { phrase: "decision made", category: "architecture", importance: "high" },
558
- { phrase: "going with", category: "architecture", importance: "normal" },
559
-
560
- // Explicit memory triggers (highest priority - always critical)
561
- { phrase: "remember this", category: "note", importance: "critical" },
562
- { phrase: "don't forget", category: "note", importance: "critical" },
563
- { phrase: "dont forget", category: "note", importance: "critical" },
564
- { phrase: "this is important", category: "note", importance: "critical" },
565
- { phrase: "make a note", category: "note", importance: "critical" },
566
- { phrase: "for the record", category: "note", importance: "critical" },
567
- { phrase: "note to self", category: "note", importance: "critical" },
568
- { phrase: "important:", category: "note", importance: "critical" },
569
- { phrase: "key point:", category: "note", importance: "high" },
570
- { phrase: "crucial:", category: "note", importance: "critical" },
533
+ { phrase: "we decided", extractorType: "decision" },
534
+ { phrase: "decision made", extractorType: "decision" },
535
+ { phrase: "going with", extractorType: "decision" },
536
+
537
+ // Explicit memory triggers (generic important-note)
538
+ { phrase: "remember this", extractorType: "important-note" },
539
+ { phrase: "don't forget", extractorType: "important-note" },
540
+ { phrase: "dont forget", extractorType: "important-note" },
541
+ { phrase: "this is important", extractorType: "important-note" },
542
+ { phrase: "make a note", extractorType: "important-note" },
543
+ { phrase: "for the record", extractorType: "important-note" },
544
+ { phrase: "note to self", extractorType: "important-note" },
545
+ { phrase: "important:", extractorType: "important-note" },
546
+ { phrase: "key point:", extractorType: "important-note" },
547
+ { phrase: "crucial:", extractorType: "important-note" },
571
548
  ];
572
549
 
573
550
  /**
@@ -604,35 +581,62 @@ async function checkAndSaveKeywordTrigger(messageText, event) {
604
581
  content = messageText;
605
582
  }
606
583
 
607
- const title = content.slice(0, 80).replace(/["\n]/g, " ").trim();
584
+ // Route through the chunker wrapper: applies the rejection corpus (drops true
585
+ // malformations) and derives category + memory_purpose from the chunker's
586
+ // taxonomy. Explicit keyword intent BYPASSES the salience threshold (B8) —
587
+ // the wrapper returns a memory for any non-malformed content.
588
+ const extract = await loadOpenClawExtract();
589
+ if (!extract) {
590
+ if (!_noExtractNoticeShown) {
591
+ console.log("[cortex-memory] No resolvable local install — skipping keyword capture (no fallback)");
592
+ _noExtractNoticeShown = true;
593
+ }
594
+ return false;
595
+ }
596
+
597
+ // The trigger phrase carries the authoritative classification — pass its
598
+ // extractorType so the wrapper pins category/purpose instead of re-guessing
599
+ // from content (which collapsed typed triggers to `note`).
600
+ const candidates = extract.extractKeywordMemory(content, matchedTrigger.extractorType);
601
+ if (candidates.length === 0) {
602
+ console.log(`[cortex-memory] Keyword trigger skipped (rejected as malformed): "${matchedTrigger.phrase}"`);
603
+ return false;
604
+ }
605
+ const mem = candidates[0];
608
606
 
609
607
  // Deduplicate via shared novelty gate (same gate used by session-end/stop extraction)
610
608
  const noveltyGate = await getSharedNoveltyGate();
611
- const novelty = noveltyGate.inspect(content.slice(0, 500));
609
+ const novelty = noveltyGate.inspect(mem.content);
612
610
  if (!novelty.allow) {
613
- console.log(`[cortex-memory] Keyword trigger skipped (duplicate): "${title}"`);
611
+ console.log(`[cortex-memory] Keyword trigger skipped (duplicate): "${mem.title}"`);
612
+ // M2: an EXPLICIT "remember this" must never be silently dropped — make the
613
+ // dedup decision visible even though we skip the duplicate store.
614
+ if (event.messages) {
615
+ event.messages.push(`🧠 Already remembered.`);
616
+ }
614
617
  return false;
615
618
  }
616
619
 
617
620
  const result = await callCortex("remember", {
618
- title,
619
- content: content.slice(0, 500),
620
- category: matchedTrigger.category,
621
+ title: mem.title,
622
+ content: mem.content,
623
+ category: mem.category,
624
+ memoryPurpose: mem.memoryPurpose,
621
625
  project: "openclaw",
622
626
  scope: "global",
623
- importance: matchedTrigger.importance,
627
+ importance: "normal",
624
628
  tags: `keyword-trigger,openclaw-hook,trigger:${matchedTrigger.phrase.replace(/\s+/g, "-")}`,
625
629
  sourceType: "hook",
626
630
  sourceIdentifier: `openclaw-keyword:${matchedTrigger.phrase.replace(/\s+/g, "-")}`,
627
631
  });
628
632
 
629
633
  if (result) {
630
- noveltyGate.remember({ content: content.slice(0, 500), title, category: matchedTrigger.category }, novelty);
634
+ noveltyGate.remember({ content: mem.content, title: mem.title, category: mem.category }, novelty);
631
635
  await noveltyGate.flush();
632
636
  if (event.messages) {
633
- event.messages.push(`✅ Saved to Cortex memory (${matchedTrigger.category}): "${title}"`);
637
+ event.messages.push(`✅ Saved to Cortex memory (${mem.category}): "${mem.title}"`);
634
638
  }
635
- console.log(`[cortex-memory] Keyword trigger "${matchedTrigger.phrase}" saved: ${title}`);
639
+ console.log(`[cortex-memory] Keyword trigger "${matchedTrigger.phrase}" saved: ${mem.title}`);
636
640
  return true;
637
641
  }
638
642
  return false;
@@ -724,8 +728,11 @@ async function selfCheckAndHeal(event) {
724
728
  const { homedir } = await import("node:os");
725
729
  const home = homedir();
726
730
 
727
- // Where am I running from?
728
- const myDir = path.dirname(new URL(import.meta.url).pathname);
731
+ // Where am I running from? Use fileURLToPath, not URL.pathname — the latter
732
+ // does NOT decode percent-encoding, so an install path with spaces/special
733
+ // chars would yield a path that fails every downstream fs read (staleness
734
+ // comparison + self-heal copy below).
735
+ const myDir = path.dirname(fileURLToPath(import.meta.url));
729
736
 
730
737
  // Expected locations (newest first)
731
738
  const expectedDirs = [
@@ -761,6 +768,51 @@ async function selfCheckAndHeal(event) {
761
768
  }
762
769
  }
763
770
 
771
+ // Task 6b: staleness signal. The hook is installed by file-copy, so a
772
+ // package update can leave THIS running copy behind the packaged source
773
+ // (e.g. an OpenClaw version-lag where the global package is newer than
774
+ // the hook last copied into ~/.openclaw). Compare our running files
775
+ // against the package's hooks/openclaw/cortex-memory source by content.
776
+ //
777
+ // WARN-ONLY by design — we do NOT re-copy from inside the long-lived
778
+ // gateway. Re-copying would overwrite the very files this process is
779
+ // executing from, racing any concurrently-bootstrapping agent's jiti
780
+ // load. The real auto-refresh happens in the npm postinstall; the
781
+ // user-invoked repair is `shieldcortex openclaw install` (also surfaced
782
+ // by `shieldcortex doctor`). No DB, no persistence — pure fs reads.
783
+ try {
784
+ const root = await resolvePackageRoot();
785
+ if (root) {
786
+ const sourceDir = path.join(root, "hooks", "openclaw", "cortex-memory");
787
+ const hookFiles = ["HOOK.md", "handler.ts", "runtime.mjs"];
788
+ let stale = false;
789
+ for (const file of hookFiles) {
790
+ const srcPath = path.join(sourceDir, file);
791
+ const minePath = path.join(myDir, file);
792
+ try {
793
+ const srcBuf = await fs.readFile(srcPath);
794
+ const mineBuf = await fs.readFile(minePath);
795
+ if (!srcBuf.equals(mineBuf)) { stale = true; break; }
796
+ } catch {
797
+ // Source file missing/unreadable (can't prove staleness for it)
798
+ // or our own file unreadable — don't flip `stale` on a read error.
799
+ // DELIBERATE ASYMMETRY with src/setup/openclaw.ts `hookFilesStale`,
800
+ // which returns `true` (stale) on a read error so the doctor nags
801
+ // on a broken install. Here we stay quiet: this runs inside the
802
+ // long-lived gateway, where a transient read error must not emit a
803
+ // spurious bootstrap "out of date" warning. Keep them divergent.
804
+ }
805
+ }
806
+ if (stale) {
807
+ console.warn(
808
+ "[cortex-memory] Installed hook is OUT OF DATE — it differs from the " +
809
+ "packaged version. Run `shieldcortex openclaw install` to refresh it " +
810
+ "(then restart the gateway) so memory capture uses the latest logic."
811
+ );
812
+ }
813
+ }
814
+ } catch { /* staleness check is best-effort — never blocks bootstrap */ }
815
+
764
816
  return; // All good
765
817
  }
766
818