sensemaking 0.15.4 → 0.17.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 (435) hide show
  1. package/README.md +33 -5
  2. package/dist/cjs/chunk/extract.d.cts +2 -0
  3. package/dist/cjs/chunk/extract.d.ts +2 -0
  4. package/dist/cjs/chunk/extract.js +139 -0
  5. package/dist/cjs/chunk/extract.js.map +1 -0
  6. package/dist/cjs/chunk/group.d.cts +4 -0
  7. package/dist/cjs/chunk/group.d.ts +4 -0
  8. package/dist/cjs/chunk/group.js +489 -0
  9. package/dist/cjs/chunk/group.js.map +1 -0
  10. package/dist/cjs/chunk/index.d.cts +8 -0
  11. package/dist/cjs/chunk/index.d.ts +8 -0
  12. package/dist/cjs/chunk/index.js +44 -0
  13. package/dist/cjs/chunk/index.js.map +1 -0
  14. package/dist/cjs/chunk/parse.d.cts +2 -0
  15. package/dist/cjs/chunk/parse.d.ts +2 -0
  16. package/dist/cjs/chunk/parse.js +71 -0
  17. package/dist/cjs/chunk/parse.js.map +1 -0
  18. package/dist/cjs/chunk/types.d.cts +19 -0
  19. package/dist/cjs/chunk/types.d.ts +19 -0
  20. package/dist/cjs/chunk/types.js +5 -0
  21. package/dist/cjs/chunk/types.js.map +1 -0
  22. package/dist/cjs/chunk/version.d.cts +1 -0
  23. package/dist/cjs/chunk/version.d.ts +1 -0
  24. package/dist/cjs/chunk/version.js +14 -0
  25. package/dist/cjs/chunk/version.js.map +1 -0
  26. package/dist/cjs/cli/download.js +12 -11
  27. package/dist/cjs/cli/download.js.map +1 -1
  28. package/dist/cjs/cli/index.d.cts +1 -1
  29. package/dist/cjs/cli/index.d.ts +1 -1
  30. package/dist/cjs/cli/index.js +1 -1
  31. package/dist/cjs/cli/index.js.map +1 -1
  32. package/dist/cjs/cli/init.js +31 -5
  33. package/dist/cjs/cli/init.js.map +1 -1
  34. package/dist/cjs/cli/map.js +1 -1
  35. package/dist/cjs/cli/map.js.map +1 -1
  36. package/dist/cjs/cli/named.js +1 -1
  37. package/dist/cjs/cli/named.js.map +1 -1
  38. package/dist/cjs/cli/path.js +2 -2
  39. package/dist/cjs/cli/path.js.map +1 -1
  40. package/dist/cjs/cli/peek.js +1 -1
  41. package/dist/cjs/cli/peek.js.map +1 -1
  42. package/dist/cjs/cli/related.js +1 -1
  43. package/dist/cjs/cli/related.js.map +1 -1
  44. package/dist/cjs/cli/search.js +1 -1
  45. package/dist/cjs/cli/search.js.map +1 -1
  46. package/dist/cjs/cli/shared.d.cts +1 -1
  47. package/dist/cjs/cli/shared.d.ts +1 -1
  48. package/dist/cjs/cli/shared.js +3 -3
  49. package/dist/cjs/cli/shared.js.map +1 -1
  50. package/dist/cjs/cli/status.js +344 -100
  51. package/dist/cjs/cli/status.js.map +1 -1
  52. package/dist/cjs/commands/map.d.cts +1 -1
  53. package/dist/cjs/commands/map.d.ts +1 -1
  54. package/dist/cjs/commands/map.js.map +1 -1
  55. package/dist/cjs/commands/peek.d.cts +1 -1
  56. package/dist/cjs/commands/peek.d.ts +1 -1
  57. package/dist/cjs/commands/peek.js +13 -6
  58. package/dist/cjs/commands/peek.js.map +1 -1
  59. package/dist/cjs/commands/related.js +17 -13
  60. package/dist/cjs/commands/related.js.map +1 -1
  61. package/dist/cjs/commands/scope.js +1 -1
  62. package/dist/cjs/commands/scope.js.map +1 -1
  63. package/dist/cjs/commands/search.d.cts +1 -1
  64. package/dist/cjs/commands/search.d.ts +1 -1
  65. package/dist/cjs/commands/search.js +28 -99
  66. package/dist/cjs/commands/search.js.map +1 -1
  67. package/dist/cjs/commands/signals.d.cts +18 -0
  68. package/dist/cjs/commands/signals.d.ts +18 -0
  69. package/dist/cjs/commands/signals.js +299 -0
  70. package/dist/cjs/commands/signals.js.map +1 -0
  71. package/dist/cjs/commands/status.d.cts +2 -2
  72. package/dist/cjs/commands/status.d.ts +2 -2
  73. package/dist/cjs/commands/status.js +1 -1
  74. package/dist/cjs/commands/status.js.map +1 -1
  75. package/dist/cjs/config/access.d.cts +8 -3
  76. package/dist/cjs/config/access.d.ts +8 -3
  77. package/dist/cjs/config/access.js +35 -17
  78. package/dist/cjs/config/access.js.map +1 -1
  79. package/dist/cjs/config/index.d.cts +5 -1
  80. package/dist/cjs/config/index.d.ts +5 -1
  81. package/dist/cjs/config/index.js +16 -2
  82. package/dist/cjs/config/index.js.map +1 -1
  83. package/dist/cjs/config/load.d.cts +6 -1
  84. package/dist/cjs/config/load.d.ts +6 -1
  85. package/dist/cjs/config/load.js +83 -8
  86. package/dist/cjs/config/load.js.map +1 -1
  87. package/dist/cjs/config/resolve.js +1 -1
  88. package/dist/cjs/config/resolve.js.map +1 -1
  89. package/dist/cjs/config/signals.d.cts +4 -0
  90. package/dist/cjs/config/signals.d.ts +4 -0
  91. package/dist/cjs/config/signals.js +30 -0
  92. package/dist/cjs/config/signals.js.map +1 -0
  93. package/dist/cjs/config/types.d.cts +7 -4
  94. package/dist/cjs/config/types.d.ts +7 -4
  95. package/dist/cjs/config/types.js +1 -1
  96. package/dist/cjs/config/types.js.map +1 -1
  97. package/dist/cjs/config/validate.d.cts +1 -0
  98. package/dist/cjs/config/validate.d.ts +1 -0
  99. package/dist/cjs/config/validate.js +127 -11
  100. package/dist/cjs/config/validate.js.map +1 -1
  101. package/dist/cjs/db/open.d.cts +1 -1
  102. package/dist/cjs/db/open.d.ts +1 -1
  103. package/dist/cjs/db/open.js +9 -4
  104. package/dist/cjs/db/open.js.map +1 -1
  105. package/dist/cjs/db/reconcile.d.cts +1 -0
  106. package/dist/cjs/db/reconcile.d.ts +1 -0
  107. package/dist/cjs/db/reconcile.js +23 -8
  108. package/dist/cjs/db/reconcile.js.map +1 -1
  109. package/dist/cjs/{sql-functions.js → db/sql-functions.js} +1 -1
  110. package/dist/cjs/db/sql-functions.js.map +1 -0
  111. package/dist/cjs/embed/cohere.d.cts +2 -0
  112. package/dist/cjs/embed/cohere.d.ts +2 -0
  113. package/dist/cjs/embed/cohere.js +238 -0
  114. package/dist/cjs/embed/cohere.js.map +1 -0
  115. package/dist/cjs/embed/http.d.cts +2 -0
  116. package/dist/cjs/embed/http.d.ts +2 -0
  117. package/dist/cjs/embed/http.js +258 -0
  118. package/dist/cjs/embed/http.js.map +1 -0
  119. package/dist/cjs/embed/identity.d.cts +13 -0
  120. package/dist/cjs/embed/identity.d.ts +13 -0
  121. package/dist/cjs/embed/identity.js +194 -0
  122. package/dist/cjs/embed/identity.js.map +1 -0
  123. package/dist/cjs/embed/langfit.d.cts +6 -0
  124. package/dist/cjs/embed/langfit.d.ts +6 -0
  125. package/dist/cjs/embed/langfit.js +286 -0
  126. package/dist/cjs/embed/langfit.js.map +1 -0
  127. package/dist/cjs/embed/languages.d.cts +3 -0
  128. package/dist/cjs/embed/languages.d.ts +3 -0
  129. package/dist/cjs/embed/languages.js +98 -0
  130. package/dist/cjs/embed/languages.js.map +1 -0
  131. package/dist/cjs/embed/openai.d.cts +2 -0
  132. package/dist/cjs/embed/openai.d.ts +2 -0
  133. package/dist/cjs/embed/openai.js +268 -0
  134. package/dist/cjs/embed/openai.js.map +1 -0
  135. package/dist/cjs/embed/query.d.cts +21 -0
  136. package/dist/cjs/embed/query.d.ts +21 -0
  137. package/dist/cjs/embed/query.js +610 -0
  138. package/dist/cjs/embed/query.js.map +1 -0
  139. package/dist/cjs/embed/registry.d.cts +3 -0
  140. package/dist/cjs/embed/registry.d.ts +3 -0
  141. package/dist/cjs/embed/registry.js +114 -0
  142. package/dist/cjs/embed/registry.js.map +1 -0
  143. package/dist/cjs/embed/static.d.cts +2 -0
  144. package/dist/cjs/embed/static.d.ts +2 -0
  145. package/dist/cjs/embed/static.js +330 -0
  146. package/dist/cjs/embed/static.js.map +1 -0
  147. package/dist/cjs/embed/store.d.cts +8 -0
  148. package/dist/cjs/embed/store.d.ts +8 -0
  149. package/dist/cjs/embed/store.js +498 -0
  150. package/dist/cjs/embed/store.js.map +1 -0
  151. package/dist/cjs/embed/types.d.cts +8 -0
  152. package/dist/cjs/embed/types.d.ts +8 -0
  153. package/dist/cjs/embed/types.js +7 -0
  154. package/dist/cjs/embed/types.js.map +1 -0
  155. package/dist/cjs/errors.d.cts +1 -1
  156. package/dist/cjs/errors.d.ts +1 -1
  157. package/dist/cjs/errors.js.map +1 -1
  158. package/dist/cjs/features/embed.d.cts +2 -28
  159. package/dist/cjs/features/embed.d.ts +2 -28
  160. package/dist/cjs/features/embed.js +39 -1027
  161. package/dist/cjs/features/embed.js.map +1 -1
  162. package/dist/cjs/{fences.js → features/fences.js} +1 -1
  163. package/dist/cjs/features/fences.js.map +1 -0
  164. package/dist/cjs/features/links.js +1 -1
  165. package/dist/cjs/features/links.js.map +1 -1
  166. package/dist/cjs/features/rank.js +1 -1
  167. package/dist/cjs/features/rank.js.map +1 -1
  168. package/dist/cjs/features/sections.js +4 -3
  169. package/dist/cjs/features/sections.js.map +1 -1
  170. package/dist/cjs/features/tags.js +1 -1
  171. package/dist/cjs/features/tags.js.map +1 -1
  172. package/dist/cjs/features/types.d.cts +4 -2
  173. package/dist/cjs/features/types.d.ts +4 -2
  174. package/dist/cjs/graph/graph.js.map +1 -0
  175. package/dist/cjs/graph/traverse.js.map +1 -0
  176. package/dist/cjs/index.d.cts +4 -4
  177. package/dist/cjs/index.d.ts +4 -4
  178. package/dist/cjs/index.js +4 -1
  179. package/dist/cjs/index.js.map +1 -1
  180. package/dist/cjs/output/column-hint.js.map +1 -0
  181. package/dist/cjs/{output.d.cts → output/output.d.cts} +2 -2
  182. package/dist/cjs/{output.d.ts → output/output.d.ts} +2 -2
  183. package/dist/cjs/{output.js → output/output.js} +9 -2
  184. package/dist/cjs/output/output.js.map +1 -0
  185. package/dist/cjs/output/progress.js.map +1 -0
  186. package/dist/cjs/{search-error.js → output/search-error.js} +1 -1
  187. package/dist/cjs/output/search-error.js.map +1 -0
  188. package/dist/cjs/scan/frontmatter.d.cts +13 -0
  189. package/dist/cjs/scan/frontmatter.d.ts +13 -0
  190. package/dist/cjs/scan/frontmatter.js +229 -0
  191. package/dist/cjs/scan/frontmatter.js.map +1 -0
  192. package/dist/cjs/scan/index.d.cts +25 -0
  193. package/dist/cjs/scan/index.d.ts +25 -0
  194. package/dist/cjs/scan/index.js +107 -0
  195. package/dist/cjs/scan/index.js.map +1 -0
  196. package/dist/cjs/scan/list.d.cts +12 -0
  197. package/dist/cjs/scan/list.d.ts +12 -0
  198. package/dist/cjs/scan/list.js +154 -0
  199. package/dist/cjs/scan/list.js.map +1 -0
  200. package/dist/cjs/text/segment.d.cts +3 -0
  201. package/dist/cjs/text/segment.d.ts +3 -0
  202. package/dist/cjs/text/segment.js +154 -0
  203. package/dist/cjs/text/segment.js.map +1 -0
  204. package/dist/cjs/text/strip.d.cts +3 -0
  205. package/dist/cjs/text/strip.d.ts +3 -0
  206. package/dist/cjs/text/strip.js +32 -0
  207. package/dist/cjs/text/strip.js.map +1 -0
  208. package/dist/esm/chunk/extract.d.ts +2 -0
  209. package/dist/esm/chunk/extract.js +114 -0
  210. package/dist/esm/chunk/extract.js.map +1 -0
  211. package/dist/esm/chunk/group.d.ts +4 -0
  212. package/dist/esm/chunk/group.js +253 -0
  213. package/dist/esm/chunk/group.js.map +1 -0
  214. package/dist/esm/chunk/index.d.ts +8 -0
  215. package/dist/esm/chunk/index.js +16 -0
  216. package/dist/esm/chunk/index.js.map +1 -0
  217. package/dist/esm/chunk/parse.d.ts +2 -0
  218. package/dist/esm/chunk/parse.js +63 -0
  219. package/dist/esm/chunk/parse.js.map +1 -0
  220. package/dist/esm/chunk/types.d.ts +19 -0
  221. package/dist/esm/chunk/types.js +2 -0
  222. package/dist/esm/chunk/types.js.map +1 -0
  223. package/dist/esm/chunk/version.d.ts +1 -0
  224. package/dist/esm/chunk/version.js +3 -0
  225. package/dist/esm/chunk/version.js.map +1 -0
  226. package/dist/esm/cli/download.js +9 -8
  227. package/dist/esm/cli/download.js.map +1 -1
  228. package/dist/esm/cli/index.d.ts +1 -1
  229. package/dist/esm/cli/index.js +1 -1
  230. package/dist/esm/cli/index.js.map +1 -1
  231. package/dist/esm/cli/init.js +32 -6
  232. package/dist/esm/cli/init.js.map +1 -1
  233. package/dist/esm/cli/map.js +1 -1
  234. package/dist/esm/cli/map.js.map +1 -1
  235. package/dist/esm/cli/named.js +1 -1
  236. package/dist/esm/cli/named.js.map +1 -1
  237. package/dist/esm/cli/path.js +2 -2
  238. package/dist/esm/cli/path.js.map +1 -1
  239. package/dist/esm/cli/peek.js +1 -1
  240. package/dist/esm/cli/peek.js.map +1 -1
  241. package/dist/esm/cli/related.js +1 -1
  242. package/dist/esm/cli/related.js.map +1 -1
  243. package/dist/esm/cli/search.js +1 -1
  244. package/dist/esm/cli/search.js.map +1 -1
  245. package/dist/esm/cli/shared.d.ts +1 -1
  246. package/dist/esm/cli/shared.js +3 -3
  247. package/dist/esm/cli/shared.js.map +1 -1
  248. package/dist/esm/cli/status.js +37 -9
  249. package/dist/esm/cli/status.js.map +1 -1
  250. package/dist/esm/commands/map.d.ts +1 -1
  251. package/dist/esm/commands/map.js.map +1 -1
  252. package/dist/esm/commands/peek.d.ts +1 -1
  253. package/dist/esm/commands/peek.js +8 -1
  254. package/dist/esm/commands/peek.js.map +1 -1
  255. package/dist/esm/commands/related.js +14 -10
  256. package/dist/esm/commands/related.js.map +1 -1
  257. package/dist/esm/commands/scope.js +1 -1
  258. package/dist/esm/commands/scope.js.map +1 -1
  259. package/dist/esm/commands/search.d.ts +1 -1
  260. package/dist/esm/commands/search.js +30 -81
  261. package/dist/esm/commands/search.js.map +1 -1
  262. package/dist/esm/commands/signals.d.ts +18 -0
  263. package/dist/esm/commands/signals.js +78 -0
  264. package/dist/esm/commands/signals.js.map +1 -0
  265. package/dist/esm/commands/status.d.ts +2 -2
  266. package/dist/esm/commands/status.js +2 -2
  267. package/dist/esm/commands/status.js.map +1 -1
  268. package/dist/esm/config/access.d.ts +8 -3
  269. package/dist/esm/config/access.js +34 -15
  270. package/dist/esm/config/access.js.map +1 -1
  271. package/dist/esm/config/index.d.ts +5 -1
  272. package/dist/esm/config/index.js +3 -1
  273. package/dist/esm/config/index.js.map +1 -1
  274. package/dist/esm/config/load.d.ts +6 -1
  275. package/dist/esm/config/load.js +67 -9
  276. package/dist/esm/config/load.js.map +1 -1
  277. package/dist/esm/config/resolve.js +2 -2
  278. package/dist/esm/config/resolve.js.map +1 -1
  279. package/dist/esm/config/signals.d.ts +4 -0
  280. package/dist/esm/config/signals.js +14 -0
  281. package/dist/esm/config/signals.js.map +1 -0
  282. package/dist/esm/config/types.d.ts +7 -4
  283. package/dist/esm/config/types.js +1 -1
  284. package/dist/esm/config/types.js.map +1 -1
  285. package/dist/esm/config/validate.d.ts +1 -0
  286. package/dist/esm/config/validate.js +65 -12
  287. package/dist/esm/config/validate.js.map +1 -1
  288. package/dist/esm/db/open.d.ts +1 -1
  289. package/dist/esm/db/open.js +11 -6
  290. package/dist/esm/db/open.js.map +1 -1
  291. package/dist/esm/db/reconcile.d.ts +1 -0
  292. package/dist/esm/db/reconcile.js +14 -4
  293. package/dist/esm/db/reconcile.js.map +1 -1
  294. package/dist/esm/{sql-functions.js → db/sql-functions.js} +1 -1
  295. package/dist/esm/db/sql-functions.js.map +1 -0
  296. package/dist/esm/embed/cohere.d.ts +2 -0
  297. package/dist/esm/embed/cohere.js +46 -0
  298. package/dist/esm/embed/cohere.js.map +1 -0
  299. package/dist/esm/embed/http.d.ts +2 -0
  300. package/dist/esm/embed/http.js +33 -0
  301. package/dist/esm/embed/http.js.map +1 -0
  302. package/dist/esm/embed/identity.d.ts +13 -0
  303. package/dist/esm/embed/identity.js +92 -0
  304. package/dist/esm/embed/identity.js.map +1 -0
  305. package/dist/esm/embed/langfit.d.ts +6 -0
  306. package/dist/esm/embed/langfit.js +44 -0
  307. package/dist/esm/embed/langfit.js.map +1 -0
  308. package/dist/esm/embed/languages.d.ts +3 -0
  309. package/dist/esm/embed/languages.js +80 -0
  310. package/dist/esm/embed/languages.js.map +1 -0
  311. package/dist/esm/embed/openai.d.ts +2 -0
  312. package/dist/esm/embed/openai.js +49 -0
  313. package/dist/esm/embed/openai.js.map +1 -0
  314. package/dist/esm/embed/query.d.ts +21 -0
  315. package/dist/esm/embed/query.js +181 -0
  316. package/dist/esm/embed/query.js.map +1 -0
  317. package/dist/esm/embed/registry.d.ts +3 -0
  318. package/dist/esm/embed/registry.js +45 -0
  319. package/dist/esm/embed/registry.js.map +1 -0
  320. package/dist/esm/embed/static.d.ts +2 -0
  321. package/dist/esm/embed/static.js +71 -0
  322. package/dist/esm/embed/static.js.map +1 -0
  323. package/dist/esm/embed/store.d.ts +8 -0
  324. package/dist/esm/embed/store.js +123 -0
  325. package/dist/esm/embed/store.js.map +1 -0
  326. package/dist/esm/embed/types.d.ts +8 -0
  327. package/dist/esm/embed/types.js +3 -0
  328. package/dist/esm/embed/types.js.map +1 -0
  329. package/dist/esm/errors.d.ts +1 -1
  330. package/dist/esm/errors.js.map +1 -1
  331. package/dist/esm/features/embed.d.ts +2 -28
  332. package/dist/esm/features/embed.js +33 -377
  333. package/dist/esm/features/embed.js.map +1 -1
  334. package/dist/esm/{fences.js → features/fences.js} +1 -1
  335. package/dist/esm/features/fences.js.map +1 -0
  336. package/dist/esm/features/links.js +1 -1
  337. package/dist/esm/features/links.js.map +1 -1
  338. package/dist/esm/features/rank.js +1 -1
  339. package/dist/esm/features/rank.js.map +1 -1
  340. package/dist/esm/features/sections.js +4 -3
  341. package/dist/esm/features/sections.js.map +1 -1
  342. package/dist/esm/features/tags.js +1 -1
  343. package/dist/esm/features/tags.js.map +1 -1
  344. package/dist/esm/features/types.d.ts +4 -2
  345. package/dist/esm/features/types.js.map +1 -1
  346. package/dist/esm/graph/graph.js.map +1 -0
  347. package/dist/esm/graph/traverse.js.map +1 -0
  348. package/dist/esm/index.d.ts +4 -4
  349. package/dist/esm/index.js +2 -2
  350. package/dist/esm/index.js.map +1 -1
  351. package/dist/esm/output/column-hint.js.map +1 -0
  352. package/dist/esm/{output.d.ts → output/output.d.ts} +2 -2
  353. package/dist/esm/{output.js → output/output.js} +6 -2
  354. package/dist/esm/output/output.js.map +1 -0
  355. package/dist/esm/output/progress.js.map +1 -0
  356. package/dist/esm/{search-error.js → output/search-error.js} +1 -1
  357. package/dist/esm/output/search-error.js.map +1 -0
  358. package/dist/esm/scan/frontmatter.d.ts +13 -0
  359. package/dist/esm/{scan.js → scan/frontmatter.js} +4 -120
  360. package/dist/esm/scan/frontmatter.js.map +1 -0
  361. package/dist/esm/scan/index.d.ts +25 -0
  362. package/dist/esm/scan/index.js +58 -0
  363. package/dist/esm/scan/index.js.map +1 -0
  364. package/dist/esm/scan/list.d.ts +12 -0
  365. package/dist/esm/scan/list.js +58 -0
  366. package/dist/esm/scan/list.js.map +1 -0
  367. package/dist/esm/text/segment.d.ts +3 -0
  368. package/dist/esm/text/segment.js +95 -0
  369. package/dist/esm/text/segment.js.map +1 -0
  370. package/dist/esm/text/strip.d.ts +3 -0
  371. package/dist/esm/text/strip.js +12 -0
  372. package/dist/esm/text/strip.js.map +1 -0
  373. package/package.json +23 -2
  374. package/schema.json +22 -8
  375. package/skills/sense/SKILL.md +21 -5
  376. package/skills/sense-setup/EXAMPLES.md +6 -6
  377. package/skills/sense-setup/SKILL.md +7 -5
  378. package/dist/cjs/column-hint.js.map +0 -1
  379. package/dist/cjs/fences.js.map +0 -1
  380. package/dist/cjs/graph.js.map +0 -1
  381. package/dist/cjs/output.js.map +0 -1
  382. package/dist/cjs/progress.js.map +0 -1
  383. package/dist/cjs/scan.d.cts +0 -35
  384. package/dist/cjs/scan.d.ts +0 -35
  385. package/dist/cjs/scan.js +0 -433
  386. package/dist/cjs/scan.js.map +0 -1
  387. package/dist/cjs/search-error.js.map +0 -1
  388. package/dist/cjs/segment.d.cts +0 -2
  389. package/dist/cjs/segment.d.ts +0 -2
  390. package/dist/cjs/segment.js +0 -98
  391. package/dist/cjs/segment.js.map +0 -1
  392. package/dist/cjs/sql-functions.js.map +0 -1
  393. package/dist/cjs/traverse.js.map +0 -1
  394. package/dist/esm/column-hint.js.map +0 -1
  395. package/dist/esm/fences.js.map +0 -1
  396. package/dist/esm/graph.js.map +0 -1
  397. package/dist/esm/output.js.map +0 -1
  398. package/dist/esm/progress.js.map +0 -1
  399. package/dist/esm/scan.d.ts +0 -35
  400. package/dist/esm/scan.js.map +0 -1
  401. package/dist/esm/search-error.js.map +0 -1
  402. package/dist/esm/segment.d.ts +0 -2
  403. package/dist/esm/segment.js +0 -65
  404. package/dist/esm/segment.js.map +0 -1
  405. package/dist/esm/sql-functions.js.map +0 -1
  406. package/dist/esm/traverse.js.map +0 -1
  407. /package/dist/cjs/{sql-functions.d.cts → db/sql-functions.d.cts} +0 -0
  408. /package/dist/cjs/{sql-functions.d.ts → db/sql-functions.d.ts} +0 -0
  409. /package/dist/cjs/{fences.d.cts → features/fences.d.cts} +0 -0
  410. /package/dist/cjs/{fences.d.ts → features/fences.d.ts} +0 -0
  411. /package/dist/cjs/{graph.d.cts → graph/graph.d.cts} +0 -0
  412. /package/dist/cjs/{graph.d.ts → graph/graph.d.ts} +0 -0
  413. /package/dist/cjs/{graph.js → graph/graph.js} +0 -0
  414. /package/dist/cjs/{traverse.d.cts → graph/traverse.d.cts} +0 -0
  415. /package/dist/cjs/{traverse.d.ts → graph/traverse.d.ts} +0 -0
  416. /package/dist/cjs/{traverse.js → graph/traverse.js} +0 -0
  417. /package/dist/cjs/{column-hint.d.cts → output/column-hint.d.cts} +0 -0
  418. /package/dist/cjs/{column-hint.d.ts → output/column-hint.d.ts} +0 -0
  419. /package/dist/cjs/{column-hint.js → output/column-hint.js} +0 -0
  420. /package/dist/cjs/{progress.d.cts → output/progress.d.cts} +0 -0
  421. /package/dist/cjs/{progress.d.ts → output/progress.d.ts} +0 -0
  422. /package/dist/cjs/{progress.js → output/progress.js} +0 -0
  423. /package/dist/cjs/{search-error.d.cts → output/search-error.d.cts} +0 -0
  424. /package/dist/cjs/{search-error.d.ts → output/search-error.d.ts} +0 -0
  425. /package/dist/esm/{sql-functions.d.ts → db/sql-functions.d.ts} +0 -0
  426. /package/dist/esm/{fences.d.ts → features/fences.d.ts} +0 -0
  427. /package/dist/esm/{graph.d.ts → graph/graph.d.ts} +0 -0
  428. /package/dist/esm/{graph.js → graph/graph.js} +0 -0
  429. /package/dist/esm/{traverse.d.ts → graph/traverse.d.ts} +0 -0
  430. /package/dist/esm/{traverse.js → graph/traverse.js} +0 -0
  431. /package/dist/esm/{column-hint.d.ts → output/column-hint.d.ts} +0 -0
  432. /package/dist/esm/{column-hint.js → output/column-hint.js} +0 -0
  433. /package/dist/esm/{progress.d.ts → output/progress.d.ts} +0 -0
  434. /package/dist/esm/{progress.js → output/progress.js} +0 -0
  435. /package/dist/esm/{search-error.d.ts → output/search-error.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import type { DatabaseSync } from 'node:sqlite';
2
2
  import type { FeatureName, ResolvedConfig, SearchOverrides } from '../config/index.js';
3
- import type { Row } from '../output.js';
3
+ import type { Row } from '../output/output.js';
4
4
  import type { PresetCoverage } from './status.js';
5
5
  export interface TreeMap {
6
6
  docs: {
@@ -1,6 +1,6 @@
1
1
  import type { DatabaseSync } from 'node:sqlite';
2
2
  import type { FeatureName, ResolvedConfig, SearchOverrides } from '../config/index.js';
3
- import type { Row } from '../output.js';
3
+ import type { Row } from '../output/output.js';
4
4
  import type { PresetCoverage } from './status.js';
5
5
  export interface TreeMap {
6
6
  docs: {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/map.ts"],"sourcesContent":["import type { DatabaseSync } from 'node:sqlite';\nimport type { FeatureName, ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { featureEnabled, featureStates } from '../config/index.ts';\nimport type { Row } from '../output.ts';\nimport { INTERNAL_COLUMNS, scopedPaths, setupMapScope } from './scope.ts';\nimport type { PresetCoverage } from './status.ts';\nimport { presetCoverage } from './status.ts';\n\nexport interface TreeMap {\n docs: { count: number; bytes: number };\n fields: Row[]; // top 20 by coverage; fieldsTotal carries the real count\n fieldsTotal: number;\n features: { on: FeatureName[]; off: FeatureName[] };\n presets: PresetCoverage[];\n hubs: Row[];\n recent: Row[];\n recentCaveat: string | null;\n}\n\n// A result row is capped at SQLITE_MAX_COLUMN (2000, default); two aggregate expressions\n// per field keeps a chunk's row safely under that regardless of how many fields the tree has.\nconst MAP_COLUMN_CHUNK = 300;\n\nfunction chunk<T>(items: T[], size: number): T[][] {\n const out: T[][] = [];\n for (let i = 0; i < items.length; i += size) out.push(items.slice(i, i + size));\n return out;\n}\n\n// What is this scope: fixed-size output regardless of tree size. Coverage and features stay\n// global -- they describe the tree, not the current question.\nexport function mapTree(db: DatabaseSync, cfg: ResolvedConfig, overrides: SearchOverrides = {}): TreeMap {\n setupMapScope(db, scopedPaths(db, cfg, overrides));\n const scopeWhere = 'WHERE \"path\" IN (SELECT \"path\" FROM _map_scope)';\n const scopeAnd = 'AND f.\"path\" IN (SELECT \"path\" FROM _map_scope)';\n\n const docs = db.prepare(`SELECT COUNT(*) AS count, COALESCE(SUM(\"_size\"), 0) AS bytes FROM frontmatter ${scopeWhere}`).get() as { count: number; bytes: number };\n\n const columns = (db.prepare('PRAGMA table_info(frontmatter)').all() as Array<{ name: string }>).map((r) => r.name).filter((name) => !INTERNAL_COLUMNS.has(name));\n // Observed types, not declared: SQLite types per value, so a field can be text in most notes\n // and numeric in a few. One aggregate scan per chunk of columns; FILTER matches COUNT's nulls.\n const allFields: Row[] = [];\n for (const group of chunk(columns, MAP_COLUMN_CHUNK)) {\n const exprs = group.map((name, i) => {\n const quoted = `\"${name.split('\"').join('\"\"')}\"`;\n return `COUNT(${quoted}) AS n${i}, GROUP_CONCAT(DISTINCT typeof(${quoted})) FILTER (WHERE ${quoted} IS NOT NULL) AS t${i}`;\n });\n const result = db.prepare(`SELECT ${exprs.join(', ')} FROM frontmatter ${scopeWhere}`).get() as Record<string, number | string | null>;\n group.forEach((name, i) => allFields.push({ field: name, coverage: result[`n${i}`] as number, type: (result[`t${i}`] as string) ?? '' }));\n }\n allFields.sort((a, b) => (b.coverage as number) - (a.coverage as number));\n const fields = allFields.slice(0, 20);\n\n const hubs = featureEnabled(cfg, 'rank') ? (db.prepare(`SELECT f.\"path\" AS path, round(f.\"_rank\" * 100, 2) AS rank, content.title FROM frontmatter f JOIN content ON content.path = f.\"path\" WHERE f.\"_rank\" IS NOT NULL ${scopeAnd} ORDER BY f.\"_rank\" DESC LIMIT 8`).all() as Row[]) : [];\n\n const recent = db.prepare(`SELECT \"path\", datetime(\"_mtime\" / 1000, 'unixepoch') AS modified FROM frontmatter ${scopeWhere} ORDER BY \"_mtime\" DESC LIMIT 5`).all() as Row[];\n\n // A fresh clone/copy stamps files with checkout time, not edit history; second granularity\n // matches the `recent` table above and is coarse enough to catch that without an exact-ms match.\n const topSecond = db.prepare(`SELECT COUNT(*) AS n FROM frontmatter ${scopeWhere} GROUP BY CAST(\"_mtime\" / 1000 AS INTEGER) ORDER BY n DESC LIMIT 1`).get() as { n: number } | undefined;\n const recentCaveat = topSecond && docs.count > 1 && topSecond.n > docs.count / 2 ? `${topSecond.n} of ${docs.count} files share one modified second, so recency likely reflects a checkout or copy, not edit history` : null;\n\n return { docs, fields, fieldsTotal: allFields.length, features: featureStates(cfg), presets: presetCoverage(db, cfg), hubs, recent, recentCaveat };\n}\n"],"names":["mapTree","MAP_COLUMN_CHUNK","chunk","items","size","out","i","length","push","slice","db","cfg","overrides","setupMapScope","scopedPaths","scopeWhere","scopeAnd","docs","prepare","get","columns","all","map","r","name","filter","INTERNAL_COLUMNS","has","allFields","group","exprs","quoted","split","join","result","forEach","field","coverage","type","sort","a","b","fields","hubs","featureEnabled","recent","topSecond","recentCaveat","count","n","fieldsTotal","features","featureStates","presets","presetCoverage"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/map.ts"],"sourcesContent":["import type { DatabaseSync } from 'node:sqlite';\nimport type { FeatureName, ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { featureEnabled, featureStates } from '../config/index.ts';\nimport type { Row } from '../output/output.ts';\nimport { INTERNAL_COLUMNS, scopedPaths, setupMapScope } from './scope.ts';\nimport type { PresetCoverage } from './status.ts';\nimport { presetCoverage } from './status.ts';\n\nexport interface TreeMap {\n docs: { count: number; bytes: number };\n fields: Row[]; // top 20 by coverage; fieldsTotal carries the real count\n fieldsTotal: number;\n features: { on: FeatureName[]; off: FeatureName[] };\n presets: PresetCoverage[];\n hubs: Row[];\n recent: Row[];\n recentCaveat: string | null;\n}\n\n// A result row is capped at SQLITE_MAX_COLUMN (2000, default); two aggregate expressions\n// per field keeps a chunk's row safely under that regardless of how many fields the tree has.\nconst MAP_COLUMN_CHUNK = 300;\n\nfunction chunk<T>(items: T[], size: number): T[][] {\n const out: T[][] = [];\n for (let i = 0; i < items.length; i += size) out.push(items.slice(i, i + size));\n return out;\n}\n\n// What is this scope: fixed-size output regardless of tree size. Coverage and features stay\n// global -- they describe the tree, not the current question.\nexport function mapTree(db: DatabaseSync, cfg: ResolvedConfig, overrides: SearchOverrides = {}): TreeMap {\n setupMapScope(db, scopedPaths(db, cfg, overrides));\n const scopeWhere = 'WHERE \"path\" IN (SELECT \"path\" FROM _map_scope)';\n const scopeAnd = 'AND f.\"path\" IN (SELECT \"path\" FROM _map_scope)';\n\n const docs = db.prepare(`SELECT COUNT(*) AS count, COALESCE(SUM(\"_size\"), 0) AS bytes FROM frontmatter ${scopeWhere}`).get() as { count: number; bytes: number };\n\n const columns = (db.prepare('PRAGMA table_info(frontmatter)').all() as Array<{ name: string }>).map((r) => r.name).filter((name) => !INTERNAL_COLUMNS.has(name));\n // Observed types, not declared: SQLite types per value, so a field can be text in most notes\n // and numeric in a few. One aggregate scan per chunk of columns; FILTER matches COUNT's nulls.\n const allFields: Row[] = [];\n for (const group of chunk(columns, MAP_COLUMN_CHUNK)) {\n const exprs = group.map((name, i) => {\n const quoted = `\"${name.split('\"').join('\"\"')}\"`;\n return `COUNT(${quoted}) AS n${i}, GROUP_CONCAT(DISTINCT typeof(${quoted})) FILTER (WHERE ${quoted} IS NOT NULL) AS t${i}`;\n });\n const result = db.prepare(`SELECT ${exprs.join(', ')} FROM frontmatter ${scopeWhere}`).get() as Record<string, number | string | null>;\n group.forEach((name, i) => allFields.push({ field: name, coverage: result[`n${i}`] as number, type: (result[`t${i}`] as string) ?? '' }));\n }\n allFields.sort((a, b) => (b.coverage as number) - (a.coverage as number));\n const fields = allFields.slice(0, 20);\n\n const hubs = featureEnabled(cfg, 'rank') ? (db.prepare(`SELECT f.\"path\" AS path, round(f.\"_rank\" * 100, 2) AS rank, content.title FROM frontmatter f JOIN content ON content.path = f.\"path\" WHERE f.\"_rank\" IS NOT NULL ${scopeAnd} ORDER BY f.\"_rank\" DESC LIMIT 8`).all() as Row[]) : [];\n\n const recent = db.prepare(`SELECT \"path\", datetime(\"_mtime\" / 1000, 'unixepoch') AS modified FROM frontmatter ${scopeWhere} ORDER BY \"_mtime\" DESC LIMIT 5`).all() as Row[];\n\n // A fresh clone/copy stamps files with checkout time, not edit history; second granularity\n // matches the `recent` table above and is coarse enough to catch that without an exact-ms match.\n const topSecond = db.prepare(`SELECT COUNT(*) AS n FROM frontmatter ${scopeWhere} GROUP BY CAST(\"_mtime\" / 1000 AS INTEGER) ORDER BY n DESC LIMIT 1`).get() as { n: number } | undefined;\n const recentCaveat = topSecond && docs.count > 1 && topSecond.n > docs.count / 2 ? `${topSecond.n} of ${docs.count} files share one modified second, so recency likely reflects a checkout or copy, not edit history` : null;\n\n return { docs, fields, fieldsTotal: allFields.length, features: featureStates(cfg), presets: presetCoverage(db, cfg), hubs, recent, recentCaveat };\n}\n"],"names":["mapTree","MAP_COLUMN_CHUNK","chunk","items","size","out","i","length","push","slice","db","cfg","overrides","setupMapScope","scopedPaths","scopeWhere","scopeAnd","docs","prepare","get","columns","all","map","r","name","filter","INTERNAL_COLUMNS","has","allFields","group","exprs","quoted","split","join","result","forEach","field","coverage","type","sort","a","b","fields","hubs","featureEnabled","recent","topSecond","recentCaveat","count","n","fieldsTotal","features","featureStates","presets","presetCoverage"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import type { DatabaseSync } from 'node:sqlite';
2
2
  import type { FeatureName, ResolvedConfig, SearchOverrides } from '../config/index.js';
3
- import type { Row } from '../output.js';
3
+ import type { Row } from '../output/output.js';
4
4
  export declare function resolveNote(paths: string[], arg: string): string;
5
5
  export interface Peek {
6
6
  path: string;
@@ -1,6 +1,6 @@
1
1
  import type { DatabaseSync } from 'node:sqlite';
2
2
  import type { FeatureName, ResolvedConfig, SearchOverrides } from '../config/index.js';
3
- import type { Row } from '../output.js';
3
+ import type { Row } from '../output/output.js';
4
4
  export declare function resolveNote(paths: string[], arg: string): string;
5
5
  export interface Peek {
6
6
  path: string;
@@ -17,7 +17,8 @@ _export(exports, {
17
17
  }
18
18
  });
19
19
  var _posix = /*#__PURE__*/ _interop_require_default(require("node:path/posix"));
20
- var _indexts = require("../config/index.js");
20
+ var _indexts = require("../chunk/index.js");
21
+ var _indexts1 = require("../config/index.js");
21
22
  var _errorsts = require("../errors.js");
22
23
  var _scopets = require("./scope.js");
23
24
  function _array_like_to_array(arr, len) {
@@ -102,6 +103,7 @@ var PEEK_LIST_LIMIT = 20;
102
103
  function peek(db, cfg, pathArg) {
103
104
  var overrides = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : {};
104
105
  var _row__parse_error, _row__size;
106
+ var _db_prepare_get;
105
107
  var paths = db.prepare('SELECT "path" FROM frontmatter').all().map(function(r) {
106
108
  return r.path;
107
109
  });
@@ -129,14 +131,14 @@ function peek(db, cfg, pathArg) {
129
131
  }
130
132
  }
131
133
  }
132
- var sectionsTotal = (0, _indexts.featureEnabled)(cfg, 'sections') ? db.prepare('SELECT COUNT(*) AS n FROM sections WHERE "path" = ?').get(path).n : 0;
133
- var sections = (0, _indexts.featureEnabled)(cfg, 'sections') ? db.prepare('SELECT level, heading, start_line, end_line, tokens FROM sections WHERE "path" = ? ORDER BY idx LIMIT ?').all(path, PEEK_LIST_LIMIT) : [];
134
+ var sectionsTotal = (0, _indexts1.featureEnabled)(cfg, 'sections') ? db.prepare('SELECT COUNT(*) AS n FROM sections WHERE "path" = ?').get(path).n : 0;
135
+ var sections = (0, _indexts1.featureEnabled)(cfg, 'sections') ? db.prepare('SELECT level, heading, start_line, end_line, tokens FROM sections WHERE "path" = ? ORDER BY idx LIMIT ?').all(path, PEEK_LIST_LIMIT) : [];
134
136
  var outbound = [];
135
137
  var backlinks = [];
136
138
  var unresolved = [];
137
139
  var backlinksTotal = 0;
138
140
  var _allowed = (0, _scopets.scopedPaths)(db, cfg, overrides);
139
- if ((0, _indexts.featureEnabled)(cfg, 'links')) {
141
+ if ((0, _indexts1.featureEnabled)(cfg, 'links')) {
140
142
  var out = db.prepare('SELECT target, dst FROM links WHERE src = ? AND (dst IS NULL OR dst != src) ORDER BY target').all(path);
141
143
  outbound = _to_consumable_array(new Set(out.filter(function(l) {
142
144
  return l.dst !== null;
@@ -153,9 +155,14 @@ function peek(db, cfg, pathArg) {
153
155
  return r.src;
154
156
  });
155
157
  }
158
+ // content.text is the stripped body already computed at reconcile time (no extra file read),
159
+ // floored by the byte/4 estimate so stripped-away syntax and frontmatter can't vanish from the price.
160
+ var body = (_db_prepare_get = db.prepare('SELECT text FROM content WHERE "path" = ?').get(path)) === null || _db_prepare_get === void 0 ? void 0 : _db_prepare_get.text;
161
+ var byteTokens = Math.ceil(((_row__size = row._size) !== null && _row__size !== void 0 ? _row__size : 0) / 4);
162
+ var tokens = body !== undefined ? Math.max(Math.ceil((0, _indexts.estimateTokens)(body)), byteTokens) : byteTokens;
156
163
  return {
157
164
  path: path,
158
- tokens: Math.ceil(((_row__size = row._size) !== null && _row__size !== void 0 ? _row__size : 0) / 4),
165
+ tokens: tokens,
159
166
  frontmatter: frontmatter,
160
167
  parseError: parseError,
161
168
  sections: sections,
@@ -170,7 +177,7 @@ function peek(db, cfg, pathArg) {
170
177
  'sections',
171
178
  'links'
172
179
  ].filter(function(name) {
173
- return !(0, _indexts.featureEnabled)(cfg, name);
180
+ return !(0, _indexts1.featureEnabled)(cfg, name);
174
181
  })
175
182
  };
176
183
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/peek.ts"],"sourcesContent":["import posix from 'node:path/posix';\nimport type { DatabaseSync } from 'node:sqlite';\nimport type { FeatureName, ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { featureEnabled } from '../config/index.ts';\nimport { SenseError } from '../errors.ts';\nimport type { Row } from '../output.ts';\nimport { INTERNAL_COLUMNS, scopedPaths } from './scope.ts';\n\n// Note resolution shared by peek and path: an exact path, or a unique basename (case\n// insensitive, .md stripped).\nexport function resolveNote(paths: string[], arg: string): string {\n const exact = paths.find((p) => p === arg);\n if (exact) return exact;\n const base = posix.basename(arg).replace(/\\.md$/i, '').toLowerCase();\n const matches = paths.filter((p) => posix.basename(p).replace(/\\.md$/i, '').toLowerCase() === base);\n if (matches.length === 1) return matches[0];\n if (matches.length > 1) throw new SenseError('NOTE_AMBIGUOUS', `\"${arg}\" is ambiguous: ${matches.join(', ')}`);\n throw new SenseError('NOTE_NOT_FOUND', `no note matches \"${arg}\"`);\n}\n\nexport interface Peek {\n path: string;\n tokens: number;\n frontmatter: Row;\n // Set when the note's frontmatter was refused, so an empty frontmatter block reads as \"did\n // not parse\" rather than \"has none\". Same reason `_parse_error` sits in the row.\n parseError: string | null;\n sections: Row[];\n outbound: string[];\n backlinks: string[];\n unresolved: string[];\n // Totals before truncation: a hub can have thousands of backlinks (or a note thousands of\n // headings), and peek's whole point is bounded output. Query the sections/links tables\n // directly for the full list.\n sectionsTotal: number;\n outboundTotal: number;\n backlinksTotal: number;\n unresolvedTotal: number;\n // Bounded k-hop expansion beyond the immediate ring already shown by outbound/backlinks\n // (depth starts at 2).\n off: FeatureName[]; // disabled features whose blocks are omitted (not empty)\n}\n\nconst PEEK_LIST_LIMIT = 20;\n\n// peek: everything about one note except its prose -- frontmatter, outline with line\n// ranges + token estimates (so the follow-up Read is a range, not the file), links both ways.\nexport function peek(db: DatabaseSync, cfg: ResolvedConfig, pathArg: string, overrides: SearchOverrides = {}): Peek {\n const paths = (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n const path = resolveNote(paths, pathArg);\n\n const row = db.prepare('SELECT * FROM frontmatter WHERE \"path\" = ?').get(path) as Row;\n const parseError = (row._parse_error as string | null) ?? null;\n const frontmatter: Row = {};\n for (const [key, value] of Object.entries(row)) {\n if (!INTERNAL_COLUMNS.has(key) && value !== null) frontmatter[key] = value;\n }\n\n const sectionsTotal = featureEnabled(cfg, 'sections') ? (db.prepare('SELECT COUNT(*) AS n FROM sections WHERE \"path\" = ?').get(path) as { n: number }).n : 0;\n const sections = featureEnabled(cfg, 'sections') ? (db.prepare('SELECT level, heading, start_line, end_line, tokens FROM sections WHERE \"path\" = ? ORDER BY idx LIMIT ?').all(path, PEEK_LIST_LIMIT) as Row[]) : [];\n\n let outbound: string[] = [];\n let backlinks: string[] = [];\n let unresolved: string[] = [];\n let backlinksTotal = 0;\n const _allowed = scopedPaths(db, cfg, overrides);\n if (featureEnabled(cfg, 'links')) {\n const out = db.prepare('SELECT target, dst FROM links WHERE src = ? AND (dst IS NULL OR dst != src) ORDER BY target').all(path) as Array<{ target: string; dst: string | null }>;\n outbound = [...new Set(out.filter((l) => l.dst !== null).map((l) => l.dst as string))];\n unresolved = out.filter((l) => l.dst === null).map((l) => l.target);\n backlinksTotal = (db.prepare('SELECT COUNT(DISTINCT src) AS n FROM links WHERE dst = ? AND src != dst').get(path) as { n: number }).n;\n backlinks = (db.prepare('SELECT DISTINCT src FROM links WHERE dst = ? AND src != dst ORDER BY src LIMIT ?').all(path, PEEK_LIST_LIMIT) as Array<{ src: string }>).map((r) => r.src);\n }\n\n return {\n path,\n tokens: Math.ceil(((row._size as number) ?? 0) / 4),\n frontmatter,\n parseError,\n sections,\n outbound: outbound.slice(0, PEEK_LIST_LIMIT),\n backlinks,\n unresolved: unresolved.slice(0, PEEK_LIST_LIMIT),\n sectionsTotal,\n outboundTotal: outbound.length,\n backlinksTotal,\n unresolvedTotal: unresolved.length,\n off: (['sections', 'links'] as FeatureName[]).filter((name) => !featureEnabled(cfg, name)),\n };\n}\n"],"names":["peek","resolveNote","paths","arg","exact","find","p","base","posix","basename","replace","toLowerCase","matches","filter","length","SenseError","join","PEEK_LIST_LIMIT","db","cfg","pathArg","overrides","row","prepare","all","map","r","path","get","parseError","_parse_error","frontmatter","Object","entries","key","value","INTERNAL_COLUMNS","has","sectionsTotal","featureEnabled","n","sections","outbound","backlinks","unresolved","backlinksTotal","_allowed","scopedPaths","out","Set","l","dst","target","src","tokens","Math","ceil","_size","slice","outboundTotal","unresolvedTotal","off","name"],"mappings":";;;;;;;;;;;QA+CgBA;eAAAA;;QArCAC;eAAAA;;;4DAVE;uBAGa;wBACJ;uBAEmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIvC,SAASA,YAAYC,KAAe,EAAEC,GAAW;IACtD,IAAMC,QAAQF,MAAMG,IAAI,CAAC,SAACC;eAAMA,MAAMH;;IACtC,IAAIC,OAAO,OAAOA;IAClB,IAAMG,OAAOC,cAAK,CAACC,QAAQ,CAACN,KAAKO,OAAO,CAAC,UAAU,IAAIC,WAAW;IAClE,IAAMC,UAAUV,MAAMW,MAAM,CAAC,SAACP;eAAME,cAAK,CAACC,QAAQ,CAACH,GAAGI,OAAO,CAAC,UAAU,IAAIC,WAAW,OAAOJ;;IAC9F,IAAIK,QAAQE,MAAM,KAAK,GAAG,OAAOF,OAAO,CAAC,EAAE;IAC3C,IAAIA,QAAQE,MAAM,GAAG,GAAG,MAAM,IAAIC,oBAAU,CAAC,kBAAkB,AAAC,IAAyBH,OAAtBT,KAAI,oBAAqC,OAAnBS,QAAQI,IAAI,CAAC;IACtG,MAAM,IAAID,oBAAU,CAAC,kBAAkB,AAAC,oBAAuB,OAAJZ,KAAI;AACjE;AAyBA,IAAMc,kBAAkB;AAIjB,SAASjB,KAAKkB,EAAgB,EAAEC,GAAmB,EAAEC,OAAe;QAAEC,YAAAA,iEAA6B,CAAC;QAKrFC,mBAwBEA;IA5BtB,IAAMpB,QAAQ,AAACgB,GAAGK,OAAO,CAAC,kCAAkCC,GAAG,GAA+BC,GAAG,CAAC,SAACC;eAAMA,EAAEC,IAAI;;IAC/G,IAAMA,OAAO1B,YAAYC,OAAOkB;IAEhC,IAAME,MAAMJ,GAAGK,OAAO,CAAC,8CAA8CK,GAAG,CAACD;IACzE,IAAME,cAAcP,oBAAAA,IAAIQ,YAAY,cAAhBR,+BAAAA,oBAAsC;IAC1D,IAAMS,cAAmB,CAAC;QACrB,kCAAA,2BAAA;;QAAL,QAAK,YAAsBC,OAAOC,OAAO,CAACX,yBAArC,SAAA,6BAAA,QAAA,yBAAA,iCAA2C;YAA3C,mCAAA,iBAAOY,sBAAKC;YACf,IAAI,CAACC,yBAAgB,CAACC,GAAG,CAACH,QAAQC,UAAU,MAAMJ,WAAW,CAACG,IAAI,GAAGC;QACvE;;QAFK;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAIL,IAAMG,gBAAgBC,IAAAA,uBAAc,EAACpB,KAAK,cAAc,AAACD,GAAGK,OAAO,CAAC,uDAAuDK,GAAG,CAACD,MAAwBa,CAAC,GAAG;IAC3J,IAAMC,WAAWF,IAAAA,uBAAc,EAACpB,KAAK,cAAeD,GAAGK,OAAO,CAAC,2GAA2GC,GAAG,CAACG,MAAMV,mBAA6B,EAAE;IAEnN,IAAIyB,WAAqB,EAAE;IAC3B,IAAIC,YAAsB,EAAE;IAC5B,IAAIC,aAAuB,EAAE;IAC7B,IAAIC,iBAAiB;IACrB,IAAMC,WAAWC,IAAAA,oBAAW,EAAC7B,IAAIC,KAAKE;IACtC,IAAIkB,IAAAA,uBAAc,EAACpB,KAAK,UAAU;QAChC,IAAM6B,MAAM9B,GAAGK,OAAO,CAAC,+FAA+FC,GAAG,CAACG;QAC1He,WAAY,qBAAG,IAAIO,IAAID,IAAInC,MAAM,CAAC,SAACqC;mBAAMA,EAAEC,GAAG,KAAK;WAAM1B,GAAG,CAAC,SAACyB;mBAAMA,EAAEC,GAAG;;QACzEP,aAAaI,IAAInC,MAAM,CAAC,SAACqC;mBAAMA,EAAEC,GAAG,KAAK;WAAM1B,GAAG,CAAC,SAACyB;mBAAMA,EAAEE,MAAM;;QAClEP,iBAAiB,AAAC3B,GAAGK,OAAO,CAAC,2EAA2EK,GAAG,CAACD,MAAwBa,CAAC;QACrIG,YAAY,AAACzB,GAAGK,OAAO,CAAC,oFAAoFC,GAAG,CAACG,MAAMV,iBAA4CQ,GAAG,CAAC,SAACC;mBAAMA,EAAE2B,GAAG;;IACpL;IAEA,OAAO;QACL1B,MAAAA;QACA2B,QAAQC,KAAKC,IAAI,CAAC,EAAElC,aAAAA,IAAImC,KAAK,cAATnC,wBAAAA,aAAwB,KAAK;QACjDS,aAAAA;QACAF,YAAAA;QACAY,UAAAA;QACAC,UAAUA,SAASgB,KAAK,CAAC,GAAGzC;QAC5B0B,WAAAA;QACAC,YAAYA,WAAWc,KAAK,CAAC,GAAGzC;QAChCqB,eAAAA;QACAqB,eAAejB,SAAS5B,MAAM;QAC9B+B,gBAAAA;QACAe,iBAAiBhB,WAAW9B,MAAM;QAClC+C,KAAK,AAAC;YAAC;YAAY;SAAQ,CAAmBhD,MAAM,CAAC,SAACiD;mBAAS,CAACvB,IAAAA,uBAAc,EAACpB,KAAK2C;;IACtF;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/peek.ts"],"sourcesContent":["import posix from 'node:path/posix';\nimport type { DatabaseSync } from 'node:sqlite';\nimport { estimateTokens } from '../chunk/index.ts';\nimport type { FeatureName, ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { featureEnabled } from '../config/index.ts';\nimport { SenseError } from '../errors.ts';\nimport type { Row } from '../output/output.ts';\nimport { INTERNAL_COLUMNS, scopedPaths } from './scope.ts';\n\n// Note resolution shared by peek and path: an exact path, or a unique basename (case\n// insensitive, .md stripped).\nexport function resolveNote(paths: string[], arg: string): string {\n const exact = paths.find((p) => p === arg);\n if (exact) return exact;\n const base = posix.basename(arg).replace(/\\.md$/i, '').toLowerCase();\n const matches = paths.filter((p) => posix.basename(p).replace(/\\.md$/i, '').toLowerCase() === base);\n if (matches.length === 1) return matches[0];\n if (matches.length > 1) throw new SenseError('NOTE_AMBIGUOUS', `\"${arg}\" is ambiguous: ${matches.join(', ')}`);\n throw new SenseError('NOTE_NOT_FOUND', `no note matches \"${arg}\"`);\n}\n\nexport interface Peek {\n path: string;\n tokens: number;\n frontmatter: Row;\n // Set when the note's frontmatter was refused, so an empty frontmatter block reads as \"did\n // not parse\" rather than \"has none\". Same reason `_parse_error` sits in the row.\n parseError: string | null;\n sections: Row[];\n outbound: string[];\n backlinks: string[];\n unresolved: string[];\n // Totals before truncation: a hub can have thousands of backlinks (or a note thousands of\n // headings), and peek's whole point is bounded output. Query the sections/links tables\n // directly for the full list.\n sectionsTotal: number;\n outboundTotal: number;\n backlinksTotal: number;\n unresolvedTotal: number;\n // Bounded k-hop expansion beyond the immediate ring already shown by outbound/backlinks\n // (depth starts at 2).\n off: FeatureName[]; // disabled features whose blocks are omitted (not empty)\n}\n\nconst PEEK_LIST_LIMIT = 20;\n\n// peek: everything about one note except its prose -- frontmatter, outline with line\n// ranges + token estimates (so the follow-up Read is a range, not the file), links both ways.\nexport function peek(db: DatabaseSync, cfg: ResolvedConfig, pathArg: string, overrides: SearchOverrides = {}): Peek {\n const paths = (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n const path = resolveNote(paths, pathArg);\n\n const row = db.prepare('SELECT * FROM frontmatter WHERE \"path\" = ?').get(path) as Row;\n const parseError = (row._parse_error as string | null) ?? null;\n const frontmatter: Row = {};\n for (const [key, value] of Object.entries(row)) {\n if (!INTERNAL_COLUMNS.has(key) && value !== null) frontmatter[key] = value;\n }\n\n const sectionsTotal = featureEnabled(cfg, 'sections') ? (db.prepare('SELECT COUNT(*) AS n FROM sections WHERE \"path\" = ?').get(path) as { n: number }).n : 0;\n const sections = featureEnabled(cfg, 'sections') ? (db.prepare('SELECT level, heading, start_line, end_line, tokens FROM sections WHERE \"path\" = ? ORDER BY idx LIMIT ?').all(path, PEEK_LIST_LIMIT) as Row[]) : [];\n\n let outbound: string[] = [];\n let backlinks: string[] = [];\n let unresolved: string[] = [];\n let backlinksTotal = 0;\n const _allowed = scopedPaths(db, cfg, overrides);\n if (featureEnabled(cfg, 'links')) {\n const out = db.prepare('SELECT target, dst FROM links WHERE src = ? AND (dst IS NULL OR dst != src) ORDER BY target').all(path) as Array<{ target: string; dst: string | null }>;\n outbound = [...new Set(out.filter((l) => l.dst !== null).map((l) => l.dst as string))];\n unresolved = out.filter((l) => l.dst === null).map((l) => l.target);\n backlinksTotal = (db.prepare('SELECT COUNT(DISTINCT src) AS n FROM links WHERE dst = ? AND src != dst').get(path) as { n: number }).n;\n backlinks = (db.prepare('SELECT DISTINCT src FROM links WHERE dst = ? AND src != dst ORDER BY src LIMIT ?').all(path, PEEK_LIST_LIMIT) as Array<{ src: string }>).map((r) => r.src);\n }\n\n // content.text is the stripped body already computed at reconcile time (no extra file read),\n // floored by the byte/4 estimate so stripped-away syntax and frontmatter can't vanish from the price.\n const body = (db.prepare('SELECT text FROM content WHERE \"path\" = ?').get(path) as { text: string } | undefined)?.text;\n const byteTokens = Math.ceil(((row._size as number) ?? 0) / 4);\n const tokens = body !== undefined ? Math.max(Math.ceil(estimateTokens(body)), byteTokens) : byteTokens;\n\n return {\n path,\n tokens,\n frontmatter,\n parseError,\n sections,\n outbound: outbound.slice(0, PEEK_LIST_LIMIT),\n backlinks,\n unresolved: unresolved.slice(0, PEEK_LIST_LIMIT),\n sectionsTotal,\n outboundTotal: outbound.length,\n backlinksTotal,\n unresolvedTotal: unresolved.length,\n off: (['sections', 'links'] as FeatureName[]).filter((name) => !featureEnabled(cfg, name)),\n };\n}\n"],"names":["peek","resolveNote","paths","arg","exact","find","p","base","posix","basename","replace","toLowerCase","matches","filter","length","SenseError","join","PEEK_LIST_LIMIT","db","cfg","pathArg","overrides","row","prepare","all","map","r","path","get","parseError","_parse_error","frontmatter","Object","entries","key","value","INTERNAL_COLUMNS","has","sectionsTotal","featureEnabled","n","sections","outbound","backlinks","unresolved","backlinksTotal","_allowed","scopedPaths","out","Set","l","dst","target","src","body","text","byteTokens","Math","ceil","_size","tokens","undefined","max","estimateTokens","slice","outboundTotal","unresolvedTotal","off","name"],"mappings":"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"}
@@ -9,8 +9,9 @@ Object.defineProperty(exports, "relatedNotes", {
9
9
  }
10
10
  });
11
11
  var _indexts = require("../config/index.js");
12
+ var _queryts = require("../embed/query.js");
13
+ var _storets = require("../embed/store.js");
12
14
  var _errorsts = require("../errors.js");
13
- var _embedts = require("../features/embed.js");
14
15
  var _peekts = require("./peek.js");
15
16
  var _scopets = require("./scope.js");
16
17
  function _array_like_to_array(arr, len) {
@@ -167,7 +168,7 @@ function _unsupported_iterable_to_array(o, minLen) {
167
168
  }
168
169
  function relatedNotes(db, cfg, pathArg, overrides, k) {
169
170
  return _async_to_generator(function() {
170
- var paths, path, outbound, backlinks, exclude, effective, allowed;
171
+ var paths, path, outbound, backlinks, exclude, effective, e, allowed;
171
172
  return _ts_generator(this, function(_state) {
172
173
  switch(_state.label){
173
174
  case 0:
@@ -189,27 +190,30 @@ function relatedNotes(db, cfg, pathArg, overrides, k) {
189
190
  // note does not already link to, which is a real answer.
190
191
  effective = (0, _indexts.resolveSearch)(cfg, overrides);
191
192
  if (!(0, _indexts.embedEnabled)(cfg)) {
192
- throw new _errorsts.SenseError('EMBED_DISABLED', 'related ranks notes by meaning, and this tree has no embedding model; add an "embed" block naming one to sense.config.json, then run `sense download` (search works without it, on words and links)');
193
+ throw new _errorsts.SenseError('EMBED_DISABLED', 'related ranks notes by meaning, and this tree has no embedding model; add an "embed" block naming one to sense.config.json (a Hugging Face id fetches automatically at first use; `sense download` prefetches it) -- search works without it, on words and links');
193
194
  }
194
- // search gates on the same flag (see wantsVectors above); reading it here too keeps
195
- // `semantic: false` meaning one thing. Without this, an overlapping semantic-on preset's
196
- // vectors would answer for a scope that declined them.
197
- if (!effective.semantic) {
198
- throw new _errorsts.SenseError('PRESET_NOT_SEMANTIC', 'preset "'.concat(effective.presetName, '" sets "semantic": false, so this scope has no vectors and related has no other signal; search it instead (words and links), or set semantic back on for that preset'));
195
+ // search gates on the same signal (see wantsVectors above); reading it here too keeps a
196
+ // preset's declared signals meaning one thing. Without this, an overlapping vectors-on
197
+ // preset's vectors would answer for a scope that declined them.
198
+ if (effective.signals.vectors === undefined) {
199
+ throw new _errorsts.SenseError('PRESET_NOT_SEMANTIC', 'preset "'.concat(effective.presetName, '" has no "vectors" signal, so this scope has no vectors and related has no other signal; search it instead (words and links), or add "vectors" to that preset\'s signals'));
199
200
  }
200
- if (!(0, _embedts.modelPresent)(cfg)) {
201
- throw new _errorsts.SenseError('EMBED_MODEL_MISSING', 'related ranks notes by meaning, so it needs the embedding model, which is not downloaded; run `sense download` (search still works without it, on words and links)');
201
+ // A downloadable HF id proceeds -- embedPending's getProvider call fetches it lazily on
202
+ // consent. Only a local path with missing files can never fetch itself.
203
+ e = (0, _indexts.embedConfig)(cfg); // embedEnabled(cfg) above guarantees this is set
204
+ if ((0, _storets.localModelMissing)(e)) {
205
+ throw new _errorsts.SenseError('EMBED_MODEL_MISSING', 'related ranks notes by meaning, so it needs the embedding model, but the local model path "'.concat(e.model, '" is missing ').concat(_storets.MODEL_FILENAMES, "; point embed.model at a directory containing them (search still works without it, on words and links)"));
202
206
  }
203
207
  allowed = (0, _scopets.scopedPaths)(db, cfg, overrides);
204
208
  // Top up pending rows before the seed check, or a fresh index reports every note as
205
209
  // having no indexed text until some search has run.
206
210
  return [
207
211
  4,
208
- (0, _embedts.embedPending)(db, cfg, cfg.baseDir)
212
+ (0, _queryts.embedPending)(db, cfg, cfg.baseDir)
209
213
  ];
210
214
  case 1:
211
215
  _state.sent();
212
- if (!(0, _embedts.hasEmbedding)(db, path)) {
216
+ if (!(0, _queryts.hasEmbedding)(db, path)) {
213
217
  throw new _errorsts.SenseError('NOTE_NOT_EMBEDDED', "".concat(path, " has no indexed text to compare -- a note that is frontmatter only, or empty, has nothing to rank by meaning"));
214
218
  }
215
219
  if (!(0, _scopets.scopeHasEmbeddings)(db, cfg, allowed)) return [
@@ -218,7 +222,7 @@ function relatedNotes(db, cfg, pathArg, overrides, k) {
218
222
  ];
219
223
  return [
220
224
  2,
221
- (0, _embedts.similarNotes)(db, cfg, path, {
225
+ (0, _queryts.similarNotes)(db, cfg, path, {
222
226
  exclude: exclude,
223
227
  allowed: allowed,
224
228
  k: k
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/related.ts"],"sourcesContent":["import type { DatabaseSync } from 'node:sqlite';\nimport type { ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { embedEnabled, resolveSearch } from '../config/index.ts';\nimport { SenseError } from '../errors.ts';\nimport { embedPending, hasEmbedding, modelPresent, similarNotes } from '../features/embed.ts';\nimport { resolveNote } from './peek.ts';\nimport { scopedPaths, scopeHasEmbeddings } from './scope.ts';\n\n// Notes most similar by cosine, excluding self and everything already linked either way.\n// Its own command, not a peek section: a full embeddings scan is ~480ms at 26k notes.\nexport async function relatedNotes(db: DatabaseSync, cfg: ResolvedConfig, pathArg: string, overrides: SearchOverrides, k: number): Promise<Array<{ path: string; similarity: number }>> {\n const paths = (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n const path = resolveNote(paths, pathArg);\n\n const outbound = (db.prepare('SELECT DISTINCT dst FROM links WHERE src = ? AND dst IS NOT NULL AND dst != src').all(path) as Array<{ dst: string }>).map((r) => r.dst);\n const backlinks = (db.prepare('SELECT DISTINCT src FROM links WHERE dst = ? AND src != dst').all(path) as Array<{ src: string }>).map((r) => r.src);\n const exclude = new Set([path, ...outbound, ...backlinks]);\n\n // Vectors are the only signal `related` has, so every way of not having them is an error\n // naming the cause. An empty table then means one thing: nothing near in meaning that this\n // note does not already link to, which is a real answer.\n const effective = resolveSearch(cfg, overrides);\n if (!embedEnabled(cfg)) {\n throw new SenseError('EMBED_DISABLED', 'related ranks notes by meaning, and this tree has no embedding model; add an \"embed\" block naming one to sense.config.json, then run `sense download` (search works without it, on words and links)');\n }\n // search gates on the same flag (see wantsVectors above); reading it here too keeps\n // `semantic: false` meaning one thing. Without this, an overlapping semantic-on preset's\n // vectors would answer for a scope that declined them.\n if (!effective.semantic) {\n throw new SenseError('PRESET_NOT_SEMANTIC', `preset \"${effective.presetName}\" sets \"semantic\": false, so this scope has no vectors and related has no other signal; search it instead (words and links), or set semantic back on for that preset`);\n }\n if (!modelPresent(cfg)) {\n throw new SenseError('EMBED_MODEL_MISSING', 'related ranks notes by meaning, so it needs the embedding model, which is not downloaded; run `sense download` (search still works without it, on words and links)');\n }\n const allowed = scopedPaths(db, cfg, overrides);\n // Top up pending rows before the seed check, or a fresh index reports every note as\n // having no indexed text until some search has run.\n await embedPending(db, cfg, cfg.baseDir);\n if (!hasEmbedding(db, path)) {\n throw new SenseError('NOTE_NOT_EMBEDDED', `${path} has no indexed text to compare -- a note that is frontmatter only, or empty, has nothing to rank by meaning`);\n }\n if (!scopeHasEmbeddings(db, cfg, allowed)) return [];\n return similarNotes(db, cfg, path, { exclude, allowed, k });\n}\n"],"names":["relatedNotes","db","cfg","pathArg","overrides","k","paths","path","outbound","backlinks","exclude","effective","allowed","prepare","all","map","r","resolveNote","dst","src","Set","resolveSearch","embedEnabled","SenseError","semantic","presetName","modelPresent","scopedPaths","embedPending","baseDir","hasEmbedding","scopeHasEmbeddings","similarNotes"],"mappings":";;;;+BAUsBA;;;eAAAA;;;uBARsB;wBACjB;uBAC4C;sBAC3C;uBACoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIzC,SAAeA,aAAaC,EAAgB,EAAEC,GAAmB,EAAEC,OAAe,EAAEC,SAA0B,EAAEC,CAAS;;YACxHC,OACAC,MAEAC,UACAC,WACAC,SAKAC,WAaAC;;;;oBAvBAN,QAAQ,AAACL,GAAGY,OAAO,CAAC,kCAAkCC,GAAG,GAA+BC,GAAG,CAAC,SAACC;+BAAMA,EAAET,IAAI;;oBACzGA,OAAOU,IAAAA,mBAAW,EAACX,OAAOH;oBAE1BK,WAAW,AAACP,GAAGY,OAAO,CAAC,mFAAmFC,GAAG,CAACP,MAAiCQ,GAAG,CAAC,SAACC;+BAAMA,EAAEE,GAAG;;oBAC/JT,YAAY,AAACR,GAAGY,OAAO,CAAC,+DAA+DC,GAAG,CAACP,MAAiCQ,GAAG,CAAC,SAACC;+BAAMA,EAAEG,GAAG;;oBAC5IT,UAAU,IAAIU,IAAI;wBAACb;sBAAD,OAAO,qBAAGC,WAAU,qBAAGC;oBAE/C,yFAAyF;oBACzF,2FAA2F;oBAC3F,yDAAyD;oBACnDE,YAAYU,IAAAA,sBAAa,EAACnB,KAAKE;oBACrC,IAAI,CAACkB,IAAAA,qBAAY,EAACpB,MAAM;wBACtB,MAAM,IAAIqB,oBAAU,CAAC,kBAAkB;oBACzC;oBACA,oFAAoF;oBACpF,yFAAyF;oBACzF,uDAAuD;oBACvD,IAAI,CAACZ,UAAUa,QAAQ,EAAE;wBACvB,MAAM,IAAID,oBAAU,CAAC,uBAAuB,AAAC,WAA+B,OAArBZ,UAAUc,UAAU,EAAC;oBAC9E;oBACA,IAAI,CAACC,IAAAA,qBAAY,EAACxB,MAAM;wBACtB,MAAM,IAAIqB,oBAAU,CAAC,uBAAuB;oBAC9C;oBACMX,UAAUe,IAAAA,oBAAW,EAAC1B,IAAIC,KAAKE;oBACrC,oFAAoF;oBACpF,oDAAoD;oBACpD;;wBAAMwB,IAAAA,qBAAY,EAAC3B,IAAIC,KAAKA,IAAI2B,OAAO;;;oBAAvC;oBACA,IAAI,CAACC,IAAAA,qBAAY,EAAC7B,IAAIM,OAAO;wBAC3B,MAAM,IAAIgB,oBAAU,CAAC,qBAAqB,AAAC,GAAO,OAALhB,MAAK;oBACpD;oBACA,IAAI,CAACwB,IAAAA,2BAAkB,EAAC9B,IAAIC,KAAKU,UAAU;;;;oBAC3C;;wBAAOoB,IAAAA,qBAAY,EAAC/B,IAAIC,KAAKK,MAAM;4BAAEG,SAAAA;4BAASE,SAAAA;4BAASP,GAAAA;wBAAE;;;;IAC3D"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/related.ts"],"sourcesContent":["import type { DatabaseSync } from 'node:sqlite';\nimport type { ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { embedConfig, embedEnabled, resolveSearch } from '../config/index.ts';\nimport { embedPending, hasEmbedding, similarNotes } from '../embed/query.ts';\nimport { localModelMissing, MODEL_FILENAMES } from '../embed/store.ts';\nimport { SenseError } from '../errors.ts';\nimport { resolveNote } from './peek.ts';\nimport { scopedPaths, scopeHasEmbeddings } from './scope.ts';\n\n// Notes most similar by cosine, excluding self and everything already linked either way.\n// Its own command, not a peek section: a full embeddings scan is ~480ms at 26k notes.\nexport async function relatedNotes(db: DatabaseSync, cfg: ResolvedConfig, pathArg: string, overrides: SearchOverrides, k: number): Promise<Array<{ path: string; similarity: number }>> {\n const paths = (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n const path = resolveNote(paths, pathArg);\n\n const outbound = (db.prepare('SELECT DISTINCT dst FROM links WHERE src = ? AND dst IS NOT NULL AND dst != src').all(path) as Array<{ dst: string }>).map((r) => r.dst);\n const backlinks = (db.prepare('SELECT DISTINCT src FROM links WHERE dst = ? AND src != dst').all(path) as Array<{ src: string }>).map((r) => r.src);\n const exclude = new Set([path, ...outbound, ...backlinks]);\n\n // Vectors are the only signal `related` has, so every way of not having them is an error\n // naming the cause. An empty table then means one thing: nothing near in meaning that this\n // note does not already link to, which is a real answer.\n const effective = resolveSearch(cfg, overrides);\n if (!embedEnabled(cfg)) {\n throw new SenseError('EMBED_DISABLED', 'related ranks notes by meaning, and this tree has no embedding model; add an \"embed\" block naming one to sense.config.json (a Hugging Face id fetches automatically at first use; `sense download` prefetches it) -- search works without it, on words and links');\n }\n // search gates on the same signal (see wantsVectors above); reading it here too keeps a\n // preset's declared signals meaning one thing. Without this, an overlapping vectors-on\n // preset's vectors would answer for a scope that declined them.\n if (effective.signals.vectors === undefined) {\n throw new SenseError('PRESET_NOT_SEMANTIC', `preset \"${effective.presetName}\" has no \"vectors\" signal, so this scope has no vectors and related has no other signal; search it instead (words and links), or add \"vectors\" to that preset's signals`);\n }\n // A downloadable HF id proceeds -- embedPending's getProvider call fetches it lazily on\n // consent. Only a local path with missing files can never fetch itself.\n const e = embedConfig(cfg); // embedEnabled(cfg) above guarantees this is set\n if (localModelMissing(e)) {\n throw new SenseError('EMBED_MODEL_MISSING', `related ranks notes by meaning, so it needs the embedding model, but the local model path \"${e.model}\" is missing ${MODEL_FILENAMES}; point embed.model at a directory containing them (search still works without it, on words and links)`);\n }\n const allowed = scopedPaths(db, cfg, overrides);\n // Top up pending rows before the seed check, or a fresh index reports every note as\n // having no indexed text until some search has run.\n await embedPending(db, cfg, cfg.baseDir);\n if (!hasEmbedding(db, path)) {\n throw new SenseError('NOTE_NOT_EMBEDDED', `${path} has no indexed text to compare -- a note that is frontmatter only, or empty, has nothing to rank by meaning`);\n }\n if (!scopeHasEmbeddings(db, cfg, allowed)) return [];\n return similarNotes(db, cfg, path, { exclude, allowed, k });\n}\n"],"names":["relatedNotes","db","cfg","pathArg","overrides","k","paths","path","outbound","backlinks","exclude","effective","e","allowed","prepare","all","map","r","resolveNote","dst","src","Set","resolveSearch","embedEnabled","SenseError","signals","vectors","undefined","presetName","embedConfig","localModelMissing","MODEL_FILENAMES","model","scopedPaths","embedPending","baseDir","hasEmbedding","scopeHasEmbeddings","similarNotes"],"mappings":";;;;+BAWsBA;;;eAAAA;;;uBATmC;uBACA;uBACN;wBACxB;sBACC;uBACoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIzC,SAAeA,aAAaC,EAAgB,EAAEC,GAAmB,EAAEC,OAAe,EAAEC,SAA0B,EAAEC,CAAS;;YACxHC,OACAC,MAEAC,UACAC,WACAC,SAKAC,WAYAC,GAIAC;;;;oBA1BAP,QAAQ,AAACL,GAAGa,OAAO,CAAC,kCAAkCC,GAAG,GAA+BC,GAAG,CAAC,SAACC;+BAAMA,EAAEV,IAAI;;oBACzGA,OAAOW,IAAAA,mBAAW,EAACZ,OAAOH;oBAE1BK,WAAW,AAACP,GAAGa,OAAO,CAAC,mFAAmFC,GAAG,CAACR,MAAiCS,GAAG,CAAC,SAACC;+BAAMA,EAAEE,GAAG;;oBAC/JV,YAAY,AAACR,GAAGa,OAAO,CAAC,+DAA+DC,GAAG,CAACR,MAAiCS,GAAG,CAAC,SAACC;+BAAMA,EAAEG,GAAG;;oBAC5IV,UAAU,IAAIW,IAAI;wBAACd;sBAAD,OAAO,qBAAGC,WAAU,qBAAGC;oBAE/C,yFAAyF;oBACzF,2FAA2F;oBAC3F,yDAAyD;oBACnDE,YAAYW,IAAAA,sBAAa,EAACpB,KAAKE;oBACrC,IAAI,CAACmB,IAAAA,qBAAY,EAACrB,MAAM;wBACtB,MAAM,IAAIsB,oBAAU,CAAC,kBAAkB;oBACzC;oBACA,wFAAwF;oBACxF,uFAAuF;oBACvF,gEAAgE;oBAChE,IAAIb,UAAUc,OAAO,CAACC,OAAO,KAAKC,WAAW;wBAC3C,MAAM,IAAIH,oBAAU,CAAC,uBAAuB,AAAC,WAA+B,OAArBb,UAAUiB,UAAU,EAAC;oBAC9E;oBACA,wFAAwF;oBACxF,wEAAwE;oBAClEhB,IAAIiB,IAAAA,oBAAW,EAAC3B,MAAM,iDAAiD;oBAC7E,IAAI4B,IAAAA,0BAAiB,EAAClB,IAAI;wBACxB,MAAM,IAAIY,oBAAU,CAAC,uBAAuB,AAAC,8FAAoHO,OAAvBnB,EAAEoB,KAAK,EAAC,iBAA+B,OAAhBD,wBAAe,EAAC;oBACnL;oBACMlB,UAAUoB,IAAAA,oBAAW,EAAChC,IAAIC,KAAKE;oBACrC,oFAAoF;oBACpF,oDAAoD;oBACpD;;wBAAM8B,IAAAA,qBAAY,EAACjC,IAAIC,KAAKA,IAAIiC,OAAO;;;oBAAvC;oBACA,IAAI,CAACC,IAAAA,qBAAY,EAACnC,IAAIM,OAAO;wBAC3B,MAAM,IAAIiB,oBAAU,CAAC,qBAAqB,AAAC,GAAO,OAALjB,MAAK;oBACpD;oBACA,IAAI,CAAC8B,IAAAA,2BAAkB,EAACpC,IAAIC,KAAKW,UAAU;;;;oBAC3C;;wBAAOyB,IAAAA,qBAAY,EAACrC,IAAIC,KAAKK,MAAM;4BAAEG,SAAAA;4BAASG,SAAAA;4BAASR,GAAAA;wBAAE;;;;IAC3D"}
@@ -35,8 +35,8 @@ _export(exports, {
35
35
  }
36
36
  });
37
37
  var _nodepath = require("node:path");
38
- var _columnhintts = require("../column-hint.js");
39
38
  var _indexts = require("../config/index.js");
39
+ var _columnhintts = require("../output/column-hint.js");
40
40
  function _array_like_to_array(arr, len) {
41
41
  if (len == null || len > arr.length) len = arr.length;
42
42
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/scope.ts"],"sourcesContent":["import { matchesGlob } from 'node:path';\nimport type { DatabaseSync } from 'node:sqlite';\nimport { columnHint } from '../column-hint.ts';\nimport type { ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { anyPresetEmbeds, resolveSearch } from '../config/index.ts';\n\nexport const INTERNAL_COLUMNS = new Set(['path', '_mtime', '_ctime', '_size', '_rank', '_parse_error']);\n\n// node:path's matchesGlob is experimental (stable behind an unstable-API flag) as of the\n// engines floor (Node >=22.20); scope filtering only ever needs single-pattern matching, so\n// it's used here in JS rather than running a directory walk in the query path.\nexport function inScope(path: string, include: string[], exclude?: string[]): boolean {\n if (!include.some((g) => matchesGlob(path, g))) return false;\n if (exclude?.some((g) => matchesGlob(path, g))) return false;\n return true;\n}\n\nexport function scopeHasEmbeddings(db: DatabaseSync, cfg: ResolvedConfig, scopedPaths: Set<string>): boolean {\n if (!anyPresetEmbeds(cfg)) return false; // the embeddings table doesn't exist at all in this case\n const rows = db.prepare('SELECT DISTINCT \"path\" FROM embeddings').all() as Array<{ path: string }>;\n return rows.some((r) => scopedPaths.has(r.path));\n}\n\n// Scope only (no --where): preset_files for a named preset, JS glob matching for an ad hoc\n// include/exclude override. Shared by scopedPaths() and search(), which also needs the\n// pre-where set to size the candidate-pool filter.\nexport function rawScope(db: DatabaseSync, cfg: ResolvedConfig, overrides: SearchOverrides, allPaths?: string[]): Set<string> {\n const effective = resolveSearch(cfg, overrides);\n const { include, exclude } = effective;\n const adHocScope = overrides.include !== undefined || overrides.exclude !== undefined || overrides.noExclude === true;\n if (!adHocScope) return new Set((db.prepare('SELECT \"path\" FROM preset_files WHERE preset = ?').all(effective.presetName) as Array<{ path: string }>).map((r) => r.path));\n const paths = allPaths ?? (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n return new Set(paths.filter((p) => inScope(p, include, exclude)));\n}\n\nexport function narrowByWhere(db: DatabaseSync, paths: Set<string>, where: string | undefined): Set<string> {\n if (!where) return paths;\n let whereRows: Array<{ path: string }>;\n try {\n whereRows = db.prepare(`SELECT \"path\" FROM frontmatter f WHERE (${where})`).all() as Array<{ path: string }>;\n } catch (err) {\n throw columnHint(db, err as Error);\n }\n const wherePaths = new Set(whereRows.map((r) => r.path));\n return new Set([...paths].filter((p) => wherePaths.has(p)));\n}\n\n// The scope resolver for non-search commands (path, peek, map): same coverage rule search()\n// applies, then narrowed by the resolved `where`.\nexport function scopedPaths(db: DatabaseSync, cfg: ResolvedConfig, overrides: SearchOverrides): Set<string> {\n const effective = resolveSearch(cfg, overrides);\n return narrowByWhere(db, rawScope(db, cfg, overrides), effective.where);\n}\n\n// Materializes a path set into a named temp table (same shape as traverse.ts's allowed_nodes)\n// so a query can join/filter against it cheaply instead of binding a parameter per path.\nexport function materializeScope(db: DatabaseSync, table: string, paths: Set<string>): void {\n db.exec(`DROP TABLE IF EXISTS ${table}`);\n db.exec(`CREATE TEMP TABLE ${table} (\"path\" TEXT PRIMARY KEY)`);\n db.prepare(`INSERT INTO ${table} SELECT DISTINCT value FROM json_each(?1)`).run(JSON.stringify([...paths]));\n}\n\nexport function setupMapScope(db: DatabaseSync, paths: Set<string>): void {\n materializeScope(db, '_map_scope', paths);\n}\n"],"names":["INTERNAL_COLUMNS","inScope","materializeScope","narrowByWhere","rawScope","scopeHasEmbeddings","scopedPaths","setupMapScope","Set","path","include","exclude","some","g","matchesGlob","db","cfg","anyPresetEmbeds","rows","prepare","all","r","has","overrides","allPaths","effective","resolveSearch","adHocScope","undefined","noExclude","presetName","map","paths","filter","p","where","whereRows","err","columnHint","wherePaths","table","exec","run","JSON","stringify"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/scope.ts"],"sourcesContent":["import { matchesGlob } from 'node:path';\nimport type { DatabaseSync } from 'node:sqlite';\nimport type { ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { anyPresetEmbeds, resolveSearch } from '../config/index.ts';\nimport { columnHint } from '../output/column-hint.ts';\n\nexport const INTERNAL_COLUMNS = new Set(['path', '_mtime', '_ctime', '_size', '_rank', '_parse_error']);\n\n// node:path's matchesGlob is experimental (stable behind an unstable-API flag) as of the\n// engines floor (Node >=22.20); scope filtering only ever needs single-pattern matching, so\n// it's used here in JS rather than running a directory walk in the query path.\nexport function inScope(path: string, include: string[], exclude?: string[]): boolean {\n if (!include.some((g) => matchesGlob(path, g))) return false;\n if (exclude?.some((g) => matchesGlob(path, g))) return false;\n return true;\n}\n\nexport function scopeHasEmbeddings(db: DatabaseSync, cfg: ResolvedConfig, scopedPaths: Set<string>): boolean {\n if (!anyPresetEmbeds(cfg)) return false; // the embeddings table doesn't exist at all in this case\n const rows = db.prepare('SELECT DISTINCT \"path\" FROM embeddings').all() as Array<{ path: string }>;\n return rows.some((r) => scopedPaths.has(r.path));\n}\n\n// Scope only (no --where): preset_files for a named preset, JS glob matching for an ad hoc\n// include/exclude override. Shared by scopedPaths() and search(), which also needs the\n// pre-where set to size the candidate-pool filter.\nexport function rawScope(db: DatabaseSync, cfg: ResolvedConfig, overrides: SearchOverrides, allPaths?: string[]): Set<string> {\n const effective = resolveSearch(cfg, overrides);\n const { include, exclude } = effective;\n const adHocScope = overrides.include !== undefined || overrides.exclude !== undefined || overrides.noExclude === true;\n if (!adHocScope) return new Set((db.prepare('SELECT \"path\" FROM preset_files WHERE preset = ?').all(effective.presetName) as Array<{ path: string }>).map((r) => r.path));\n const paths = allPaths ?? (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n return new Set(paths.filter((p) => inScope(p, include, exclude)));\n}\n\nexport function narrowByWhere(db: DatabaseSync, paths: Set<string>, where: string | undefined): Set<string> {\n if (!where) return paths;\n let whereRows: Array<{ path: string }>;\n try {\n whereRows = db.prepare(`SELECT \"path\" FROM frontmatter f WHERE (${where})`).all() as Array<{ path: string }>;\n } catch (err) {\n throw columnHint(db, err as Error);\n }\n const wherePaths = new Set(whereRows.map((r) => r.path));\n return new Set([...paths].filter((p) => wherePaths.has(p)));\n}\n\n// The scope resolver for non-search commands (path, peek, map): same coverage rule search()\n// applies, then narrowed by the resolved `where`.\nexport function scopedPaths(db: DatabaseSync, cfg: ResolvedConfig, overrides: SearchOverrides): Set<string> {\n const effective = resolveSearch(cfg, overrides);\n return narrowByWhere(db, rawScope(db, cfg, overrides), effective.where);\n}\n\n// Materializes a path set into a named temp table (same shape as traverse.ts's allowed_nodes)\n// so a query can join/filter against it cheaply instead of binding a parameter per path.\nexport function materializeScope(db: DatabaseSync, table: string, paths: Set<string>): void {\n db.exec(`DROP TABLE IF EXISTS ${table}`);\n db.exec(`CREATE TEMP TABLE ${table} (\"path\" TEXT PRIMARY KEY)`);\n db.prepare(`INSERT INTO ${table} SELECT DISTINCT value FROM json_each(?1)`).run(JSON.stringify([...paths]));\n}\n\nexport function setupMapScope(db: DatabaseSync, paths: Set<string>): void {\n materializeScope(db, '_map_scope', paths);\n}\n"],"names":["INTERNAL_COLUMNS","inScope","materializeScope","narrowByWhere","rawScope","scopeHasEmbeddings","scopedPaths","setupMapScope","Set","path","include","exclude","some","g","matchesGlob","db","cfg","anyPresetEmbeds","rows","prepare","all","r","has","overrides","allPaths","effective","resolveSearch","adHocScope","undefined","noExclude","presetName","map","paths","filter","p","where","whereRows","err","columnHint","wherePaths","table","exec","run","JSON","stringify"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import type { DatabaseSync } from 'node:sqlite';
2
2
  import type { ResolvedConfig } from '../config/index.js';
3
- import type { Row } from '../output.js';
3
+ import type { Row } from '../output/output.js';
4
4
  export interface SearchOptions {
5
5
  k?: number;
6
6
  where?: string;
@@ -1,6 +1,6 @@
1
1
  import type { DatabaseSync } from 'node:sqlite';
2
2
  import type { ResolvedConfig } from '../config/index.js';
3
- import type { Row } from '../output.js';
3
+ import type { Row } from '../output/output.js';
4
4
  export interface SearchOptions {
5
5
  k?: number;
6
6
  where?: string;
@@ -11,13 +11,12 @@ Object.defineProperty(exports, "search", {
11
11
  var _nodefs = require("node:fs");
12
12
  var _nodepath = require("node:path");
13
13
  var _indexts = require("../config/index.js");
14
+ var _storets = require("../embed/store.js");
14
15
  var _errorsts = require("../errors.js");
15
- var _embedts = require("../features/embed.js");
16
- var _indexts1 = require("../features/index.js");
17
- var _graphts = require("../graph.js");
18
- var _searcherrorts = require("../search-error.js");
19
- var _segmentts = require("../segment.js");
16
+ var _searcherrorts = require("../output/search-error.js");
17
+ var _segmentts = require("../text/segment.js");
20
18
  var _scopets = require("./scope.js");
19
+ var _signalsts = require("./signals.js");
21
20
  function _array_like_to_array(arr, len) {
22
21
  if (len == null || len > arr.length) len = arr.length;
23
22
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
@@ -26,9 +25,6 @@ function _array_like_to_array(arr, len) {
26
25
  function _array_with_holes(arr) {
27
26
  if (Array.isArray(arr)) return arr;
28
27
  }
29
- function _array_without_holes(arr) {
30
- if (Array.isArray(arr)) return _array_like_to_array(arr);
31
- }
32
28
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
33
29
  try {
34
30
  var info = gen[key](arg);
@@ -55,11 +51,6 @@ function _async_to_generator(fn) {
55
51
  });
56
52
  };
57
53
  }
58
- function _iterable_to_array(iter) {
59
- if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) {
60
- return Array.from(iter);
61
- }
62
- }
63
54
  function _iterable_to_array_limit(arr, i) {
64
55
  var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
65
56
  if (_i == null) return;
@@ -87,15 +78,9 @@ function _iterable_to_array_limit(arr, i) {
87
78
  function _non_iterable_rest() {
88
79
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
89
80
  }
90
- function _non_iterable_spread() {
91
- throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
92
- }
93
81
  function _sliced_to_array(arr, i) {
94
82
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
95
83
  }
96
- function _to_consumable_array(arr) {
97
- return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
98
- }
99
84
  function _ts_generator(thisArg, body) {
100
85
  var f, y, t, _ = {
101
86
  label: 0,
@@ -203,13 +188,8 @@ function _unsupported_iterable_to_array(o, minLen) {
203
188
  if (n === "Map" || n === "Set") return Array.from(n);
204
189
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
205
190
  }
206
- // Mirrors the main columns onto the sidecars, so a title match found through title_seg ranks
207
- // like a title match found through title, not like a body match.
208
- var WEIGHTED_BM25 = 'bm25(content, 10.0, 5.0, 1.0, 0, 10.0, 5.0, 1.0)';
209
- var RRF_K = 60;
210
191
  // snippet() re-tokenizes each candidate doc, superlinearly: ~10s for one 1MB doc
211
- // (BENCHMARKING.md). Past this bound, rows get the linear JS excerpt instead.
212
- var SNIPPET_BOUND = 16384;
192
+ // (benchmark/reports/2026-08-23-hub-release-battery.md). Past this bound, rows get the JS excerpt.
213
193
  var EXCERPT_WINDOW = 160;
214
194
  // Bare terms from an FTS5 query string: strips operators/quoting so the oversized-doc excerpt
215
195
  // scan matches the same words the query matched on, not FTS5 syntax.
@@ -346,14 +326,14 @@ function lineRangeFor(db, path, line) {
346
326
  }
347
327
  function search(_0, _1, _2) {
348
328
  return _async_to_generator(function(db, cfg, terms) {
349
- var opts, _hits_get, _chunkLines_get, _chunkSimilarity_get, effective, k, allPaths, scopePaths, scopeActive, allowedPaths, fetch, wantsVectors, semanticEnabled, scope, whereJoin, whereCond, scopeCond, matchSql, query, matchRows, hits, oversized, candidates, edges, linked, seeds, ranked, chunkLines, chunkSimilarity, vec, insert, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step_value, path, c, where, similarityCol, rows, bareTerms, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, row, text, _computeExcerpt, excerpt, offset;
329
+ var opts, _hits_get, _chunkLines_get, _chunkSimilarity_get, effective, k, signals, allPaths, scopePaths, scopeActive, allowedPaths, fetch, wantsVectors, e, semanticEnabled, scope, whereJoin, whereCond, scopeCond, query, candidates, matchRows, hits, oversized, chunkLines, chunkSimilarity, ref, insert, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step_value, path, c, where, similarityCol, rows, bareTerms, _iteratorNormalCompletion1, _didIteratorError1, _iteratorError1, _iterator1, _step1, row, text, _computeExcerpt, excerpt, offset;
350
330
  var _arguments = arguments;
351
331
  return _ts_generator(this, function(_state) {
352
332
  switch(_state.label){
353
333
  case 0:
354
334
  opts = _arguments.length > 3 && _arguments[3] !== void 0 ? _arguments[3] : {};
355
335
  effective = (0, _indexts.resolveSearch)(cfg, opts);
356
- k = effective.k;
336
+ k = effective.k, signals = effective.signals;
357
337
  allPaths = db.prepare('SELECT "path" FROM frontmatter').all().map(function(r) {
358
338
  return r.path;
359
339
  });
@@ -365,11 +345,14 @@ function search(_0, _1, _2) {
365
345
  throw (0, _searcherrorts.searchError)(err, terms, effective.where);
366
346
  }
367
347
  fetch = Math.max(k * 3, 30);
368
- // Asking for vectors without a model is a misconfiguration, not a mode: degrading would make
369
- // the same search answer differently before and after a download. semantic:false never asks.
370
- wantsVectors = effective.semantic && (0, _indexts.anyPresetEmbeds)(cfg);
371
- if (wantsVectors && !(0, _embedts.modelPresent)(cfg)) {
372
- throw new _errorsts.SenseError('EMBED_MODEL_MISSING', 'preset "'.concat(effective.presetName, '" searches with vectors, but the embedding model is not available; run `sense download`, or set "semantic": false on that preset to search on words and links'));
348
+ // A downloadable HF id proceeds -- getProvider fetches it lazily on consent. Only a
349
+ // local path with missing files errors here, since nothing will ever fetch it for itself.
350
+ wantsVectors = signals.vectors !== undefined;
351
+ if (wantsVectors) {
352
+ e = (0, _indexts.embedConfig)(cfg); // validate.ts guarantees this is set whenever "vectors" is declared
353
+ if ((0, _storets.localModelMissing)(e)) {
354
+ throw new _errorsts.SenseError('EMBED_MODEL_MISSING', 'preset "'.concat(effective.presetName, '" searches with vectors, but the local model path "').concat(e.model, '" is missing ').concat(_storets.MODEL_FILENAMES, '; point embed.model at a directory containing them, or drop "vectors" from that preset\'s signals to search without them'));
355
+ }
373
356
  }
374
357
  semanticEnabled = wantsVectors && (0, _scopets.scopeHasEmbeddings)(db, cfg, allowedPaths);
375
358
  // Terms pass to MATCH as written, with one transform: a run of text whose language marks no
@@ -391,17 +374,17 @@ function search(_0, _1, _2) {
391
374
  // thousands of paths, past SQLITE_MAX_VARIABLE_NUMBER on older builds.
392
375
  if (scopeActive) (0, _scopets.materializeScope)(db, '_search_scope', scopePaths);
393
376
  scopeCond = scopeActive ? 'AND content.path IN (SELECT "path" FROM _search_scope)' : '';
394
- // Docs past SNIPPET_BOUND skip snippet() entirely -- SQLite
395
- // short-circuits the untaken CASE branch, so it's never invoked on them.
396
- // Column 2 (text), not -1 (best column): -1 could surface a _seg sidecar as the excerpt,
397
- // which is machine-spaced and not what the author wrote. A row that matches only in a
398
- // sidecar gets an unhighlighted text excerpt below instead -- a stated cost.
399
- matchSql = "SELECT content.path AS path, CASE WHEN length(content.text) <= ".concat(SNIPPET_BOUND, " THEN snippet(content, 2, '\xab', '\xbb', '…', 10) ELSE NULL END AS hit FROM content ").concat(whereJoin, " WHERE content MATCH ? ").concat(whereCond, " ").concat(scopeCond, " ORDER BY ").concat(WEIGHTED_BM25, " LIMIT ").concat(fetch);
400
377
  query = (0, _indexts.contentTokenize)(cfg) === undefined ? (0, _segmentts.segmentMatch)(terms) : terms;
401
- try {
402
- matchRows = db.prepare(matchSql).all(query);
403
- } catch (err) {
404
- throw (0, _searcherrorts.searchError)(err, terms, scope);
378
+ candidates = new Map();
379
+ matchRows = [];
380
+ // A query that rewrites to nothing (e.g. only unspaced-script punctuation) has no
381
+ // searchable words: zero lexical rows, and the other signals still compose.
382
+ if (signals.words !== undefined && query.trim() !== '') {
383
+ try {
384
+ matchRows = (0, _signalsts.wordsCandidates)(db, candidates, query, whereJoin, whereCond, scopeCond, fetch, signals.words);
385
+ } catch (err) {
386
+ throw (0, _searcherrorts.searchError)(err, terms, scope);
387
+ }
405
388
  }
406
389
  hits = new Map(matchRows.map(function(r) {
407
390
  return [
@@ -416,46 +399,7 @@ function search(_0, _1, _2) {
416
399
  }).map(function(r) {
417
400
  return r.path;
418
401
  }));
419
- candidates = new Map();
420
- matchRows.forEach(function(r, i) {
421
- candidates.set(r.path, {
422
- score: 1 / (RRF_K + i),
423
- via: 'match'
424
- });
425
- });
426
- edges = (0, _indexts.featureEnabled)(cfg, 'links') && matchRows.length > 0 ? (0, _indexts1.linkEdges)(db) : [];
427
- if (edges.length > 0) {
428
- // Gates the label only, not the score: restart mass ranks every seed without an incident
429
- // edge, but dropping it from the score reweights fusion (FEVER hit@10 0.997 -> 0.907).
430
- linked = new Set(edges.flat());
431
- seeds = new Map(matchRows.map(function(r, i) {
432
- return [
433
- r.path,
434
- 1 / (i + 1)
435
- ];
436
- }));
437
- ranked = _to_consumable_array((0, _graphts.personalizedRank)(allPaths, edges, seeds)).filter(function(param) {
438
- var _param = _sliced_to_array(param, 2), path = _param[0], score = _param[1];
439
- return score > 1e-9 && allowedPaths.has(path);
440
- }).sort(function(a, b) {
441
- return b[1] - a[1];
442
- }).slice(0, fetch);
443
- ranked.forEach(function(param, i) {
444
- var _param = _sliced_to_array(param, 1), path = _param[0];
445
- var existing = candidates.get(path);
446
- if (existing) {
447
- existing.score += 1 / (RRF_K + i);
448
- if (linked.has(path)) existing.via = 'match+link';
449
- } else {
450
- candidates.set(path, {
451
- score: 1 / (RRF_K + i),
452
- via: 'link'
453
- });
454
- }
455
- });
456
- }
457
- // Vector expansion, invoked only: a third RRF list at the swept flat-region constants
458
- // (weight 1, pool = fetch). Each row carries its best chunk's line range.
402
+ if (signals.links !== undefined) (0, _signalsts.linksCandidates)(db, candidates, matchRows, allPaths, allowedPaths, fetch, signals.links);
459
403
  chunkLines = new Map();
460
404
  chunkSimilarity = new Map();
461
405
  if (!semanticEnabled) return [
@@ -464,25 +408,10 @@ function search(_0, _1, _2) {
464
408
  ];
465
409
  return [
466
410
  4,
467
- (0, _embedts.semanticCandidates)(db, cfg, terms, fetch, allowedPaths)
411
+ (0, _signalsts.vectorsCandidates)(db, cfg, candidates, terms, fetch, allowedPaths, signals.vectors)
468
412
  ];
469
413
  case 1:
470
- vec = _state.sent();
471
- vec.forEach(function(param, i) {
472
- var path = param.path, lines = param.lines, similarity = param.similarity;
473
- chunkLines.set(path, lines);
474
- chunkSimilarity.set(path, similarity);
475
- var existing = candidates.get(path);
476
- if (existing) {
477
- existing.score += 1 / (RRF_K + i);
478
- existing.via = "".concat(existing.via, "+vector");
479
- } else {
480
- candidates.set(path, {
481
- score: 1 / (RRF_K + i),
482
- via: 'vector'
483
- });
484
- }
485
- });
414
+ ref = _state.sent(), chunkLines = ref.chunkLines, chunkSimilarity = ref.chunkSimilarity, ref;
486
415
  _state.label = 2;
487
416
  case 2:
488
417
  db.exec('DROP TABLE IF EXISTS _search');