@nxuss/lemma 1.37.0 → 1.39.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 (284) hide show
  1. package/README.md +9 -6
  2. package/bin/brain-ingest.js +86 -27
  3. package/bin/doctor.js +31 -4
  4. package/bin/init.js +98 -60
  5. package/dashboard/dist/assets/index-DNTQXLER.css +1 -0
  6. package/dashboard/dist/assets/index-DzL_Zu3m.js +452 -0
  7. package/dashboard/dist/index.html +2 -2
  8. package/dist/cjs/cli/gitHooks.d.ts +9 -2
  9. package/dist/cjs/cli/gitHooks.d.ts.map +1 -1
  10. package/dist/cjs/cli/gitHooks.js +31 -4
  11. package/dist/cjs/cli/gitHooks.js.map +1 -1
  12. package/dist/cjs/cli/hostHooks.d.ts +13 -1
  13. package/dist/cjs/cli/hostHooks.d.ts.map +1 -1
  14. package/dist/cjs/cli/hostHooks.js +34 -4
  15. package/dist/cjs/cli/hostHooks.js.map +1 -1
  16. package/dist/cjs/cli/lemma-proxy.d.ts.map +1 -1
  17. package/dist/cjs/cli/lemma-proxy.js +42 -5
  18. package/dist/cjs/cli/lemma-proxy.js.map +1 -1
  19. package/dist/cjs/infra/analyzers/index.d.ts +0 -2
  20. package/dist/cjs/infra/analyzers/index.d.ts.map +1 -1
  21. package/dist/cjs/infra/analyzers/index.js +1 -6
  22. package/dist/cjs/infra/analyzers/index.js.map +1 -1
  23. package/dist/cjs/infra/cli.d.ts +4 -0
  24. package/dist/cjs/infra/cli.d.ts.map +1 -1
  25. package/dist/cjs/infra/cli.js +6 -199
  26. package/dist/cjs/infra/cli.js.map +1 -1
  27. package/dist/cjs/infra/index.d.ts +1 -3
  28. package/dist/cjs/infra/index.d.ts.map +1 -1
  29. package/dist/cjs/infra/index.js +1 -16
  30. package/dist/cjs/infra/index.js.map +1 -1
  31. package/dist/cjs/infra/mcp-tools.d.ts.map +1 -1
  32. package/dist/cjs/infra/mcp-tools.js +8 -453
  33. package/dist/cjs/infra/mcp-tools.js.map +1 -1
  34. package/dist/cjs/infra/types.d.ts +0 -101
  35. package/dist/cjs/infra/types.d.ts.map +1 -1
  36. package/dist/cjs/infra/types.js +2 -1
  37. package/dist/cjs/infra/types.js.map +1 -1
  38. package/dist/cjs/mcp/index.js +33 -10
  39. package/dist/cjs/mcp/index.js.map +1 -1
  40. package/dist/cjs/mcp/prompts.d.ts +1 -1
  41. package/dist/cjs/mcp/prompts.d.ts.map +1 -1
  42. package/dist/cjs/mcp/prompts.js +8 -21
  43. package/dist/cjs/mcp/prompts.js.map +1 -1
  44. package/dist/cjs/mcp/tool-profiles.d.ts +8 -3
  45. package/dist/cjs/mcp/tool-profiles.d.ts.map +1 -1
  46. package/dist/cjs/mcp/tool-profiles.js +25 -54
  47. package/dist/cjs/mcp/tool-profiles.js.map +1 -1
  48. package/dist/cjs/mcp/tools/memory.d.ts +8 -0
  49. package/dist/cjs/mcp/tools/memory.d.ts.map +1 -1
  50. package/dist/cjs/mcp/tools/memory.js +154 -125
  51. package/dist/cjs/mcp/tools/memory.js.map +1 -1
  52. package/dist/cjs/mcp/tools.d.ts.map +1 -1
  53. package/dist/cjs/mcp/tools.js +11 -6
  54. package/dist/cjs/mcp/tools.js.map +1 -1
  55. package/dist/cjs/mcp/workspaceShared.d.ts.map +1 -1
  56. package/dist/cjs/mcp/workspaceShared.js +13 -12
  57. package/dist/cjs/mcp/workspaceShared.js.map +1 -1
  58. package/dist/cjs/proxy/ProjectRegistry.d.ts +44 -0
  59. package/dist/cjs/proxy/ProjectRegistry.d.ts.map +1 -1
  60. package/dist/cjs/proxy/ProjectRegistry.js +92 -3
  61. package/dist/cjs/proxy/ProjectRegistry.js.map +1 -1
  62. package/dist/cjs/subconscious/HostRecall.d.ts +36 -3
  63. package/dist/cjs/subconscious/HostRecall.d.ts.map +1 -1
  64. package/dist/cjs/subconscious/HostRecall.js +164 -37
  65. package/dist/cjs/subconscious/HostRecall.js.map +1 -1
  66. package/dist/cjs/subconscious/NarrowEvidence.d.ts +47 -0
  67. package/dist/cjs/subconscious/NarrowEvidence.d.ts.map +1 -0
  68. package/dist/cjs/subconscious/NarrowEvidence.js +252 -0
  69. package/dist/cjs/subconscious/NarrowEvidence.js.map +1 -0
  70. package/dist/cjs/subconscious/TheBrainV2.d.ts +37 -0
  71. package/dist/cjs/subconscious/TheBrainV2.d.ts.map +1 -1
  72. package/dist/cjs/subconscious/TheBrainV2.js +147 -15
  73. package/dist/cjs/subconscious/TheBrainV2.js.map +1 -1
  74. package/dist/cjs/subconscious/freshness/LocalFsResolver.d.ts.map +1 -1
  75. package/dist/cjs/subconscious/freshness/LocalFsResolver.js +17 -0
  76. package/dist/cjs/subconscious/freshness/LocalFsResolver.js.map +1 -1
  77. package/dist/cjs/subconscious/recallDigest.d.ts +42 -0
  78. package/dist/cjs/subconscious/recallDigest.d.ts.map +1 -0
  79. package/dist/cjs/subconscious/recallDigest.js +94 -0
  80. package/dist/cjs/subconscious/recallDigest.js.map +1 -0
  81. package/dist/cjs/utils/OtherLanguageSymbols.d.ts +31 -0
  82. package/dist/cjs/utils/OtherLanguageSymbols.d.ts.map +1 -0
  83. package/dist/cjs/utils/OtherLanguageSymbols.js +283 -0
  84. package/dist/cjs/utils/OtherLanguageSymbols.js.map +1 -0
  85. package/dist/cjs/utils/SavingsLedger.d.ts +27 -0
  86. package/dist/cjs/utils/SavingsLedger.d.ts.map +1 -1
  87. package/dist/cjs/utils/SavingsLedger.js +51 -0
  88. package/dist/cjs/utils/SavingsLedger.js.map +1 -1
  89. package/dist/cjs/utils/StoreDraft.d.ts +12 -0
  90. package/dist/cjs/utils/StoreDraft.d.ts.map +1 -1
  91. package/dist/cjs/utils/StoreDraft.js +53 -1
  92. package/dist/cjs/utils/StoreDraft.js.map +1 -1
  93. package/dist/cjs/utils/SymbolSurgicalContext.d.ts +2 -0
  94. package/dist/cjs/utils/SymbolSurgicalContext.d.ts.map +1 -1
  95. package/dist/cjs/utils/SymbolSurgicalContext.js +1 -0
  96. package/dist/cjs/utils/SymbolSurgicalContext.js.map +1 -1
  97. package/dist/cjs/utils/reportSavings.d.ts +17 -4
  98. package/dist/cjs/utils/reportSavings.d.ts.map +1 -1
  99. package/dist/cjs/utils/reportSavings.js +67 -22
  100. package/dist/cjs/utils/reportSavings.js.map +1 -1
  101. package/dist/esm/cli/gitHooks.d.ts +9 -2
  102. package/dist/esm/cli/gitHooks.d.ts.map +1 -1
  103. package/dist/esm/cli/gitHooks.js +31 -4
  104. package/dist/esm/cli/gitHooks.js.map +1 -1
  105. package/dist/esm/cli/hostHooks.d.ts +13 -1
  106. package/dist/esm/cli/hostHooks.d.ts.map +1 -1
  107. package/dist/esm/cli/hostHooks.js +32 -3
  108. package/dist/esm/cli/hostHooks.js.map +1 -1
  109. package/dist/esm/cli/lemma-proxy.d.ts.map +1 -1
  110. package/dist/esm/cli/lemma-proxy.js +42 -5
  111. package/dist/esm/cli/lemma-proxy.js.map +1 -1
  112. package/dist/esm/infra/analyzers/index.d.ts +0 -2
  113. package/dist/esm/infra/analyzers/index.d.ts.map +1 -1
  114. package/dist/esm/infra/analyzers/index.js +0 -2
  115. package/dist/esm/infra/analyzers/index.js.map +1 -1
  116. package/dist/esm/infra/cli.d.ts +4 -0
  117. package/dist/esm/infra/cli.d.ts.map +1 -1
  118. package/dist/esm/infra/cli.js +6 -199
  119. package/dist/esm/infra/cli.js.map +1 -1
  120. package/dist/esm/infra/index.d.ts +1 -3
  121. package/dist/esm/infra/index.d.ts.map +1 -1
  122. package/dist/esm/infra/index.js +1 -3
  123. package/dist/esm/infra/index.js.map +1 -1
  124. package/dist/esm/infra/mcp-tools.d.ts.map +1 -1
  125. package/dist/esm/infra/mcp-tools.js +9 -454
  126. package/dist/esm/infra/mcp-tools.js.map +1 -1
  127. package/dist/esm/infra/types.d.ts +0 -101
  128. package/dist/esm/infra/types.d.ts.map +1 -1
  129. package/dist/esm/infra/types.js +2 -1
  130. package/dist/esm/infra/types.js.map +1 -1
  131. package/dist/esm/mcp/index.js +33 -10
  132. package/dist/esm/mcp/index.js.map +1 -1
  133. package/dist/esm/mcp/prompts.d.ts +1 -1
  134. package/dist/esm/mcp/prompts.d.ts.map +1 -1
  135. package/dist/esm/mcp/prompts.js +8 -21
  136. package/dist/esm/mcp/prompts.js.map +1 -1
  137. package/dist/esm/mcp/tool-profiles.d.ts +8 -3
  138. package/dist/esm/mcp/tool-profiles.d.ts.map +1 -1
  139. package/dist/esm/mcp/tool-profiles.js +25 -54
  140. package/dist/esm/mcp/tool-profiles.js.map +1 -1
  141. package/dist/esm/mcp/tools/memory.d.ts +8 -0
  142. package/dist/esm/mcp/tools/memory.d.ts.map +1 -1
  143. package/dist/esm/mcp/tools/memory.js +156 -128
  144. package/dist/esm/mcp/tools/memory.js.map +1 -1
  145. package/dist/esm/mcp/tools.d.ts.map +1 -1
  146. package/dist/esm/mcp/tools.js +12 -7
  147. package/dist/esm/mcp/tools.js.map +1 -1
  148. package/dist/esm/mcp/workspaceShared.d.ts.map +1 -1
  149. package/dist/esm/mcp/workspaceShared.js +13 -12
  150. package/dist/esm/mcp/workspaceShared.js.map +1 -1
  151. package/dist/esm/proxy/ProjectRegistry.d.ts +44 -0
  152. package/dist/esm/proxy/ProjectRegistry.d.ts.map +1 -1
  153. package/dist/esm/proxy/ProjectRegistry.js +91 -2
  154. package/dist/esm/proxy/ProjectRegistry.js.map +1 -1
  155. package/dist/esm/subconscious/HostRecall.d.ts +36 -3
  156. package/dist/esm/subconscious/HostRecall.d.ts.map +1 -1
  157. package/dist/esm/subconscious/HostRecall.js +159 -36
  158. package/dist/esm/subconscious/HostRecall.js.map +1 -1
  159. package/dist/esm/subconscious/NarrowEvidence.d.ts +47 -0
  160. package/dist/esm/subconscious/NarrowEvidence.d.ts.map +1 -0
  161. package/dist/esm/subconscious/NarrowEvidence.js +211 -0
  162. package/dist/esm/subconscious/NarrowEvidence.js.map +1 -0
  163. package/dist/esm/subconscious/TheBrainV2.d.ts +37 -0
  164. package/dist/esm/subconscious/TheBrainV2.d.ts.map +1 -1
  165. package/dist/esm/subconscious/TheBrainV2.js +146 -14
  166. package/dist/esm/subconscious/TheBrainV2.js.map +1 -1
  167. package/dist/esm/subconscious/freshness/LocalFsResolver.d.ts.map +1 -1
  168. package/dist/esm/subconscious/freshness/LocalFsResolver.js +17 -0
  169. package/dist/esm/subconscious/freshness/LocalFsResolver.js.map +1 -1
  170. package/dist/esm/subconscious/recallDigest.d.ts +42 -0
  171. package/dist/esm/subconscious/recallDigest.d.ts.map +1 -0
  172. package/dist/esm/subconscious/recallDigest.js +87 -0
  173. package/dist/esm/subconscious/recallDigest.js.map +1 -0
  174. package/dist/esm/utils/OtherLanguageSymbols.d.ts +31 -0
  175. package/dist/esm/utils/OtherLanguageSymbols.d.ts.map +1 -0
  176. package/dist/esm/utils/OtherLanguageSymbols.js +275 -0
  177. package/dist/esm/utils/OtherLanguageSymbols.js.map +1 -0
  178. package/dist/esm/utils/SavingsLedger.d.ts +27 -0
  179. package/dist/esm/utils/SavingsLedger.d.ts.map +1 -1
  180. package/dist/esm/utils/SavingsLedger.js +51 -0
  181. package/dist/esm/utils/SavingsLedger.js.map +1 -1
  182. package/dist/esm/utils/StoreDraft.d.ts +12 -0
  183. package/dist/esm/utils/StoreDraft.d.ts.map +1 -1
  184. package/dist/esm/utils/StoreDraft.js +52 -1
  185. package/dist/esm/utils/StoreDraft.js.map +1 -1
  186. package/dist/esm/utils/SymbolSurgicalContext.d.ts +2 -0
  187. package/dist/esm/utils/SymbolSurgicalContext.d.ts.map +1 -1
  188. package/dist/esm/utils/SymbolSurgicalContext.js +1 -1
  189. package/dist/esm/utils/SymbolSurgicalContext.js.map +1 -1
  190. package/dist/esm/utils/reportSavings.d.ts +17 -4
  191. package/dist/esm/utils/reportSavings.d.ts.map +1 -1
  192. package/dist/esm/utils/reportSavings.js +65 -22
  193. package/dist/esm/utils/reportSavings.js.map +1 -1
  194. package/package.json +2 -1
  195. package/dashboard/dist/assets/index-BoeQau6n.css +0 -1
  196. package/dashboard/dist/assets/index-Clf3qR64.js +0 -451
  197. package/dist/cjs/infra/analyzers/DriftDetector.d.ts +0 -4
  198. package/dist/cjs/infra/analyzers/DriftDetector.d.ts.map +0 -1
  199. package/dist/cjs/infra/analyzers/DriftDetector.js +0 -88
  200. package/dist/cjs/infra/analyzers/DriftDetector.js.map +0 -1
  201. package/dist/cjs/infra/analyzers/InfraAnalyzer.d.ts +0 -3
  202. package/dist/cjs/infra/analyzers/InfraAnalyzer.d.ts.map +0 -1
  203. package/dist/cjs/infra/analyzers/InfraAnalyzer.js +0 -73
  204. package/dist/cjs/infra/analyzers/InfraAnalyzer.js.map +0 -1
  205. package/dist/cjs/infra/config.d.ts +0 -17
  206. package/dist/cjs/infra/config.d.ts.map +0 -1
  207. package/dist/cjs/infra/config.js +0 -111
  208. package/dist/cjs/infra/config.js.map +0 -1
  209. package/dist/cjs/infra/errorCause.d.ts +0 -36
  210. package/dist/cjs/infra/errorCause.d.ts.map +0 -1
  211. package/dist/cjs/infra/errorCause.js +0 -143
  212. package/dist/cjs/infra/errorCause.js.map +0 -1
  213. package/dist/cjs/infra/providers/InfraProvider.d.ts +0 -9
  214. package/dist/cjs/infra/providers/InfraProvider.d.ts.map +0 -1
  215. package/dist/cjs/infra/providers/InfraProvider.js +0 -3
  216. package/dist/cjs/infra/providers/InfraProvider.js.map +0 -1
  217. package/dist/cjs/infra/providers/JenkinsProvider.d.ts +0 -16
  218. package/dist/cjs/infra/providers/JenkinsProvider.d.ts.map +0 -1
  219. package/dist/cjs/infra/providers/JenkinsProvider.js +0 -193
  220. package/dist/cjs/infra/providers/JenkinsProvider.js.map +0 -1
  221. package/dist/cjs/infra/providers/OKDProvider.d.ts +0 -24
  222. package/dist/cjs/infra/providers/OKDProvider.d.ts.map +0 -1
  223. package/dist/cjs/infra/providers/OKDProvider.js +0 -296
  224. package/dist/cjs/infra/providers/OKDProvider.js.map +0 -1
  225. package/dist/cjs/infra/providers/TerraformProvider.d.ts +0 -17
  226. package/dist/cjs/infra/providers/TerraformProvider.d.ts.map +0 -1
  227. package/dist/cjs/infra/providers/TerraformProvider.js +0 -111
  228. package/dist/cjs/infra/providers/TerraformProvider.js.map +0 -1
  229. package/dist/cjs/infra/providers/index.d.ts +0 -9
  230. package/dist/cjs/infra/providers/index.d.ts.map +0 -1
  231. package/dist/cjs/infra/providers/index.js +0 -34
  232. package/dist/cjs/infra/providers/index.js.map +0 -1
  233. package/dist/cjs/infra/templates/jenkins/index.d.ts +0 -15
  234. package/dist/cjs/infra/templates/jenkins/index.d.ts.map +0 -1
  235. package/dist/cjs/infra/templates/jenkins/index.js +0 -128
  236. package/dist/cjs/infra/templates/jenkins/index.js.map +0 -1
  237. package/dist/cjs/infra/templates/okd/index.d.ts +0 -31
  238. package/dist/cjs/infra/templates/okd/index.d.ts.map +0 -1
  239. package/dist/cjs/infra/templates/okd/index.js +0 -149
  240. package/dist/cjs/infra/templates/okd/index.js.map +0 -1
  241. package/dist/esm/infra/analyzers/DriftDetector.d.ts +0 -4
  242. package/dist/esm/infra/analyzers/DriftDetector.d.ts.map +0 -1
  243. package/dist/esm/infra/analyzers/DriftDetector.js +0 -84
  244. package/dist/esm/infra/analyzers/DriftDetector.js.map +0 -1
  245. package/dist/esm/infra/analyzers/InfraAnalyzer.d.ts +0 -3
  246. package/dist/esm/infra/analyzers/InfraAnalyzer.d.ts.map +0 -1
  247. package/dist/esm/infra/analyzers/InfraAnalyzer.js +0 -70
  248. package/dist/esm/infra/analyzers/InfraAnalyzer.js.map +0 -1
  249. package/dist/esm/infra/config.d.ts +0 -17
  250. package/dist/esm/infra/config.d.ts.map +0 -1
  251. package/dist/esm/infra/config.js +0 -101
  252. package/dist/esm/infra/config.js.map +0 -1
  253. package/dist/esm/infra/errorCause.d.ts +0 -36
  254. package/dist/esm/infra/errorCause.d.ts.map +0 -1
  255. package/dist/esm/infra/errorCause.js +0 -138
  256. package/dist/esm/infra/errorCause.js.map +0 -1
  257. package/dist/esm/infra/providers/InfraProvider.d.ts +0 -9
  258. package/dist/esm/infra/providers/InfraProvider.d.ts.map +0 -1
  259. package/dist/esm/infra/providers/InfraProvider.js +0 -2
  260. package/dist/esm/infra/providers/InfraProvider.js.map +0 -1
  261. package/dist/esm/infra/providers/JenkinsProvider.d.ts +0 -16
  262. package/dist/esm/infra/providers/JenkinsProvider.d.ts.map +0 -1
  263. package/dist/esm/infra/providers/JenkinsProvider.js +0 -186
  264. package/dist/esm/infra/providers/JenkinsProvider.js.map +0 -1
  265. package/dist/esm/infra/providers/OKDProvider.d.ts +0 -24
  266. package/dist/esm/infra/providers/OKDProvider.d.ts.map +0 -1
  267. package/dist/esm/infra/providers/OKDProvider.js +0 -292
  268. package/dist/esm/infra/providers/OKDProvider.js.map +0 -1
  269. package/dist/esm/infra/providers/TerraformProvider.d.ts +0 -17
  270. package/dist/esm/infra/providers/TerraformProvider.d.ts.map +0 -1
  271. package/dist/esm/infra/providers/TerraformProvider.js +0 -107
  272. package/dist/esm/infra/providers/TerraformProvider.js.map +0 -1
  273. package/dist/esm/infra/providers/index.d.ts +0 -9
  274. package/dist/esm/infra/providers/index.d.ts.map +0 -1
  275. package/dist/esm/infra/providers/index.js +0 -27
  276. package/dist/esm/infra/providers/index.js.map +0 -1
  277. package/dist/esm/infra/templates/jenkins/index.d.ts +0 -15
  278. package/dist/esm/infra/templates/jenkins/index.d.ts.map +0 -1
  279. package/dist/esm/infra/templates/jenkins/index.js +0 -124
  280. package/dist/esm/infra/templates/jenkins/index.js.map +0 -1
  281. package/dist/esm/infra/templates/okd/index.d.ts +0 -31
  282. package/dist/esm/infra/templates/okd/index.d.ts.map +0 -1
  283. package/dist/esm/infra/templates/okd/index.js +0 -142
  284. package/dist/esm/infra/templates/okd/index.js.map +0 -1
@@ -14,7 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  return (mod && mod.__esModule) ? mod : { "default": mod };
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.TheBrainV2 = exports.MAX_DERIVED_DEPTH = exports.BloomFilter = void 0;
17
+ exports.TheBrainV2 = exports.MAX_DERIVED_DEPTH = exports.BloomFilter = exports.TOKENIZER_VERSION = void 0;
18
18
  exports.resetBrainKeyCache = resetBrainKeyCache;
19
19
  exports.listSnapshotNames = listSnapshotNames;
20
20
  exports.mergeEntryMaps = mergeEntryMaps;
@@ -658,6 +658,14 @@ function tokenize(text) {
658
658
  'cada', 'otra', 'otro', 'otras', 'otros', 'entre', 'sobre', 'sin', 'ya', 'tan', 'mas',
659
659
  'lo', 'le', 'les', 'nos', 'os', 'ni', 'sino', 'porque', 'cuando', 'donde', 'quien',
660
660
  'cual', 'cuales', 'sea', 'ha', 'han', 'hemos', 'habia', 'habían', 'esta', 'están',
661
+ // Conversational filler. Prompts are written to a person ("can you please help me…",
662
+ // "necesito que realmente…"), and these words outweighed the topic when measuring how much
663
+ // of a prompt a memory covers. They name no subject a memory could be about.
664
+ 'please', 'help', 'know', 'want', 'like', 'just', 'really', 'actually', 'maybe', 'also', 'let',
665
+ 'me', 'my', 'we', 'our', 'us', 'you', 'your', 'i', 'im', 'get', 'got', 'make', 'sure', 'thing', 'things',
666
+ 'por', 'favor', 'necesito', 'quiero', 'puedes', 'podemos', 'podrias', 'haz', 'hacer', 'dime', 'ayuda',
667
+ 'ayudame', 'realmente', 'actualmente', 'tambien', 'solo', 'algo', 'cosa', 'cosas', 'nos', 'tu', 'yo',
668
+ 'me', 'mi', 'mis', 'te', 'ver', 'bien',
661
669
  ]);
662
670
  const terms = normalized
663
671
  .split(/\s+/)
@@ -679,7 +687,25 @@ function tokenize(text) {
679
687
  const synonymTags = terms
680
688
  .map(t => SYNONYM_CLUSTERS.get(t))
681
689
  .filter((c) => c !== undefined);
682
- return [...new Set([...terms, ...bigrams, ...stems, ...synonymTags])];
690
+ // 8. English/Spanish cognates share a root once their suffix is dropped: "description" and
691
+ // "descripcion", "configuration"/"configuracion", "velocity"/"velocidad", "automatic"/
692
+ // "automatico". Same additive rule as stems and synonyms.
693
+ const cognateTags = terms.map(cognate).filter((c) => c !== undefined);
694
+ return [...new Set([...terms, ...bigrams, ...stems, ...synonymTags, ...cognateTags])];
695
+ }
696
+ /**
697
+ * Bump whenever tokenize() changes what it emits. Terms are computed once, at store time, and
698
+ * persisted, so a tokenizer improvement (stems, diacritics, synonym groups) used to reach new
699
+ * memories only — every memory already in the Brain kept the vocabulary it was stored with.
700
+ * rebuildIndex() re-tokenizes any entry indexed under another version.
701
+ */
702
+ exports.TOKENIZER_VERSION = 6;
703
+ /** (Re)computes an entry's index terms with the current tokenizer. */
704
+ function indexTerms(entry) {
705
+ const terms = tokenize(`${entry.query} ${entry.response || ''}`);
706
+ entry.terms = [...new Set(terms)];
707
+ entry.termFreq = termFrequencies(terms);
708
+ entry.tokv = exports.TOKENIZER_VERSION;
683
709
  }
684
710
  // Groups of interchangeable dev-vocabulary terms (bilingual). Each member maps to a shared
685
711
  // `syn_<canonical>` token so any two synonyms in the same group become a shared index bucket
@@ -689,14 +715,43 @@ function tokenize(text) {
689
715
  const SYNONYM_GROUPS = [
690
716
  ['jwt', 'token', 'session', 'auth', 'login', 'autenticacion', 'sesion', 'autenticar'],
691
717
  ['timeout', 'expiration', 'expiry', 'vencimiento', 'caducidad', 'expirar', 'vencer'],
692
- ['bug', 'error', 'fallo', 'falla', 'issue', 'defect', 'defecto'],
718
+ ['bug', 'error', 'fallo', 'falla', 'issue', 'defect', 'defecto', 'fail', 'fails', 'failing', 'failed', 'fallar', 'fallaba'],
693
719
  ['fix', 'patch', 'solucion', 'solucionar', 'arreglar', 'corregir', 'hotfix'],
694
720
  ['delete', 'remove', 'eliminar', 'borrar', 'quitar'],
695
721
  ['config', 'configuration', 'configuracion', 'settings', 'ajustes'],
696
722
  ['deploy', 'deployment', 'despliegue', 'desplegar', 'release'],
697
- ['crash', 'exception', 'excepcion', 'throw', 'falla'],
723
+ ['crash', 'exception', 'excepcion', 'throw'],
698
724
  ['slow', 'lento', 'lentitud', 'latency', 'latencia', 'performance', 'rendimiento'],
699
725
  ['test', 'tests', 'testing', 'prueba', 'pruebas', 'spec'],
726
+ // Everyday words a bilingual corpus splits across languages: a Spanish memory and an English
727
+ // question about the same thing otherwise share no term at all.
728
+ ['change', 'changes', 'changed', 'cambio', 'cambios', 'cambiar', 'cambia', 'cambiado'],
729
+ ['active', 'activo', 'activos', 'activa', 'activas', 'enabled', 'habilitado'],
730
+ ['file', 'files', 'archivo', 'archivos', 'fichero'],
731
+ ['search', 'searches', 'buscar', 'busqueda', 'busca', 'find'],
732
+ ['memory', 'memories', 'memoria', 'memorias'],
733
+ ['write', 'writes', 'escribir', 'escribe', 'escritura'],
734
+ ['read', 'reads', 'leer', 'lee', 'lectura', 'lecturas'],
735
+ ['build', 'compile', 'compilar', 'compila', 'compilacion'],
736
+ ['publish', 'published', 'publicar', 'publicado', 'publicada', 'publicacion'],
737
+ ['comment', 'comments', 'comentario', 'comentarios'],
738
+ ['string', 'strings', 'cadena', 'cadenas'],
739
+ ['server', 'servidor'],
740
+ ['tool', 'tools', 'herramienta', 'herramientas'],
741
+ ['project', 'projects', 'proyecto', 'proyectos'],
742
+ ['broken', 'breaks', 'roto', 'rota', 'rompe', 'romper', 'rompia'],
743
+ ['missing', 'falta', 'faltante', 'faltaba'],
744
+ ['ignore', 'ignored', 'ignores', 'ignora', 'ignorar', 'ignorado', 'ignoraba'],
745
+ ['update', 'updated', 'actualizar', 'actualiza', 'actualizacion'],
746
+ ['stale', 'outdated', 'desactualizado', 'desactualizada', 'obsoleto', 'obsoleta'],
747
+ ['restart', 'reconnect', 'reiniciar', 'reconectar'],
748
+ ['wrong', 'incorrect', 'incorrecto', 'incorrecta', 'erroneo'],
749
+ // Money vocabulary: "¿por qué el saldo sale negativo?" shared only "negativo" with the memory
750
+ // that answers it ("why the ledger was negative") — and that with every "falso negativo".
751
+ ['ledger', 'saldo', 'balance', 'bitacora'],
752
+ ['negative', 'negativo', 'negativa', 'negativos', 'negativas'],
753
+ ['cost', 'costs', 'costo', 'costos', 'gasto', 'gastos', 'spent', 'spend', 'charge', 'charged', 'cobro', 'cobrar', 'cobrado', 'cobraba'],
754
+ ['savings', 'saving', 'saved', 'ahorro', 'ahorros', 'ahorrar', 'ahorra'],
700
755
  ];
701
756
  const SYNONYM_CLUSTERS = new Map();
702
757
  for (const group of SYNONYM_GROUPS) {
@@ -704,6 +759,24 @@ for (const group of SYNONYM_GROUPS) {
704
759
  for (const member of group)
705
760
  SYNONYM_CLUSTERS.set(member, canonical);
706
761
  }
762
+ const COGNATE_RULES = [
763
+ [/(?:tions?|ciones|cion)$/, 'tion'],
764
+ [/(?:ities|ity|idades|idad)$/, 'ity'],
765
+ [/(?:ically|icamente)$/, 'ic'],
766
+ [/(?:ics?|icos?|icas?)$/, 'ic'],
767
+ ];
768
+ /** `cog_<root><suffix>` for a word with an English/Spanish cognate suffix, else undefined. */
769
+ function cognate(term) {
770
+ if (term.length < 6 || term.includes('_'))
771
+ return undefined;
772
+ for (const [re, kind] of COGNATE_RULES) {
773
+ if (re.test(term)) {
774
+ const root = term.replace(re, '');
775
+ return root.length >= 3 ? `cog_${root}_${kind}` : undefined;
776
+ }
777
+ }
778
+ return undefined;
779
+ }
707
780
  // Suffix-stripping rules, longest/most-specific match first. Additive expansion only —
708
781
  // this is not a correctness-critical stemmer, so mild over-stemming (merging two distinct
709
782
  // words into one stem) is an acceptable recall/precision trade: it can only ever add a
@@ -1317,7 +1390,9 @@ class TheBrainV2 {
1317
1390
  // index.json. It is a pure derivation of the entries, so reconstructing it is the
1318
1391
  // only way it can never disagree with them — and a stale or half-written index.json
1319
1392
  // used to be able to hide entries from search entirely while they sat on disk intact.
1320
- this.rebuildIndex();
1393
+ // Entries indexed by an older tokenizer were re-tokenized: write that back once.
1394
+ if (this.rebuildIndex() > 0)
1395
+ this.scheduleSave();
1321
1396
  this.recalcAvgDocLength();
1322
1397
  }
1323
1398
  catch (err) {
@@ -1343,7 +1418,12 @@ class TheBrainV2 {
1343
1418
  // A merge can replace an id's entry with a peer's newer version whose query differs, so
1344
1419
  // the memo is rebuilt alongside the index rather than trusted across one.
1345
1420
  this.queryTermCache.clear();
1421
+ let retokenized = 0;
1346
1422
  for (const entry of this.entries.values()) {
1423
+ if (entry.tokv !== exports.TOKENIZER_VERSION) {
1424
+ indexTerms(entry);
1425
+ retokenized++;
1426
+ }
1347
1427
  for (const term of entry.terms) {
1348
1428
  let ids = this.invertedIndex.get(term);
1349
1429
  if (!ids) {
@@ -1353,6 +1433,7 @@ class TheBrainV2 {
1353
1433
  ids.add(entry.id);
1354
1434
  }
1355
1435
  }
1436
+ return retokenized;
1356
1437
  }
1357
1438
  /**
1358
1439
  * Pull in anything another process wrote since we last touched the corpus.
@@ -1651,6 +1732,7 @@ class TheBrainV2 {
1651
1732
  response: response.trim(),
1652
1733
  terms: [...new Set(terms)],
1653
1734
  termFreq,
1735
+ tokv: exports.TOKENIZER_VERSION,
1654
1736
  provider,
1655
1737
  timestamp: options.timestamp || new Date().toISOString(),
1656
1738
  hits: 0,
@@ -1762,17 +1844,15 @@ class TheBrainV2 {
1762
1844
  }
1763
1845
  // 2b. Scope to the calling project. Entries with no projectId predate scoping and stay
1764
1846
  // visible everywhere — dropping a user's existing memories to enforce a new field would
1765
- // look exactly like the Brain losing data. If scoping leaves nothing, fall back to the
1766
- // unscoped candidates rather than reporting a miss the Brain could have answered.
1767
- if (options.projectId) {
1768
- const scoped = new Set([...candidateIds].filter((id) => {
1847
+ // look exactly like the Brain losing data — but they are labelled 'unscoped' in the result.
1848
+ // Another project's memories are never returned unless the caller asks for allProjects:
1849
+ // this used to fall back to every project's candidates whenever the caller's own had none,
1850
+ // so a project with an empty Brain was answered from someone else's.
1851
+ if (options.projectId && !options.allProjects) {
1852
+ for (const id of [...candidateIds]) {
1769
1853
  const owner = this.entries.get(id)?.projectId;
1770
- return owner === undefined || owner === options.projectId;
1771
- }));
1772
- if (scoped.size > 0 || options.strictProject) {
1773
- candidateIds.clear();
1774
- for (const id of scoped)
1775
- candidateIds.add(id);
1854
+ if (owner !== undefined && owner !== options.projectId)
1855
+ candidateIds.delete(id);
1776
1856
  }
1777
1857
  }
1778
1858
  if (candidateIds.size === 0) {
@@ -1918,6 +1998,11 @@ class TheBrainV2 {
1918
1998
  ...(r.entry.outcome ? { outcome: r.entry.outcome } : {}),
1919
1999
  ...(claims && claims.length > 0 ? { claims } : {}),
1920
2000
  ...(r.entry.domain ? { domain: r.entry.domain } : {}),
2001
+ ...(r.entry.projectId === undefined
2002
+ ? { scope: 'unscoped' }
2003
+ : options.projectId && r.entry.projectId !== options.projectId
2004
+ ? { scope: 'other-project', ownerProject: r.entry.projectId }
2005
+ : {}),
1921
2006
  ...(cosmeticChanges && cosmeticChanges.length > 0 ? { cosmeticChanges } : {}),
1922
2007
  };
1923
2008
  });
@@ -2007,6 +2092,36 @@ class TheBrainV2 {
2007
2092
  }
2008
2093
  return results;
2009
2094
  }
2095
+ /**
2096
+ * Give memories stored before projects existed to the project their evidence lives in.
2097
+ *
2098
+ * An unscoped memory is visible to every project, so one project's notes surface in another's
2099
+ * searches. When all the code it tracks sits inside `root`, there is no doubt whose it is, and
2100
+ * it is stamped with `projectId`. A memory that tracks nothing, or tracks files outside `root`,
2101
+ * is left alone: nothing proves who it belongs to, and guessing would hide it from the project
2102
+ * that does own it. Returns how many were adopted.
2103
+ */
2104
+ adoptUnscopedByEvidence(projectId, root) {
2105
+ const base = root.endsWith(path_1.default.sep) ? root : root + path_1.default.sep;
2106
+ let adopted = 0;
2107
+ for (const entry of this.entries.values()) {
2108
+ if (entry.projectId !== undefined)
2109
+ continue;
2110
+ const tracked = [
2111
+ ...Object.keys(entry.fileHashes || {}),
2112
+ ...Object.keys(entry.symbolHashes || {}).map((k) => k.substring(0, k.lastIndexOf('::'))),
2113
+ ];
2114
+ if (tracked.length === 0)
2115
+ continue;
2116
+ if (!tracked.every((abs) => path_1.default.resolve(abs).startsWith(base)))
2117
+ continue;
2118
+ entry.projectId = projectId;
2119
+ adopted++;
2120
+ }
2121
+ if (adopted > 0)
2122
+ this.scheduleSave();
2123
+ return adopted;
2124
+ }
2010
2125
  embeddingSidecar() {
2011
2126
  if (!this.sidecar)
2012
2127
  this.sidecar = new BrainEmbeddings_1.EmbeddingSidecar(EMBEDDINGS_FILE);
@@ -2120,6 +2235,21 @@ class TheBrainV2 {
2120
2235
  * whether a reuse happened. Unknown ids fail silently (a peer may have forgotten the
2121
2236
  * entry since the search ranked it); savings attribution must never break a search.
2122
2237
  */
2238
+ /** Inverse document frequency of one index term over the whole corpus (BM25's formula). */
2239
+ termIdf(term) {
2240
+ this.syncIfChanged();
2241
+ const N = this.entries.size;
2242
+ const df = this.invertedIndex.get(term)?.size ?? 0;
2243
+ return Math.log((N - df + 0.5) / (df + 0.5) + 1);
2244
+ }
2245
+ /** One reuse of a memory the agent chose and read (see search_memory's shortlist). */
2246
+ recordReuse(id) {
2247
+ const entry = this.entries.get(id);
2248
+ if (!entry)
2249
+ return;
2250
+ entry.hits++;
2251
+ this.scheduleSave();
2252
+ }
2123
2253
  creditSavings(id, tokens) {
2124
2254
  if (!Number.isFinite(tokens) || tokens <= 0)
2125
2255
  return;
@@ -2252,6 +2382,7 @@ class TheBrainV2 {
2252
2382
  const terms = tokenize(keeper.query + ' ' + keeper.response);
2253
2383
  keeper.terms = [...new Set(terms)];
2254
2384
  keeper.termFreq = termFrequencies(terms);
2385
+ keeper.tokv = exports.TOKENIZER_VERSION;
2255
2386
  keeper.charCount = keeper.query.length + keeper.response.length;
2256
2387
  this.entries.set(keepId, keeper);
2257
2388
  for (const term of keeper.terms) {
@@ -2695,6 +2826,7 @@ class TheBrainV2 {
2695
2826
  const terms = tokenize(entry.query + ' ' + entry.response);
2696
2827
  entry.terms = [...new Set(terms)];
2697
2828
  entry.termFreq = termFrequencies(terms);
2829
+ entry.tokv = exports.TOKENIZER_VERSION;
2698
2830
  entry.charCount = entry.query.length + entry.response.length;
2699
2831
  // Claims supplied in this patch were just hashed by buildClaims; the helper re-anchors the
2700
2832
  // ones carried over, so either way the entry's evidence describes the code as it is now.