sensemaking 0.18.3 → 0.19.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 (368) hide show
  1. package/README.md +22 -4
  2. package/dist/cjs/chunk/group.js +10 -23
  3. package/dist/cjs/chunk/group.js.map +1 -1
  4. package/dist/cjs/chunk/parse.js +2 -5
  5. package/dist/cjs/chunk/parse.js.map +1 -1
  6. package/dist/cjs/cli/index.js.map +1 -1
  7. package/dist/cjs/cli/shared.js +6 -10
  8. package/dist/cjs/cli/shared.js.map +1 -1
  9. package/dist/cjs/cli/status.js +44 -10
  10. package/dist/cjs/cli/status.js.map +1 -1
  11. package/dist/cjs/cli.js +2 -8
  12. package/dist/cjs/cli.js.map +1 -1
  13. package/dist/cjs/commands/map.js +1 -3
  14. package/dist/cjs/commands/map.js.map +1 -1
  15. package/dist/cjs/commands/peek.js.map +1 -1
  16. package/dist/cjs/commands/related.js +3 -5
  17. package/dist/cjs/commands/related.js.map +1 -1
  18. package/dist/cjs/commands/scope.js.map +1 -1
  19. package/dist/cjs/commands/search.js +6 -8
  20. package/dist/cjs/commands/search.js.map +1 -1
  21. package/dist/cjs/commands/signals.js.map +1 -1
  22. package/dist/cjs/config/access.js.map +1 -1
  23. package/dist/cjs/config/index.d.cts +1 -1
  24. package/dist/cjs/config/index.d.ts +1 -1
  25. package/dist/cjs/config/index.js +3 -0
  26. package/dist/cjs/config/index.js.map +1 -1
  27. package/dist/cjs/config/load.js +10 -24
  28. package/dist/cjs/config/load.js.map +1 -1
  29. package/dist/cjs/config/resolve.js.map +1 -1
  30. package/dist/cjs/config/signals.js +2 -3
  31. package/dist/cjs/config/signals.js.map +1 -1
  32. package/dist/cjs/config/types.d.cts +2 -1
  33. package/dist/cjs/config/types.d.ts +2 -1
  34. package/dist/cjs/config/types.js +8 -0
  35. package/dist/cjs/config/types.js.map +1 -1
  36. package/dist/cjs/config/validate.d.cts +1 -1
  37. package/dist/cjs/config/validate.d.ts +1 -1
  38. package/dist/cjs/config/validate.js +9 -10
  39. package/dist/cjs/config/validate.js.map +1 -1
  40. package/dist/cjs/embed/cohere.js +2 -2
  41. package/dist/cjs/embed/cohere.js.map +1 -1
  42. package/dist/cjs/embed/distribution.js +3 -3
  43. package/dist/cjs/embed/distribution.js.map +1 -1
  44. package/dist/cjs/embed/handoff.d.cts +3 -0
  45. package/dist/cjs/embed/handoff.d.ts +3 -0
  46. package/dist/cjs/embed/handoff.js +39 -0
  47. package/dist/cjs/embed/handoff.js.map +1 -0
  48. package/dist/cjs/embed/identity.d.cts +11 -10
  49. package/dist/cjs/embed/identity.d.ts +11 -10
  50. package/dist/cjs/embed/identity.js +30 -15
  51. package/dist/cjs/embed/identity.js.map +1 -1
  52. package/dist/cjs/embed/langfit.js +2 -3
  53. package/dist/cjs/embed/langfit.js.map +1 -1
  54. package/dist/cjs/embed/languages.js +2 -4
  55. package/dist/cjs/embed/languages.js.map +1 -1
  56. package/dist/cjs/embed/openai.js +2 -2
  57. package/dist/cjs/embed/openai.js.map +1 -1
  58. package/dist/cjs/embed/query.js +58 -20
  59. package/dist/cjs/embed/query.js.map +1 -1
  60. package/dist/cjs/embed/registry.js +1 -2
  61. package/dist/cjs/embed/registry.js.map +1 -1
  62. package/dist/cjs/embed/static.d.cts +1 -1
  63. package/dist/cjs/embed/static.d.ts +1 -1
  64. package/dist/cjs/embed/static.js +8 -10
  65. package/dist/cjs/embed/static.js.map +1 -1
  66. package/dist/cjs/embed/store.d.cts +2 -2
  67. package/dist/cjs/embed/store.d.ts +2 -2
  68. package/dist/cjs/embed/store.js +48 -34
  69. package/dist/cjs/embed/store.js.map +1 -1
  70. package/dist/cjs/embed/types.js +1 -3
  71. package/dist/cjs/embed/types.js.map +1 -1
  72. package/dist/cjs/errors.d.cts +1 -1
  73. package/dist/cjs/errors.d.ts +1 -1
  74. package/dist/cjs/errors.js.map +1 -1
  75. package/dist/cjs/features/embed.js +19 -17
  76. package/dist/cjs/features/embed.js.map +1 -1
  77. package/dist/cjs/features/fences.js +5 -10
  78. package/dist/cjs/features/fences.js.map +1 -1
  79. package/dist/cjs/features/links.js +20 -37
  80. package/dist/cjs/features/links.js.map +1 -1
  81. package/dist/cjs/features/sections.js +21 -19
  82. package/dist/cjs/features/sections.js.map +1 -1
  83. package/dist/cjs/features/tags.js +5 -8
  84. package/dist/cjs/features/tags.js.map +1 -1
  85. package/dist/cjs/graph/traverse.js +1 -2
  86. package/dist/cjs/graph/traverse.js.map +1 -1
  87. package/dist/cjs/index.d.cts +1 -1
  88. package/dist/cjs/index.d.ts +1 -1
  89. package/dist/cjs/index.js +3 -0
  90. package/dist/cjs/index.js.map +1 -1
  91. package/dist/cjs/output/column-hint.js +3 -6
  92. package/dist/cjs/output/column-hint.js.map +1 -1
  93. package/dist/cjs/output/output.js +7 -14
  94. package/dist/cjs/output/output.js.map +1 -1
  95. package/dist/cjs/output/search-error.js +2 -5
  96. package/dist/cjs/output/search-error.js.map +1 -1
  97. package/dist/cjs/scan/frontmatter.d.cts +1 -0
  98. package/dist/cjs/scan/frontmatter.d.ts +1 -0
  99. package/dist/cjs/scan/frontmatter.js +14 -18
  100. package/dist/cjs/scan/frontmatter.js.map +1 -1
  101. package/dist/cjs/scan/list.js +2 -3
  102. package/dist/cjs/scan/list.js.map +1 -1
  103. package/dist/cjs/scan/reparse.js +12 -26
  104. package/dist/cjs/scan/reparse.js.map +1 -1
  105. package/dist/cjs/scan/worker-error.js.map +1 -1
  106. package/dist/cjs/store/cache.d.cts +2 -0
  107. package/dist/cjs/store/cache.d.ts +2 -0
  108. package/dist/cjs/store/cache.js +20 -0
  109. package/dist/cjs/store/cache.js.map +1 -0
  110. package/dist/cjs/store/duckdb/batch.js +4 -16
  111. package/dist/cjs/store/duckdb/batch.js.map +1 -1
  112. package/dist/cjs/store/duckdb/connection.js +8 -20
  113. package/dist/cjs/store/duckdb/connection.js.map +1 -1
  114. package/dist/cjs/store/duckdb/fieldStats.js +2 -8
  115. package/dist/cjs/store/duckdb/fieldStats.js.map +1 -1
  116. package/dist/cjs/store/duckdb/lexical.js +21 -29
  117. package/dist/cjs/store/duckdb/lexical.js.map +1 -1
  118. package/dist/cjs/store/duckdb/native.js.map +1 -1
  119. package/dist/cjs/store/duckdb/open.js +12 -13
  120. package/dist/cjs/store/duckdb/open.js.map +1 -1
  121. package/dist/cjs/store/duckdb/reconcile.js +4 -11
  122. package/dist/cjs/store/duckdb/reconcile.js.map +1 -1
  123. package/dist/cjs/store/duckdb/sql-functions.js +2 -4
  124. package/dist/cjs/store/duckdb/sql-functions.js.map +1 -1
  125. package/dist/cjs/store/duckdb/store.js +2 -3
  126. package/dist/cjs/store/duckdb/store.js.map +1 -1
  127. package/dist/cjs/store/duckdb/vectors.js +8 -18
  128. package/dist/cjs/store/duckdb/vectors.js.map +1 -1
  129. package/dist/cjs/store/index.d.cts +3 -2
  130. package/dist/cjs/store/index.d.ts +3 -2
  131. package/dist/cjs/store/index.js +7 -8
  132. package/dist/cjs/store/index.js.map +1 -1
  133. package/dist/cjs/store/native.js +6 -16
  134. package/dist/cjs/store/native.js.map +1 -1
  135. package/dist/cjs/store/sql-functions.js.map +1 -1
  136. package/dist/cjs/store/sqlite/connection.js +4 -8
  137. package/dist/cjs/store/sqlite/connection.js.map +1 -1
  138. package/dist/cjs/store/sqlite/fieldStats.js.map +1 -1
  139. package/dist/cjs/store/sqlite/lexical.js +3 -5
  140. package/dist/cjs/store/sqlite/lexical.js.map +1 -1
  141. package/dist/cjs/store/sqlite/open.d.cts +0 -1
  142. package/dist/cjs/store/sqlite/open.d.ts +0 -1
  143. package/dist/cjs/store/sqlite/open.js +22 -40
  144. package/dist/cjs/store/sqlite/open.js.map +1 -1
  145. package/dist/cjs/store/sqlite/reconcile.js +2 -3
  146. package/dist/cjs/store/sqlite/reconcile.js.map +1 -1
  147. package/dist/cjs/store/sqlite/sql-functions.js +2 -4
  148. package/dist/cjs/store/sqlite/sql-functions.js.map +1 -1
  149. package/dist/cjs/store/sqlite/store.js.map +1 -1
  150. package/dist/cjs/store/transaction.js +1 -3
  151. package/dist/cjs/store/transaction.js.map +1 -1
  152. package/dist/cjs/store/turso/connection.js +2 -6
  153. package/dist/cjs/store/turso/connection.js.map +1 -1
  154. package/dist/cjs/store/turso/fieldStats.js.map +1 -1
  155. package/dist/cjs/store/turso/lexical.d.cts +2 -0
  156. package/dist/cjs/store/turso/lexical.d.ts +2 -0
  157. package/dist/cjs/store/turso/lexical.js +347 -0
  158. package/dist/cjs/store/turso/lexical.js.map +1 -0
  159. package/dist/cjs/store/turso/native.js.map +1 -1
  160. package/dist/cjs/store/turso/open.d.cts +1 -1
  161. package/dist/cjs/store/turso/open.d.ts +1 -1
  162. package/dist/cjs/store/turso/open.js +81 -54
  163. package/dist/cjs/store/turso/open.js.map +1 -1
  164. package/dist/cjs/store/turso/reconcile.js +22 -22
  165. package/dist/cjs/store/turso/reconcile.js.map +1 -1
  166. package/dist/cjs/store/turso/store.js +18 -41
  167. package/dist/cjs/store/turso/store.js.map +1 -1
  168. package/dist/cjs/store/turso/vectors.d.cts +8 -0
  169. package/dist/cjs/store/turso/vectors.d.ts +8 -0
  170. package/dist/cjs/store/turso/vectors.js +435 -0
  171. package/dist/cjs/store/turso/vectors.js.map +1 -0
  172. package/dist/cjs/store/types.js +2 -3
  173. package/dist/cjs/store/types.js.map +1 -1
  174. package/dist/cjs/store/vectors.js.map +1 -1
  175. package/dist/cjs/text/segment.d.cts +1 -0
  176. package/dist/cjs/text/segment.d.ts +1 -0
  177. package/dist/cjs/text/segment.js +10 -14
  178. package/dist/cjs/text/segment.js.map +1 -1
  179. package/dist/cjs/watch.js +2 -5
  180. package/dist/cjs/watch.js.map +1 -1
  181. package/dist/cjs/workers/parse.js.map +1 -1
  182. package/dist/esm/chunk/group.js +10 -23
  183. package/dist/esm/chunk/group.js.map +1 -1
  184. package/dist/esm/chunk/parse.js +4 -8
  185. package/dist/esm/chunk/parse.js.map +1 -1
  186. package/dist/esm/cli/index.js +3 -5
  187. package/dist/esm/cli/index.js.map +1 -1
  188. package/dist/esm/cli/shared.js +12 -22
  189. package/dist/esm/cli/shared.js.map +1 -1
  190. package/dist/esm/cli/status.js +43 -9
  191. package/dist/esm/cli/status.js.map +1 -1
  192. package/dist/esm/cli.js +2 -8
  193. package/dist/esm/cli.js.map +1 -1
  194. package/dist/esm/commands/map.js +1 -3
  195. package/dist/esm/commands/map.js.map +1 -1
  196. package/dist/esm/commands/peek.js.map +1 -1
  197. package/dist/esm/commands/related.js +3 -5
  198. package/dist/esm/commands/related.js.map +1 -1
  199. package/dist/esm/commands/scope.js +3 -5
  200. package/dist/esm/commands/scope.js.map +1 -1
  201. package/dist/esm/commands/search.js +10 -16
  202. package/dist/esm/commands/search.js.map +1 -1
  203. package/dist/esm/commands/signals.js +3 -7
  204. package/dist/esm/commands/signals.js.map +1 -1
  205. package/dist/esm/config/access.js +8 -13
  206. package/dist/esm/config/access.js.map +1 -1
  207. package/dist/esm/config/index.d.ts +1 -1
  208. package/dist/esm/config/index.js +1 -1
  209. package/dist/esm/config/index.js.map +1 -1
  210. package/dist/esm/config/load.js +10 -24
  211. package/dist/esm/config/load.js.map +1 -1
  212. package/dist/esm/config/resolve.js +2 -3
  213. package/dist/esm/config/resolve.js.map +1 -1
  214. package/dist/esm/config/signals.js +3 -5
  215. package/dist/esm/config/signals.js.map +1 -1
  216. package/dist/esm/config/types.d.ts +2 -1
  217. package/dist/esm/config/types.js +8 -2
  218. package/dist/esm/config/types.js.map +1 -1
  219. package/dist/esm/config/validate.d.ts +1 -1
  220. package/dist/esm/config/validate.js +7 -10
  221. package/dist/esm/config/validate.js.map +1 -1
  222. package/dist/esm/embed/cohere.js +2 -2
  223. package/dist/esm/embed/cohere.js.map +1 -1
  224. package/dist/esm/embed/distribution.js +1 -1
  225. package/dist/esm/embed/distribution.js.map +1 -1
  226. package/dist/esm/embed/handoff.d.ts +3 -0
  227. package/dist/esm/embed/handoff.js +21 -0
  228. package/dist/esm/embed/handoff.js.map +1 -0
  229. package/dist/esm/embed/identity.d.ts +11 -10
  230. package/dist/esm/embed/identity.js +29 -26
  231. package/dist/esm/embed/identity.js.map +1 -1
  232. package/dist/esm/embed/langfit.js +2 -3
  233. package/dist/esm/embed/langfit.js.map +1 -1
  234. package/dist/esm/embed/languages.js +2 -4
  235. package/dist/esm/embed/languages.js.map +1 -1
  236. package/dist/esm/embed/openai.js +2 -2
  237. package/dist/esm/embed/openai.js.map +1 -1
  238. package/dist/esm/embed/query.js +21 -6
  239. package/dist/esm/embed/query.js.map +1 -1
  240. package/dist/esm/embed/registry.js +1 -2
  241. package/dist/esm/embed/registry.js.map +1 -1
  242. package/dist/esm/embed/static.d.ts +1 -1
  243. package/dist/esm/embed/static.js +8 -10
  244. package/dist/esm/embed/static.js.map +1 -1
  245. package/dist/esm/embed/store.d.ts +2 -2
  246. package/dist/esm/embed/store.js +28 -23
  247. package/dist/esm/embed/store.js.map +1 -1
  248. package/dist/esm/embed/types.js +1 -3
  249. package/dist/esm/embed/types.js.map +1 -1
  250. package/dist/esm/errors.d.ts +1 -1
  251. package/dist/esm/errors.js.map +1 -1
  252. package/dist/esm/features/embed.js +16 -16
  253. package/dist/esm/features/embed.js.map +1 -1
  254. package/dist/esm/features/fences.js +9 -19
  255. package/dist/esm/features/fences.js.map +1 -1
  256. package/dist/esm/features/links.js +24 -49
  257. package/dist/esm/features/links.js.map +1 -1
  258. package/dist/esm/features/sections.js +20 -20
  259. package/dist/esm/features/sections.js.map +1 -1
  260. package/dist/esm/features/tags.js +5 -8
  261. package/dist/esm/features/tags.js.map +1 -1
  262. package/dist/esm/features/types.js.map +1 -1
  263. package/dist/esm/graph/traverse.js +1 -2
  264. package/dist/esm/graph/traverse.js.map +1 -1
  265. package/dist/esm/index.d.ts +1 -1
  266. package/dist/esm/index.js +1 -1
  267. package/dist/esm/index.js.map +1 -1
  268. package/dist/esm/output/column-hint.js +3 -6
  269. package/dist/esm/output/column-hint.js.map +1 -1
  270. package/dist/esm/output/output.js +9 -20
  271. package/dist/esm/output/output.js.map +1 -1
  272. package/dist/esm/output/search-error.js +2 -5
  273. package/dist/esm/output/search-error.js.map +1 -1
  274. package/dist/esm/scan/frontmatter.d.ts +1 -0
  275. package/dist/esm/scan/frontmatter.js +13 -18
  276. package/dist/esm/scan/frontmatter.js.map +1 -1
  277. package/dist/esm/scan/list.js +2 -3
  278. package/dist/esm/scan/list.js.map +1 -1
  279. package/dist/esm/scan/reparse.js +16 -34
  280. package/dist/esm/scan/reparse.js.map +1 -1
  281. package/dist/esm/scan/worker-error.js.map +1 -1
  282. package/dist/esm/store/cache.d.ts +2 -0
  283. package/dist/esm/store/cache.js +11 -0
  284. package/dist/esm/store/cache.js.map +1 -0
  285. package/dist/esm/store/duckdb/batch.js +4 -16
  286. package/dist/esm/store/duckdb/batch.js.map +1 -1
  287. package/dist/esm/store/duckdb/connection.js +8 -20
  288. package/dist/esm/store/duckdb/connection.js.map +1 -1
  289. package/dist/esm/store/duckdb/fieldStats.js +4 -12
  290. package/dist/esm/store/duckdb/fieldStats.js.map +1 -1
  291. package/dist/esm/store/duckdb/lexical.js +29 -36
  292. package/dist/esm/store/duckdb/lexical.js.map +1 -1
  293. package/dist/esm/store/duckdb/native.js +2 -7
  294. package/dist/esm/store/duckdb/native.js.map +1 -1
  295. package/dist/esm/store/duckdb/open.js +16 -23
  296. package/dist/esm/store/duckdb/open.js.map +1 -1
  297. package/dist/esm/store/duckdb/reconcile.js +4 -11
  298. package/dist/esm/store/duckdb/reconcile.js.map +1 -1
  299. package/dist/esm/store/duckdb/sql-functions.js +4 -9
  300. package/dist/esm/store/duckdb/sql-functions.js.map +1 -1
  301. package/dist/esm/store/duckdb/store.js +6 -14
  302. package/dist/esm/store/duckdb/store.js.map +1 -1
  303. package/dist/esm/store/duckdb/vectors.js +14 -31
  304. package/dist/esm/store/duckdb/vectors.js.map +1 -1
  305. package/dist/esm/store/index.d.ts +3 -2
  306. package/dist/esm/store/index.js +5 -6
  307. package/dist/esm/store/index.js.map +1 -1
  308. package/dist/esm/store/native.js +10 -25
  309. package/dist/esm/store/native.js.map +1 -1
  310. package/dist/esm/store/sql-functions.js +3 -5
  311. package/dist/esm/store/sql-functions.js.map +1 -1
  312. package/dist/esm/store/sqlite/connection.js +4 -8
  313. package/dist/esm/store/sqlite/connection.js.map +1 -1
  314. package/dist/esm/store/sqlite/fieldStats.js +2 -6
  315. package/dist/esm/store/sqlite/fieldStats.js.map +1 -1
  316. package/dist/esm/store/sqlite/lexical.js +5 -9
  317. package/dist/esm/store/sqlite/lexical.js.map +1 -1
  318. package/dist/esm/store/sqlite/open.d.ts +0 -1
  319. package/dist/esm/store/sqlite/open.js +21 -41
  320. package/dist/esm/store/sqlite/open.js.map +1 -1
  321. package/dist/esm/store/sqlite/reconcile.js +6 -13
  322. package/dist/esm/store/sqlite/reconcile.js.map +1 -1
  323. package/dist/esm/store/sqlite/sql-functions.js +2 -4
  324. package/dist/esm/store/sqlite/sql-functions.js.map +1 -1
  325. package/dist/esm/store/sqlite/store.js +1 -2
  326. package/dist/esm/store/sqlite/store.js.map +1 -1
  327. package/dist/esm/store/transaction.js +2 -5
  328. package/dist/esm/store/transaction.js.map +1 -1
  329. package/dist/esm/store/turso/connection.js +2 -6
  330. package/dist/esm/store/turso/connection.js.map +1 -1
  331. package/dist/esm/store/turso/fieldStats.js +2 -5
  332. package/dist/esm/store/turso/fieldStats.js.map +1 -1
  333. package/dist/esm/store/turso/lexical.d.ts +2 -0
  334. package/dist/esm/store/turso/lexical.js +128 -0
  335. package/dist/esm/store/turso/lexical.js.map +1 -0
  336. package/dist/esm/store/turso/native.js +2 -7
  337. package/dist/esm/store/turso/native.js.map +1 -1
  338. package/dist/esm/store/turso/open.d.ts +1 -1
  339. package/dist/esm/store/turso/open.js +36 -29
  340. package/dist/esm/store/turso/open.js.map +1 -1
  341. package/dist/esm/store/turso/reconcile.js +22 -22
  342. package/dist/esm/store/turso/reconcile.js.map +1 -1
  343. package/dist/esm/store/turso/store.js +17 -28
  344. package/dist/esm/store/turso/store.js.map +1 -1
  345. package/dist/esm/store/turso/vectors.d.ts +8 -0
  346. package/dist/esm/store/turso/vectors.js +98 -0
  347. package/dist/esm/store/turso/vectors.js.map +1 -0
  348. package/dist/esm/store/types.js +2 -3
  349. package/dist/esm/store/types.js.map +1 -1
  350. package/dist/esm/store/vectors.js +2 -3
  351. package/dist/esm/store/vectors.js.map +1 -1
  352. package/dist/esm/text/segment.d.ts +1 -0
  353. package/dist/esm/text/segment.js +13 -21
  354. package/dist/esm/text/segment.js.map +1 -1
  355. package/dist/esm/watch.js +2 -5
  356. package/dist/esm/watch.js.map +1 -1
  357. package/dist/esm/workers/parse.js.map +1 -1
  358. package/package.json +3 -1
  359. package/schema.json +2 -2
  360. package/skills/sense/SKILL.md +2 -2
  361. package/skills/sense-setup/SKILL.md +3 -3
  362. package/dist/cjs/store/meta.d.cts +0 -3
  363. package/dist/cjs/store/meta.d.ts +0 -3
  364. package/dist/cjs/store/meta.js +0 -215
  365. package/dist/cjs/store/meta.js.map +0 -1
  366. package/dist/esm/store/meta.d.ts +0 -3
  367. package/dist/esm/store/meta.js +0 -17
  368. package/dist/esm/store/meta.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/status.ts"],"sourcesContent":["import { dirname } from 'node:path';\nimport { presetCoverage } from '../commands/status.ts';\nimport { embedConfig, featureStates, SUPPORTED_CONFIG_VERSION } from '../config/index.ts';\nimport { languageDistribution } from '../embed/distribution.ts';\nimport { probeReachable } from '../embed/http.ts';\nimport { isDownloadable, MODEL_FILENAMES, modelDir, modelPresent, readLanguages } from '../embed/store.ts';\nimport { featuresLine, presetsLines, stringifyJson } from '../output/output.ts';\nimport { docCount, getMeta, openStore } from '../store/index.ts';\nimport type { Store } from '../store/types.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, formatOf, parse, printWarnings } from './shared.ts';\nimport type { Command } from './types.ts';\n\n// status names what you cannot read off the config file: locations sense chose, values it\n// derived, state it stored. Config content is not echoed -- the config line says which file to\n// read, and duplicating its globs here would create two places that disagree after an edit.\n// The exception is the embed block's url and key, whose effect is remote and otherwise invisible.\n\n// Vectors are computed on the first semantic query, not at reconcile, so a tree can have a\n// semantic-on preset with nothing embedded yet -- reported here because a fast reconcile on\n// such a tree otherwise reads as \"the feature isn't on\".\nasync function vectorState(store: Store): Promise<{ embedded: number; pending: number } | null> {\n try {\n const stmt = await store.prepare('SELECT COUNT(vector) AS embedded, COUNT(*) - COUNT(vector) AS pending FROM embeddings');\n return (await stmt.get()) as { embedded: number; pending: number };\n } catch {\n return null;\n }\n}\n\nasync function parseErrorCount(store: Store): Promise<number> {\n const stmt = await store.prepare(`SELECT COUNT(*) AS n FROM frontmatter WHERE \"_parse_error\" IS NOT NULL`);\n return ((await stmt.get()) as { n: number }).n;\n}\n\n// A URL can carry credentials in its userinfo (https://user:pass@host/v1). status output gets\n// pasted into issues and transcripts, so it is always safe to paste.\nexport function redactUrl(url: string): string {\n try {\n const parsed = new URL(url);\n if (!parsed.username && !parsed.password) return url;\n parsed.username = '';\n parsed.password = '';\n return `${parsed.toString().replace(/\\/$/, '')} (credentials redacted)`;\n } catch {\n return url;\n }\n}\n\n// A stopped Ollama/LM Studio/Cohere endpoint prints identically to a running one otherwise; any\n// HTTP response counts as reachable (probeReachable), so this only distinguishes up from down.\nasync function embedReachable(e: { provider: string; url?: string }): Promise<boolean | null> {\n if (e.provider === 'static' || (e.provider === 'openai' && !e.url)) return null;\n const base = (e.url ?? 'https://api.cohere.com').replace(/\\/+$/, '');\n return probeReachable(e.provider === 'openai' ? `${base}/models` : base);\n}\n\nconst status: Command = async (ctx) => {\n const { values } = parse(ctx.argv, `usage: ${ctx.name} ${USAGE.status}`, { ...FORMAT, ...CONFIG });\n const format = formatOf(values);\n const cfg = ctx.resolveConfig(values.config as string | undefined);\n const { store, dbPath, warnings } = await openStore(cfg);\n printWarnings(warnings);\n\n const features = featureStates(cfg);\n const e = embedConfig(cfg);\n const hasModel = e ? modelPresent(cfg) : false;\n const reachable = e ? await embedReachable(e) : null;\n const vectors = e ? await vectorState(store) : null;\n const presets = await presetCoverage(store, cfg);\n const staticLanguages = e && e.provider === 'static' ? readLanguages(e.model) : undefined;\n const declaredLanguages = staticLanguages && staticLanguages.length > 0 ? staticLanguages : null;\n const detectedLanguages = (await languageDistribution(store)) ?? null;\n const heartbeat = await getMeta(store, 'watch_heartbeat');\n // Written by the store's open() on every open, so it is this cache's true version on either\n // store (sqlite 18, duckdb 2); a version mismatch already triggered a rebuild before this read.\n const cacheSchema = await getMeta(store, 'schema_version');\n // Each store owns what it reports and how it is worded (Store.engineStatus); this command\n // prints entries generically, without branching on any store's name.\n const engine = await store.engineStatus();\n // The env var holds the token; only its name and whether it is set are ever reported.\n const keyEnv = e?.key ? { name: e.key, set: (process.env[e.key] ?? '') !== '' } : null;\n const result = {\n config: cfg.configPath,\n configVersion: SUPPORTED_CONFIG_VERSION,\n migratedFrom: cfg.migratedFrom ?? null,\n unknownConfigKeys: cfg.unknownKeys ?? null,\n tree: cfg.baseDir,\n cache: dirname(dbPath),\n db: dbPath,\n cacheSchema,\n docs: await docCount(store),\n unparseableFrontmatter: await parseErrorCount(store),\n features: features.on,\n featuresOff: features.off,\n embed: e ? { provider: e.provider, model: e.model, dir: e.provider === 'static' ? modelDir(e.model) : null, url: e.url ? redactUrl(e.url) : null, reachable, keyEnv, downloaded: hasModel, languages: declaredLanguages, detectedLanguages, ...(vectors ?? {}) } : null,\n presets,\n queries: Object.keys(cfg.queries ?? {}).length,\n watcherPid: await getMeta(store, 'watch_pid'),\n watcherHeartbeatSecondsAgo: heartbeat ? Math.round((Date.now() - Date.parse(heartbeat)) / 1000) : null,\n engine,\n };\n\n if (format === 'json') {\n console.log(stringifyJson(result, 2));\n } else {\n const migrated = cfg.migratedFrom !== undefined ? `, migrated from v${cfg.migratedFrom} on this run` : '';\n console.log(`config: ${result.config} (v${SUPPORTED_CONFIG_VERSION}${migrated})`);\n // A load-time stderr warning has scrolled away by the time anyone looks here.\n if (cfg.unknownKeys) console.log(` unknown keys, ignored: ${cfg.unknownKeys.join(', ')}`);\n console.log(`tree: ${result.tree}`);\n console.log(`cache: ${result.cache} (schema ${result.cacheSchema}; delete this directory to reset)`);\n console.log(`docs: ${result.docs}${result.unparseableFrontmatter > 0 ? ` (${result.unparseableFrontmatter} with unparseable frontmatter: WHERE _parse_error IS NOT NULL)` : ''}`);\n console.log('');\n console.log(featuresLine(features));\n // One authoritative block, off states included: an absent model reads as a degraded search,\n // not as an empty corpus.\n if (!e) console.log('embed: off (no preset asks for vectors)');\n else {\n console.log(`embed: ${e.provider} ${e.model}`);\n if (e.provider === 'static') console.log(` model: ${modelDir(e.model)} (${hasModel ? 'present' : `missing, ${isDownloadable(e.model) ? `fetches automatically at first search, or run \\`${ctx.name} download\\` to prefetch` : `no ${MODEL_FILENAMES} in that directory`}`})`);\n if (declaredLanguages) console.log(` languages: ${declaredLanguages.join(', ')} (declared by the model card)`);\n // Cohere defaults to api.cohere.com with no url in the config; show it anyway so the\n // reachability probe below has something to name.\n if (e.url || reachable !== null) {\n const shown = e.url ? redactUrl(e.url) : 'https://api.cohere.com (default)';\n console.log(` url: ${shown}${reachable === null ? '' : reachable ? ' (reachable)' : ' (unreachable)'}`);\n }\n if (keyEnv) console.log(` key: env ${keyEnv.name} (${keyEnv.set ? 'set' : 'NOT SET'})`);\n if (!hasModel) console.log(' vectors: off until the model is present; search runs on words and links');\n else if (vectors) console.log(` vectors: ${vectors.embedded} embedded, ${vectors.pending} pending (embedded on the first semantic search)`);\n if (detectedLanguages) {\n const total = Object.values(detectedLanguages).reduce((a, b) => a + b, 0);\n const breakdown = Object.entries(detectedLanguages)\n .sort((a, b) => b[1] - a[1])\n .map(([code, n]) => `${code} ${Math.round((n / total) * 100)}%`)\n .join(', ');\n console.log(` detected: ${breakdown} (${total} chunks classified)`);\n }\n }\n console.log('');\n for (const line of presetsLines(presets)) console.log(line);\n console.log('');\n console.log(`queries: ${result.queries} saved (${ctx.name} --list)`);\n const pid = result.watcherPid ? `pid ${result.watcherPid}, ` : '';\n console.log(result.watcherHeartbeatSecondsAgo === null ? 'watcher: none' : `watcher: ${pid}last heartbeat ${result.watcherHeartbeatSecondsAgo}s ago`);\n for (const [key, value] of Object.entries(result.engine)) console.log(`${`${store.name}:`.padEnd(10)}${key} ${value}`);\n }\n await store.close();\n};\nexport default status;\n"],"names":["redactUrl","vectorState","store","stmt","prepare","get","parseErrorCount","n","url","parsed","URL","username","password","toString","replace","embedReachable","e","base","provider","probeReachable","status","ctx","process","cfg","values","format","dbPath","warnings","features","hasModel","reachable","vectors","presets","staticLanguages","declaredLanguages","detectedLanguages","heartbeat","cacheSchema","engine","keyEnv","result","migrated","shown","total","breakdown","line","pid","key","value","parse","argv","USAGE","name","FORMAT","CONFIG","formatOf","resolveConfig","config","openStore","printWarnings","featureStates","embedConfig","modelPresent","presetCoverage","readLanguages","model","undefined","length","languageDistribution","getMeta","engineStatus","set","env","configPath","configVersion","SUPPORTED_CONFIG_VERSION","migratedFrom","unknownConfigKeys","unknownKeys","tree","baseDir","cache","dirname","db","docCount","docs","unparseableFrontmatter","on","featuresOff","off","embed","dir","modelDir","downloaded","languages","queries","Object","keys","watcherPid","watcherHeartbeatSecondsAgo","Math","round","Date","now","console","log","stringifyJson","join","featuresLine","isDownloadable","MODEL_FILENAMES","embedded","pending","reduce","a","b","entries","sort","map","code","presetsLines","padEnd","close"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/status.ts"],"sourcesContent":["import { dirname } from 'node:path';\nimport { presetCoverage } from '../commands/status.ts';\nimport { embedConfig, featureStates, SUPPORTED_CONFIG_VERSION } from '../config/index.ts';\nimport { languageDistribution } from '../embed/distribution.ts';\nimport { probeReachable } from '../embed/http.ts';\nimport { isDownloadable, MODEL_FILENAMES, modelDir, modelPresent, readLanguages } from '../embed/store.ts';\nimport { featuresLine, presetsLines, stringifyJson } from '../output/output.ts';\nimport { docCount, getMeta, openStore } from '../store/index.ts';\nimport type { Store } from '../store/types.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, formatOf, parse, printWarnings } from './shared.ts';\nimport type { Command } from './types.ts';\n\n// status names what you cannot read off the config file: locations sense chose, values it derived, state it stored. Config content itself is not echoed, since duplicating its globs here would create two places that disagree after an edit.\n// The exception is the embed block's url and key, whose effect is remote and otherwise invisible.\n\n// Vectors are computed on the first semantic query, not at reconcile, so a tree can have a semantic-on preset with nothing embedded yet.\n// Reported here because a fast reconcile on such a tree otherwise reads as \"the feature isn't on\".\nasync function vectorState(store: Store): Promise<{ embedded: number; pending: number } | null> {\n try {\n const stmt = await store.prepare('SELECT COUNT(vector) AS embedded, COUNT(*) - COUNT(vector) AS pending FROM embeddings');\n return (await stmt.get()) as { embedded: number; pending: number };\n } catch {\n return null;\n }\n}\n\nasync function parseErrorCount(store: Store): Promise<number> {\n const stmt = await store.prepare(`SELECT COUNT(*) AS n FROM frontmatter WHERE \"_parse_error\" IS NOT NULL`);\n return ((await stmt.get()) as { n: number }).n;\n}\n\n// A URL can carry credentials in its userinfo (https://user:pass@host/v1). status output gets\n// pasted into issues and transcripts, so it is always safe to paste.\nexport function redactUrl(url: string): string {\n try {\n const parsed = new URL(url);\n if (!parsed.username && !parsed.password) return url;\n parsed.username = '';\n parsed.password = '';\n return `${parsed.toString().replace(/\\/$/, '')} (credentials redacted)`;\n } catch {\n return url;\n }\n}\n\n// A stopped Ollama/LM Studio/Cohere endpoint prints identically to a running one otherwise; any\n// HTTP response counts as reachable (probeReachable), so this only distinguishes up from down.\nasync function embedReachable(e: { provider: string; url?: string }): Promise<boolean | null> {\n if (e.provider === 'static' || (e.provider === 'openai' && !e.url)) return null;\n const base = (e.url ?? 'https://api.cohere.com').replace(/\\/+$/, '');\n return probeReachable(e.provider === 'openai' ? `${base}/models` : base);\n}\n\ntype LanguagesState = 'declared' | 'none' | 'unresolved' | null;\n\n// Config-declared languages win over the model card, for every provider, as registry.ts does.\n// A local-path model has no card by design, so it is never \"unresolved\": that means an HF id.\nfunction languagesInfo(e: NonNullable<ReturnType<typeof embedConfig>>): { languages: string[] | null; state: LanguagesState; source: 'config' | 'card' | null } {\n if (e.languages) return { languages: e.languages, state: 'declared', source: 'config' };\n if (e.provider !== 'static' || !isDownloadable(e.model)) return { languages: null, state: null, source: null };\n const cardLanguages = readLanguages(e.model);\n if (cardLanguages === undefined) return { languages: null, state: 'unresolved', source: null };\n if (cardLanguages.length === 0) return { languages: null, state: 'none', source: null };\n return { languages: cardLanguages, state: 'declared', source: 'card' };\n}\n\nconst status: Command = async (ctx) => {\n const { values } = parse(ctx.argv, `usage: ${ctx.name} ${USAGE.status}`, { ...FORMAT, ...CONFIG });\n const format = formatOf(values);\n const cfg = ctx.resolveConfig(values.config as string | undefined);\n const { store, dbPath, warnings } = await openStore(cfg);\n printWarnings(warnings);\n\n const features = featureStates(cfg);\n const e = embedConfig(cfg);\n const hasModel = e ? modelPresent(cfg) : false;\n const reachable = e ? await embedReachable(e) : null;\n const vectors = e ? await vectorState(store) : null;\n const presets = await presetCoverage(store, cfg);\n const { languages: declaredLanguages, state: languagesState, source: languagesSource } = e ? languagesInfo(e) : { languages: null, state: null, source: null };\n const detectedLanguages = (await languageDistribution(store)) ?? null;\n const heartbeat = await getMeta(store, 'watch_heartbeat');\n // Written by the store's open() on every open, so it is this cache's true version on either\n // store (sqlite 18, duckdb 2); a version mismatch already triggered a rebuild before this read.\n const cacheSchema = await getMeta(store, 'schema_version');\n // Each store owns what it reports and how it is worded (Store.engineStatus); this command\n // prints entries generically, without branching on any store's name.\n const engine = await store.engineStatus();\n // The env var holds the token; only its name and whether it is set are ever reported.\n const keyEnv = e?.key ? { name: e.key, set: (process.env[e.key] ?? '') !== '' } : null;\n const result = {\n config: cfg.configPath,\n configVersion: SUPPORTED_CONFIG_VERSION,\n migratedFrom: cfg.migratedFrom ?? null,\n unknownConfigKeys: cfg.unknownKeys ?? null,\n tree: cfg.baseDir,\n cache: dirname(dbPath),\n db: dbPath,\n cacheSchema,\n docs: await docCount(store),\n unparseableFrontmatter: await parseErrorCount(store),\n features: features.on,\n featuresOff: features.off,\n embed: e ? { provider: e.provider, model: e.model, dir: e.provider === 'static' ? modelDir(e.model) : null, url: e.url ? redactUrl(e.url) : null, reachable, keyEnv, downloaded: hasModel, languages: declaredLanguages, languagesState, detectedLanguages, ...(vectors ?? {}) } : null,\n presets,\n queries: Object.keys(cfg.queries ?? {}).length,\n watcherPid: await getMeta(store, 'watch_pid'),\n watcherHeartbeatSecondsAgo: heartbeat ? Math.round((Date.now() - Date.parse(heartbeat)) / 1000) : null,\n engine,\n };\n\n if (format === 'json') {\n console.log(stringifyJson(result, 2));\n } else {\n const migrated = cfg.migratedFrom !== undefined ? `, migrated from v${cfg.migratedFrom} on this run` : '';\n console.log(`config: ${result.config} (v${SUPPORTED_CONFIG_VERSION}${migrated})`);\n // A load-time stderr warning has scrolled away by the time anyone looks here.\n if (cfg.unknownKeys) console.log(` unknown keys, ignored: ${cfg.unknownKeys.join(', ')}`);\n console.log(`tree: ${result.tree}`);\n console.log(`cache: ${result.cache} (schema ${result.cacheSchema}; delete this directory to reset)`);\n console.log(`docs: ${result.docs}${result.unparseableFrontmatter > 0 ? ` (${result.unparseableFrontmatter} with unparseable frontmatter: WHERE _parse_error IS NOT NULL)` : ''}`);\n console.log('');\n console.log(featuresLine(features));\n // One authoritative block, off states included: an absent model reads as a degraded search,\n // not as an empty corpus.\n if (!e) console.log('embed: off (no preset asks for vectors)');\n else {\n console.log(`embed: ${e.provider} ${e.model}`);\n if (e.provider === 'static') console.log(` model: ${modelDir(e.model)} (${hasModel ? 'present' : `missing, ${isDownloadable(e.model) ? `fetches automatically at first search, or run \\`${ctx.name} download\\` to prefetch` : `no ${MODEL_FILENAMES} in that directory`}`})`);\n if (declaredLanguages && languagesSource === 'config') console.log(` languages: ${declaredLanguages.join(', ')} (declared in embed.languages)`);\n else if (declaredLanguages && languagesSource === 'card') console.log(` languages: ${declaredLanguages.join(', ')} (declared by the model card)`);\n else if (languagesState === 'none') console.log(' languages: none declared by the model card');\n else if (languagesState === 'unresolved') console.log(` languages: unresolved (model card unreachable; run \\`${ctx.name} download\\`)`);\n // Cohere defaults to api.cohere.com with no url in the config; show it anyway so the\n // reachability probe below has something to name.\n if (e.url || reachable !== null) {\n const shown = e.url ? redactUrl(e.url) : 'https://api.cohere.com (default)';\n console.log(` url: ${shown}${reachable === null ? '' : reachable ? ' (reachable)' : ' (unreachable)'}`);\n }\n if (keyEnv) console.log(` key: env ${keyEnv.name} (${keyEnv.set ? 'set' : 'NOT SET'})`);\n if (!hasModel) console.log(' vectors: off until the model is present; search runs on words and links');\n else if (vectors) console.log(` vectors: ${vectors.embedded} embedded, ${vectors.pending} pending (embedded on the first semantic search)`);\n if (detectedLanguages) {\n const total = Object.values(detectedLanguages).reduce((a, b) => a + b, 0);\n const breakdown = Object.entries(detectedLanguages)\n .sort((a, b) => b[1] - a[1])\n .map(([code, n]) => `${code} ${Math.round((n / total) * 100)}%`)\n .join(', ');\n console.log(` detected: ${breakdown} (${total} chunks classified)`);\n }\n }\n console.log('');\n for (const line of presetsLines(presets)) console.log(line);\n console.log('');\n console.log(`queries: ${result.queries} saved (${ctx.name} --list)`);\n const pid = result.watcherPid ? `pid ${result.watcherPid}, ` : '';\n console.log(result.watcherHeartbeatSecondsAgo === null ? 'watcher: none' : `watcher: ${pid}last heartbeat ${result.watcherHeartbeatSecondsAgo}s ago`);\n for (const [key, value] of Object.entries(result.engine)) console.log(`${`${store.name}:`.padEnd(10)}${key} ${value}`);\n }\n await store.close();\n};\nexport default status;\n"],"names":["redactUrl","vectorState","store","stmt","prepare","get","parseErrorCount","n","url","parsed","URL","username","password","toString","replace","embedReachable","e","base","provider","probeReachable","languagesInfo","languages","state","source","isDownloadable","model","cardLanguages","readLanguages","undefined","length","status","ctx","process","cfg","values","format","dbPath","warnings","features","hasModel","reachable","vectors","presets","declaredLanguages","languagesState","languagesSource","detectedLanguages","heartbeat","cacheSchema","engine","keyEnv","result","migrated","shown","total","breakdown","line","pid","key","value","parse","argv","USAGE","name","FORMAT","CONFIG","formatOf","resolveConfig","config","openStore","printWarnings","featureStates","embedConfig","modelPresent","presetCoverage","languageDistribution","getMeta","engineStatus","set","env","configPath","configVersion","SUPPORTED_CONFIG_VERSION","migratedFrom","unknownConfigKeys","unknownKeys","tree","baseDir","cache","dirname","db","docCount","docs","unparseableFrontmatter","on","featuresOff","off","embed","dir","modelDir","downloaded","queries","Object","keys","watcherPid","watcherHeartbeatSecondsAgo","Math","round","Date","now","console","log","stringifyJson","join","featuresLine","MODEL_FILENAMES","embedded","pending","reduce","a","b","entries","sort","map","code","presetsLines","padEnd","close"],"mappings":"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"}
package/dist/cjs/cli.js CHANGED
@@ -240,14 +240,8 @@ function cli(argv, name) {
240
240
  return _ts_generator(this, function(_state) {
241
241
  switch(_state.label){
242
242
  case 0:
243
- // stdout is a pipe whenever the caller pipes or redirects, and a reader that goes away
244
- // (`| head`) makes every later write fail. The failure arrives asynchronously, after the
245
- // write loop has already returned: console.log absorbs it, process.stdout.write (what the
246
- // streaming formats use) does not, so with no listener the process dies on an unhandled
247
- // 'error' event having already done its work. Neither throwing nor exiting is safe from
248
- // here. The event is async, so a throw is an uncaught exception rather than something
249
- // bin/cli.js can catch, and process.exit() would skip the cleanup `sense watch` runs on the
250
- // way out, leaving a heartbeat behind that makes a dead watcher look alive.
243
+ // A closed pipe reader's EPIPE arrives async, after the write loop returns: console.log absorbs it, process.stdout.write (streaming formats) does not, so an unhandled listener kills the process.
244
+ // A throw here is uncaught (async); process.exit() would skip `sense watch`'s cleanup, leaving a heartbeat behind that makes a dead watcher look alive.
251
245
  process.stdout.on('error', function(err) {
252
246
  if (err.code === 'EPIPE') return;
253
247
  console.error("sense: ".concat(err.message));
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { parseArgs } from 'node:util';\nimport { COMMANDS, USAGE } from './cli/index.ts';\nimport type { Ctx } from './cli/types.ts';\nimport { loadConfig, SUPPORTED_CONFIG_VERSION } from './config/index.ts';\n\n// Parsing and dispatch only; commands lazy-load from src/cli/, so nothing heavy is imported\n// here. Flags parse per command -- this file handles only --version/--help/--list/--config.\n\n// Works from dist/cjs and dist/esm alike: walk up past the dist type-marker package.json.\nfunction packageVersion(): string {\n const load = createRequire(import.meta.url);\n for (const rel of ['../package.json', '../../package.json', '../../../package.json']) {\n try {\n const pkg = load(rel) as { name?: string; version?: string };\n if (pkg.name === 'sensemaking' && pkg.version) return pkg.version;\n } catch {}\n }\n return 'unknown';\n}\n\nfunction usage(name: string): string {\n const lines = Object.values(USAGE).map((u) => ` ${name} ${u}`);\n return [`usage: ${name} <name> [params...] [--format table|json|csv] [--config path]`, ...lines, ` ${name} --list`, ` ${name} --version`].join('\\n');\n}\n\nfunction resolveConfigFor(name: string, configPath: string | undefined) {\n const cfg = loadConfig(configPath);\n if (cfg.migratedFrom !== undefined) {\n console.warn(`${name}: migrated ${cfg.configPath} from config version ${cfg.migratedFrom} to ${SUPPORTED_CONFIG_VERSION}`);\n }\n if (cfg.unknownKeys !== undefined) {\n console.warn(`${name}: ${cfg.configPath} sets ${cfg.unknownKeys.join(', ')}, which this build does not read (no effect); see schema.json for the keys it does`);\n }\n return cfg;\n}\n\n// Thrown errors -> exit 1 with the message verbatim; usage errors exit 2 directly.\nexport default async function cli(argv: string[], name: string): Promise<void> {\n // stdout is a pipe whenever the caller pipes or redirects, and a reader that goes away\n // (`| head`) makes every later write fail. The failure arrives asynchronously, after the\n // write loop has already returned: console.log absorbs it, process.stdout.write (what the\n // streaming formats use) does not, so with no listener the process dies on an unhandled\n // 'error' event having already done its work. Neither throwing nor exiting is safe from\n // here. The event is async, so a throw is an uncaught exception rather than something\n // bin/cli.js can catch, and process.exit() would skip the cleanup `sense watch` runs on the\n // way out, leaving a heartbeat behind that makes a dead watcher look alive.\n process.stdout.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EPIPE') return;\n console.error(`sense: ${err.message}`);\n process.exitCode = 1;\n });\n\n const first = argv[0];\n\n // No command word, or the first token looks like a flag: the only flags this level knows.\n if (!first || first.startsWith('-')) {\n let values: Record<string, string | boolean | undefined>;\n try {\n ({ values } = parseArgs({\n args: argv,\n options: {\n version: { type: 'boolean', default: false, short: 'v' },\n help: { type: 'boolean', default: false, short: 'h' },\n list: { type: 'boolean', default: false },\n config: { type: 'string' },\n },\n allowPositionals: true,\n }));\n } catch (err) {\n console.error((err as Error).message);\n console.error(usage(name));\n process.exit(2);\n }\n\n try {\n if (values.version) {\n console.log(packageVersion());\n return;\n }\n if (values.help) {\n console.log(usage(name));\n return;\n }\n if (values.list) {\n const queries = resolveConfigFor(name, values.config as string | undefined).queries;\n for (const queryName of Object.keys(queries).sort()) {\n // Every entry names its verb, so --list can label both kinds rather than only\n // marking the exception.\n console.log(`${queryName} (${'search' in queries[queryName] ? 'search' : 'sql'})`);\n }\n return;\n }\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n\n console.error(usage(name));\n process.exit(2);\n }\n\n // Breaking renames get one release of a pointer instead of an \"unknown\" error: find ->\n // search, and query -> sql (which took its name back from the search sense of \"query\").\n const RENAMED: Record<string, string> = { find: 'search', query: 'sql' };\n if (RENAMED[first]) {\n console.error(`${name}: ${first} is now ${RENAMED[first]}`);\n console.error(usage(name));\n process.exit(2);\n }\n\n const ctx: Ctx = {\n name,\n argv: argv.slice(1),\n resolveConfig: (configPath) => resolveConfigFor(name, configPath),\n usageError(message) {\n console.error(message);\n process.exit(2);\n },\n };\n\n try {\n const load = COMMANDS[first];\n if (load) await (await load()).default(ctx);\n else await (await import('./cli/named.ts')).default(ctx, first);\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n}\n"],"names":["cli","packageVersion","load","createRequire","rel","pkg","name","version","usage","lines","Object","values","USAGE","map","u","join","resolveConfigFor","configPath","cfg","loadConfig","migratedFrom","undefined","console","warn","SUPPORTED_CONFIG_VERSION","unknownKeys","argv","first","queries","queryName","RENAMED","ctx","err","process","stdout","on","code","error","message","exitCode","startsWith","parseArgs","args","options","type","default","short","help","list","config","allowPositionals","exit","log","keys","sort","find","query","slice","resolveConfig","usageError","COMMANDS"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { parseArgs } from 'node:util';\nimport { COMMANDS, USAGE } from './cli/index.ts';\nimport type { Ctx } from './cli/types.ts';\nimport { loadConfig, SUPPORTED_CONFIG_VERSION } from './config/index.ts';\n\n// Parsing and dispatch only; commands lazy-load from src/cli/, so nothing heavy is imported\n// here. Flags parse per command -- this file handles only --version/--help/--list/--config.\n\n// Works from dist/cjs and dist/esm alike: walk up past the dist type-marker package.json.\nfunction packageVersion(): string {\n const load = createRequire(import.meta.url);\n for (const rel of ['../package.json', '../../package.json', '../../../package.json']) {\n try {\n const pkg = load(rel) as { name?: string; version?: string };\n if (pkg.name === 'sensemaking' && pkg.version) return pkg.version;\n } catch {}\n }\n return 'unknown';\n}\n\nfunction usage(name: string): string {\n const lines = Object.values(USAGE).map((u) => ` ${name} ${u}`);\n return [`usage: ${name} <name> [params...] [--format table|json|csv] [--config path]`, ...lines, ` ${name} --list`, ` ${name} --version`].join('\\n');\n}\n\nfunction resolveConfigFor(name: string, configPath: string | undefined) {\n const cfg = loadConfig(configPath);\n if (cfg.migratedFrom !== undefined) {\n console.warn(`${name}: migrated ${cfg.configPath} from config version ${cfg.migratedFrom} to ${SUPPORTED_CONFIG_VERSION}`);\n }\n if (cfg.unknownKeys !== undefined) {\n console.warn(`${name}: ${cfg.configPath} sets ${cfg.unknownKeys.join(', ')}, which this build does not read (no effect); see schema.json for the keys it does`);\n }\n return cfg;\n}\n\n// Thrown errors -> exit 1 with the message verbatim; usage errors exit 2 directly.\nexport default async function cli(argv: string[], name: string): Promise<void> {\n // A closed pipe reader's EPIPE arrives async, after the write loop returns: console.log absorbs it, process.stdout.write (streaming formats) does not, so an unhandled listener kills the process.\n // A throw here is uncaught (async); process.exit() would skip `sense watch`'s cleanup, leaving a heartbeat behind that makes a dead watcher look alive.\n process.stdout.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EPIPE') return;\n console.error(`sense: ${err.message}`);\n process.exitCode = 1;\n });\n\n const first = argv[0];\n\n // No command word, or the first token looks like a flag: the only flags this level knows.\n if (!first || first.startsWith('-')) {\n let values: Record<string, string | boolean | undefined>;\n try {\n ({ values } = parseArgs({\n args: argv,\n options: {\n version: { type: 'boolean', default: false, short: 'v' },\n help: { type: 'boolean', default: false, short: 'h' },\n list: { type: 'boolean', default: false },\n config: { type: 'string' },\n },\n allowPositionals: true,\n }));\n } catch (err) {\n console.error((err as Error).message);\n console.error(usage(name));\n process.exit(2);\n }\n\n try {\n if (values.version) {\n console.log(packageVersion());\n return;\n }\n if (values.help) {\n console.log(usage(name));\n return;\n }\n if (values.list) {\n const queries = resolveConfigFor(name, values.config as string | undefined).queries;\n for (const queryName of Object.keys(queries).sort()) {\n // Every entry names its verb, so --list can label both kinds rather than only\n // marking the exception.\n console.log(`${queryName} (${'search' in queries[queryName] ? 'search' : 'sql'})`);\n }\n return;\n }\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n\n console.error(usage(name));\n process.exit(2);\n }\n\n // Breaking renames get one release of a pointer instead of an \"unknown\" error: find ->\n // search, and query -> sql (which took its name back from the search sense of \"query\").\n const RENAMED: Record<string, string> = { find: 'search', query: 'sql' };\n if (RENAMED[first]) {\n console.error(`${name}: ${first} is now ${RENAMED[first]}`);\n console.error(usage(name));\n process.exit(2);\n }\n\n const ctx: Ctx = {\n name,\n argv: argv.slice(1),\n resolveConfig: (configPath) => resolveConfigFor(name, configPath),\n usageError(message) {\n console.error(message);\n process.exit(2);\n },\n };\n\n try {\n const load = COMMANDS[first];\n if (load) await (await load()).default(ctx);\n else await (await import('./cli/named.ts')).default(ctx, first);\n } catch (err) {\n console.error((err as Error).message);\n process.exit(1);\n }\n}\n"],"names":["cli","packageVersion","load","createRequire","rel","pkg","name","version","usage","lines","Object","values","USAGE","map","u","join","resolveConfigFor","configPath","cfg","loadConfig","migratedFrom","undefined","console","warn","SUPPORTED_CONFIG_VERSION","unknownKeys","argv","first","queries","queryName","RENAMED","ctx","err","process","stdout","on","code","error","message","exitCode","startsWith","parseArgs","args","options","type","default","short","help","list","config","allowPositionals","exit","log","keys","sort","find","query","slice","resolveConfig","usageError","COMMANDS"],"mappings":"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"}
@@ -228,9 +228,7 @@ function mapTree(_0, _1) {
228
228
  return !_scopets.INTERNAL_COLUMNS.has(name);
229
229
  });
230
230
  // Observed types, not declared: a field can be text in most notes and numeric in a few, so
231
- // every distinct type observed across the scope is reported, not just the first. Aggregated
232
- // in SQL, one query per chunk of columns (native-not-emulated: each store's fieldStats()
233
- // classifies through its own engine mechanism but returns the same vocabulary).
231
+ // every distinct type observed across the scope is reported, not just the first.
234
232
  allFields = [];
235
233
  _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
236
234
  _state.label = 6;
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/map.ts"],"sourcesContent":["import type { FeatureName, ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { featureEnabled, featureStates } from '../config/index.ts';\nimport type { Row } from '../output/output.ts';\nimport type { FieldStat, Store } from '../store/types.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 per\n// field keeps a chunk's row width safely under that regardless of how many fields the tree has.\nconst MAP_COLUMN_CHUNK = 300;\n\n// \"YYYY-MM-DD HH:MM:SS\" UTC, the exact shape sqlite's datetime(ms / 1000, 'unixepoch') prints;\n// formatted in JS so the query stays dialect-free.\nfunction utcSecond(ms: number): string {\n return new Date(ms).toISOString().slice(0, 19).replace('T', ' ');\n}\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 async function mapTree(store: Store, cfg: ResolvedConfig, overrides: SearchOverrides = {}): Promise<TreeMap> {\n return store.transaction(async () => {\n await setupMapScope(store, await scopedPaths(store, 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 = (await (await store.prepare(`SELECT COUNT(*) AS count, COALESCE(SUM(\"_size\"), 0) AS bytes FROM frontmatter ${scopeWhere}`)).get()) as { count: number; bytes: number };\n\n const columns = (await store.docs.columns()).filter((name) => !INTERNAL_COLUMNS.has(name));\n // Observed types, not declared: a field can be text in most notes and numeric in a few, so\n // every distinct type observed across the scope is reported, not just the first. Aggregated\n // in SQL, one query per chunk of columns (native-not-emulated: each store's fieldStats()\n // classifies through its own engine mechanism but returns the same vocabulary).\n const allFields: FieldStat[] = [];\n for (const group of chunk(columns, MAP_COLUMN_CHUNK)) allFields.push(...(await store.docs.fieldStats(group, scopeWhere)));\n allFields.sort((a, b) => b.coverage - a.coverage);\n const fields = allFields.slice(0, 20) as unknown as Row[];\n\n const hubs = featureEnabled(cfg, 'rank') ? ((await (await store.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 = ((await (await store.prepare(`SELECT \"path\", \"_mtime\" AS mtime FROM frontmatter ${scopeWhere} ORDER BY \"_mtime\" DESC LIMIT 5`)).all()) as Array<{ path: string; mtime: number }>).map((r) => ({ path: r.path, modified: utcSecond(r.mtime) }));\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 = (await (await store.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: await presetCoverage(store, cfg), hubs, recent, recentCaveat };\n });\n}\n"],"names":["mapTree","MAP_COLUMN_CHUNK","utcSecond","ms","Date","toISOString","slice","replace","chunk","items","size","out","i","length","push","store","cfg","overrides","transaction","allFields","scopeWhere","scopeAnd","docs","columns","group","fields","hubs","recent","topSecond","recentCaveat","scopedPaths","setupMapScope","prepare","get","filter","name","INTERNAL_COLUMNS","has","fieldStats","sort","a","b","coverage","featureEnabled","all","map","r","path","modified","mtime","count","n","fieldsTotal","features","featureStates","presetCoverage","presets"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/map.ts"],"sourcesContent":["import type { FeatureName, ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { featureEnabled, featureStates } from '../config/index.ts';\nimport type { Row } from '../output/output.ts';\nimport type { FieldStat, Store } from '../store/types.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 per\n// field keeps a chunk's row width safely under that regardless of how many fields the tree has.\nconst MAP_COLUMN_CHUNK = 300;\n\n// \"YYYY-MM-DD HH:MM:SS\" UTC, the exact shape sqlite's datetime(ms / 1000, 'unixepoch') prints;\n// formatted in JS so the query stays dialect-free.\nfunction utcSecond(ms: number): string {\n return new Date(ms).toISOString().slice(0, 19).replace('T', ' ');\n}\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 async function mapTree(store: Store, cfg: ResolvedConfig, overrides: SearchOverrides = {}): Promise<TreeMap> {\n return store.transaction(async () => {\n await setupMapScope(store, await scopedPaths(store, 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 = (await (await store.prepare(`SELECT COUNT(*) AS count, COALESCE(SUM(\"_size\"), 0) AS bytes FROM frontmatter ${scopeWhere}`)).get()) as { count: number; bytes: number };\n\n const columns = (await store.docs.columns()).filter((name) => !INTERNAL_COLUMNS.has(name));\n // Observed types, not declared: a field can be text in most notes and numeric in a few, so\n // every distinct type observed across the scope is reported, not just the first.\n const allFields: FieldStat[] = [];\n for (const group of chunk(columns, MAP_COLUMN_CHUNK)) allFields.push(...(await store.docs.fieldStats(group, scopeWhere)));\n allFields.sort((a, b) => b.coverage - a.coverage);\n const fields = allFields.slice(0, 20) as unknown as Row[];\n\n const hubs = featureEnabled(cfg, 'rank') ? ((await (await store.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 = ((await (await store.prepare(`SELECT \"path\", \"_mtime\" AS mtime FROM frontmatter ${scopeWhere} ORDER BY \"_mtime\" DESC LIMIT 5`)).all()) as Array<{ path: string; mtime: number }>).map((r) => ({ path: r.path, modified: utcSecond(r.mtime) }));\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 = (await (await store.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: await presetCoverage(store, cfg), hubs, recent, recentCaveat };\n });\n}\n"],"names":["mapTree","MAP_COLUMN_CHUNK","utcSecond","ms","Date","toISOString","slice","replace","chunk","items","size","out","i","length","push","store","cfg","overrides","transaction","allFields","scopeWhere","scopeAnd","docs","columns","group","fields","hubs","recent","topSecond","recentCaveat","scopedPaths","setupMapScope","prepare","get","filter","name","INTERNAL_COLUMNS","has","fieldStats","sort","a","b","coverage","featureEnabled","all","map","r","path","modified","mtime","count","n","fieldsTotal","features","featureStates","presetCoverage","presets"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/peek.ts"],"sourcesContent":["import posix from 'node:path/posix';\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 type { Store } from '../store/types.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 async function peek(store: Store, cfg: ResolvedConfig, pathArg: string, overrides: SearchOverrides = {}): Promise<Peek> {\n return store.transaction(async () => {\n const pathsStmt = await store.prepare('SELECT \"path\" FROM frontmatter');\n const paths = ((await pathsStmt.all()) as Array<{ path: string }>).map((r) => r.path);\n const path = resolveNote(paths, pathArg);\n\n const rowStmt = await store.prepare('SELECT * FROM frontmatter WHERE \"path\" = ?');\n const row = (await rowStmt.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 let sectionsTotal = 0;\n let sections: Row[] = [];\n if (featureEnabled(cfg, 'sections')) {\n sectionsTotal = ((await (await store.prepare('SELECT COUNT(*) AS n FROM sections WHERE \"path\" = ?')).get(path)) as { n: number }).n;\n sections = (await (await store.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\n let outbound: string[] = [];\n let backlinks: string[] = [];\n let unresolved: string[] = [];\n let backlinksTotal = 0;\n await scopedPaths(store, cfg, overrides); // validates --preset/--where/--include/--exclude even though peek's own output isn't scope-filtered\n if (featureEnabled(cfg, 'links')) {\n const out = (await (await store.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 = ((await (await store.prepare('SELECT COUNT(DISTINCT src) AS n FROM links WHERE dst = ? AND src != dst')).get(path)) as { n: number }).n;\n backlinks = ((await (await store.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 = ((await (await store.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}\n"],"names":["peek","resolveNote","paths","arg","exact","find","p","base","posix","basename","replace","toLowerCase","matches","filter","length","SenseError","join","PEEK_LIST_LIMIT","store","cfg","pathArg","overrides","transaction","row","pathsStmt","path","rowStmt","parseError","frontmatter","key","value","sectionsTotal","sections","outbound","backlinks","unresolved","backlinksTotal","out","body","byteTokens","tokens","prepare","all","map","r","get","_parse_error","Object","entries","INTERNAL_COLUMNS","has","featureEnabled","n","scopedPaths","Set","l","dst","target","src","text","Math","ceil","_size","undefined","max","estimateTokens","slice","outboundTotal","unresolvedTotal","off","name"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/peek.ts"],"sourcesContent":["import posix from 'node:path/posix';\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 type { Store } from '../store/types.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.\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 async function peek(store: Store, cfg: ResolvedConfig, pathArg: string, overrides: SearchOverrides = {}): Promise<Peek> {\n return store.transaction(async () => {\n const pathsStmt = await store.prepare('SELECT \"path\" FROM frontmatter');\n const paths = ((await pathsStmt.all()) as Array<{ path: string }>).map((r) => r.path);\n const path = resolveNote(paths, pathArg);\n\n const rowStmt = await store.prepare('SELECT * FROM frontmatter WHERE \"path\" = ?');\n const row = (await rowStmt.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 let sectionsTotal = 0;\n let sections: Row[] = [];\n if (featureEnabled(cfg, 'sections')) {\n sectionsTotal = ((await (await store.prepare('SELECT COUNT(*) AS n FROM sections WHERE \"path\" = ?')).get(path)) as { n: number }).n;\n sections = (await (await store.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\n let outbound: string[] = [];\n let backlinks: string[] = [];\n let unresolved: string[] = [];\n let backlinksTotal = 0;\n await scopedPaths(store, cfg, overrides); // validates --preset/--where/--include/--exclude even though peek's own output isn't scope-filtered\n if (featureEnabled(cfg, 'links')) {\n const out = (await (await store.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 = ((await (await store.prepare('SELECT COUNT(DISTINCT src) AS n FROM links WHERE dst = ? AND src != dst')).get(path)) as { n: number }).n;\n backlinks = ((await (await store.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 = ((await (await store.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}\n"],"names":["peek","resolveNote","paths","arg","exact","find","p","base","posix","basename","replace","toLowerCase","matches","filter","length","SenseError","join","PEEK_LIST_LIMIT","store","cfg","pathArg","overrides","transaction","row","pathsStmt","path","rowStmt","parseError","frontmatter","key","value","sectionsTotal","sections","outbound","backlinks","unresolved","backlinksTotal","out","body","byteTokens","tokens","prepare","all","map","r","get","_parse_error","Object","entries","INTERNAL_COLUMNS","has","featureEnabled","n","scopedPaths","Set","l","dst","target","src","text","Math","ceil","_size","undefined","max","estimateTokens","slice","outboundTotal","unresolvedTotal","off","name"],"mappings":"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"}
@@ -216,15 +216,13 @@ function relatedNotes(store, cfg, pathArg, overrides, k) {
216
216
  path
217
217
  ].concat(_to_consumable_array(outbound), _to_consumable_array(backlinks)));
218
218
  // Vectors are the only signal `related` has, so every way of not having them is an error
219
- // naming the cause. An empty table then means one thing: nothing near in meaning that this
220
- // note does not already link to, which is a real answer.
219
+ // naming the cause; an empty result means one thing, nothing near in meaning.
221
220
  effective = (0, _indexts.resolveSearch)(cfg, overrides);
222
221
  if (!(0, _indexts.embedEnabled)(cfg)) {
223
222
  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');
224
223
  }
225
- // search gates on the same signal (see wantsVectors above); reading it here too keeps a
226
- // preset's declared signals meaning one thing. Without this, an overlapping vectors-on
227
- // preset's vectors would answer for a scope that declined them.
224
+ // search gates on the same signal, so a preset's declared signals mean one thing: without
225
+ // this check an overlapping vectors-on preset would answer for a scope that declined them.
228
226
  if (effective.signals.vectors === undefined) {
229
227
  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'));
230
228
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/related.ts"],"sourcesContent":["import 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 type { Store } from '../store/types.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(store: Store, cfg: ResolvedConfig, pathArg: string, overrides: SearchOverrides, k: number): Promise<Array<{ path: string; similarity: number }>> {\n const paths = ((await (await store.prepare('SELECT \"path\" FROM frontmatter')).all()) as Array<{ path: string }>).map((r) => r.path);\n const path = resolveNote(paths, pathArg);\n\n const outbound = ((await (await store.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 = ((await (await store.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 = await scopedPaths(store, 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(store, cfg, cfg.baseDir);\n if (!(await hasEmbedding(store, 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 (!(await scopeHasEmbeddings(store, cfg, allowed))) return [];\n return similarNotes(store, cfg, path, { exclude, allowed, k });\n}\n"],"names":["relatedNotes","store","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;;;uBAVmC;uBACA;uBACN;wBACxB;sBAEC;uBACoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIzC,SAAeA,aAAaC,KAAY,EAAEC,GAAmB,EAAEC,OAAe,EAAEC,SAA0B,EAAEC,CAAS;;YACpHC,OACAC,MAEAC,UACAC,WACAC,SAKAC,WAYAC,GAIAC;;;;oBA1BiB;;wBAAMZ,MAAMa,OAAO,CAAC;;;oBAA3B;;wBAAO,cAAuDC,GAAG;;;oBAA3ET,QAAQ,AAAE,cAAiGU,GAAG,CAAC,SAACC;+BAAMA,EAAEV,IAAI;;oBAC5HA,OAAOW,IAAAA,mBAAW,EAACZ,OAAOH;oBAEN;;wBAAMF,MAAMa,OAAO,CAAC;;;oBAA3B;;wBAAO,cAAwGC,GAAG,CAACR;;;oBAAhIC,WAAW,AAAE,cAAqJQ,GAAG,CAAC,SAACC;+BAAMA,EAAEE,GAAG;;oBAC7J;;wBAAMlB,MAAMa,OAAO,CAAC;;;oBAA3B;;wBAAO,cAAoFC,GAAG,CAACR;;;oBAA7GE,YAAY,AAAE,cAAiIO,GAAG,CAAC,SAACC;+BAAMA,EAAEG,GAAG;;oBAC/JV,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;oBACgB;;wBAAME,IAAAA,oBAAW,EAAChC,OAAOC,KAAKE;;;oBAAxCS,UAAU;oBAChB,oFAAoF;oBACpF,oDAAoD;oBACpD;;wBAAMqB,IAAAA,qBAAY,EAACjC,OAAOC,KAAKA,IAAIiC,OAAO;;;oBAA1C;oBACM;;wBAAMC,IAAAA,qBAAY,EAACnC,OAAOM;;;oBAAhC,IAAI,CAAE,eAAkC;wBACtC,MAAM,IAAIiB,oBAAU,CAAC,qBAAqB,AAAC,GAAO,OAALjB,MAAK;oBACpD;oBACM;;wBAAM8B,IAAAA,2BAAkB,EAACpC,OAAOC,KAAKW;;;oBAA3C,IAAI,CAAE,eAAgD;;;;oBACtD;;wBAAOyB,IAAAA,qBAAY,EAACrC,OAAOC,KAAKK,MAAM;4BAAEG,SAAAA;4BAASG,SAAAA;4BAASR,GAAAA;wBAAE;;;;IAC9D"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/related.ts"],"sourcesContent":["import 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 type { Store } from '../store/types.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(store: Store, cfg: ResolvedConfig, pathArg: string, overrides: SearchOverrides, k: number): Promise<Array<{ path: string; similarity: number }>> {\n const paths = ((await (await store.prepare('SELECT \"path\" FROM frontmatter')).all()) as Array<{ path: string }>).map((r) => r.path);\n const path = resolveNote(paths, pathArg);\n\n const outbound = ((await (await store.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 = ((await (await store.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 result means one thing, nothing near in meaning.\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, so a preset's declared signals mean one thing: without\n // this check an overlapping vectors-on preset 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 = await scopedPaths(store, 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(store, cfg, cfg.baseDir);\n if (!(await hasEmbedding(store, 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 (!(await scopeHasEmbeddings(store, cfg, allowed))) return [];\n return similarNotes(store, cfg, path, { exclude, allowed, k });\n}\n"],"names":["relatedNotes","store","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;;;uBAVmC;uBACA;uBACN;wBACxB;sBAEC;uBACoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIzC,SAAeA,aAAaC,KAAY,EAAEC,GAAmB,EAAEC,OAAe,EAAEC,SAA0B,EAAEC,CAAS;;YACpHC,OACAC,MAEAC,UACAC,WACAC,SAIAC,WAWAC,GAIAC;;;;oBAxBiB;;wBAAMZ,MAAMa,OAAO,CAAC;;;oBAA3B;;wBAAO,cAAuDC,GAAG;;;oBAA3ET,QAAQ,AAAE,cAAiGU,GAAG,CAAC,SAACC;+BAAMA,EAAEV,IAAI;;oBAC5HA,OAAOW,IAAAA,mBAAW,EAACZ,OAAOH;oBAEN;;wBAAMF,MAAMa,OAAO,CAAC;;;oBAA3B;;wBAAO,cAAwGC,GAAG,CAACR;;;oBAAhIC,WAAW,AAAE,cAAqJQ,GAAG,CAAC,SAACC;+BAAMA,EAAEE,GAAG;;oBAC7J;;wBAAMlB,MAAMa,OAAO,CAAC;;;oBAA3B;;wBAAO,cAAoFC,GAAG,CAACR;;;oBAA7GE,YAAY,AAAE,cAAiIO,GAAG,CAAC,SAACC;+BAAMA,EAAEG,GAAG;;oBAC/JV,UAAU,IAAIW,IAAI;wBAACd;sBAAD,OAAO,qBAAGC,WAAU,qBAAGC;oBAE/C,yFAAyF;oBACzF,8EAA8E;oBACxEE,YAAYW,IAAAA,sBAAa,EAACpB,KAAKE;oBACrC,IAAI,CAACmB,IAAAA,qBAAY,EAACrB,MAAM;wBACtB,MAAM,IAAIsB,oBAAU,CAAC,kBAAkB;oBACzC;oBACA,0FAA0F;oBAC1F,2FAA2F;oBAC3F,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;oBACgB;;wBAAME,IAAAA,oBAAW,EAAChC,OAAOC,KAAKE;;;oBAAxCS,UAAU;oBAChB,oFAAoF;oBACpF,oDAAoD;oBACpD;;wBAAMqB,IAAAA,qBAAY,EAACjC,OAAOC,KAAKA,IAAIiC,OAAO;;;oBAA1C;oBACM;;wBAAMC,IAAAA,qBAAY,EAACnC,OAAOM;;;oBAAhC,IAAI,CAAE,eAAkC;wBACtC,MAAM,IAAIiB,oBAAU,CAAC,qBAAqB,AAAC,GAAO,OAALjB,MAAK;oBACpD;oBACM;;wBAAM8B,IAAAA,2BAAkB,EAACpC,OAAOC,KAAKW;;;oBAA3C,IAAI,CAAE,eAAgD;;;;oBACtD;;wBAAOyB,IAAAA,qBAAY,EAACrC,OAAOC,KAAKK,MAAM;4BAAEG,SAAAA;4BAASG,SAAAA;4BAASR,GAAAA;wBAAE;;;;IAC9D"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/scope.ts"],"sourcesContent":["import { matchesGlob } from 'node:path';\nimport type { ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { anyPresetEmbeds, resolveSearch } from '../config/index.ts';\nimport { columnHint } from '../output/column-hint.ts';\nimport type { Store } from '../store/types.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 async function scopeHasEmbeddings(store: Store, cfg: ResolvedConfig, scopedPaths: Set<string>): Promise<boolean> {\n if (!anyPresetEmbeds(cfg)) return false; // the embeddings table doesn't exist at all in this case\n const stmt = await store.prepare('SELECT DISTINCT \"path\" FROM embeddings');\n const rows = (await stmt.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 async function rawScope(store: Store, cfg: ResolvedConfig, overrides: SearchOverrides, allPaths?: string[]): Promise<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) {\n const stmt = await store.prepare('SELECT \"path\" FROM preset_files WHERE preset = ?');\n return new Set(((await stmt.all(effective.presetName)) as Array<{ path: string }>).map((r) => r.path));\n }\n const paths = allPaths ?? (await allFrontmatterPaths(store));\n return new Set(paths.filter((p) => inScope(p, include, exclude)));\n}\n\nasync function allFrontmatterPaths(store: Store): Promise<string[]> {\n const stmt = await store.prepare('SELECT \"path\" FROM frontmatter');\n return ((await stmt.all()) as Array<{ path: string }>).map((r) => r.path);\n}\n\nexport async function narrowByWhere(store: Store, paths: Set<string>, where: string | undefined): Promise<Set<string>> {\n if (!where) return paths;\n let whereRows: Array<{ path: string }>;\n try {\n const stmt = await store.prepare(`SELECT \"path\" FROM frontmatter f WHERE (${where})`);\n whereRows = (await stmt.all()) as Array<{ path: string }>;\n } catch (err) {\n throw columnHint(await store.docs.columns(), 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 async function scopedPaths(store: Store, cfg: ResolvedConfig, overrides: SearchOverrides): Promise<Set<string>> {\n const effective = resolveSearch(cfg, overrides);\n return narrowByWhere(store, await rawScope(store, 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 async function materializeScope(store: Store, table: string, paths: Set<string>): Promise<void> {\n await store.exec(`DROP TABLE IF EXISTS ${table}`);\n await store.exec(`CREATE TEMP TABLE ${table} (\"path\" TEXT PRIMARY KEY)`);\n await store.runBatch(\n `INSERT INTO ${table} (\"path\") VALUES (?)`,\n [...paths].map((p) => [p])\n );\n}\n\nexport async function setupMapScope(store: Store, paths: Set<string>): Promise<void> {\n await materializeScope(store, '_map_scope', paths);\n}\n"],"names":["INTERNAL_COLUMNS","inScope","materializeScope","narrowByWhere","rawScope","scopeHasEmbeddings","scopedPaths","setupMapScope","Set","path","include","exclude","some","g","matchesGlob","store","cfg","stmt","rows","anyPresetEmbeds","prepare","all","r","has","overrides","allPaths","effective","adHocScope","paths","resolveSearch","undefined","noExclude","presetName","map","allFrontmatterPaths","filter","p","where","whereRows","err","wherePaths","docs","columns","columnHint","table","exec","runBatch"],"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 { ResolvedConfig, SearchOverrides } from '../config/index.ts';\nimport { anyPresetEmbeds, resolveSearch } from '../config/index.ts';\nimport { columnHint } from '../output/column-hint.ts';\nimport type { Store } from '../store/types.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) at the\n// Node >=22.20 engines floor; used here in JS rather than 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 async function scopeHasEmbeddings(store: Store, cfg: ResolvedConfig, scopedPaths: Set<string>): Promise<boolean> {\n if (!anyPresetEmbeds(cfg)) return false; // the embeddings table doesn't exist at all in this case\n const stmt = await store.prepare('SELECT DISTINCT \"path\" FROM embeddings');\n const rows = (await stmt.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()'s candidate-pool sizing.\nexport async function rawScope(store: Store, cfg: ResolvedConfig, overrides: SearchOverrides, allPaths?: string[]): Promise<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) {\n const stmt = await store.prepare('SELECT \"path\" FROM preset_files WHERE preset = ?');\n return new Set(((await stmt.all(effective.presetName)) as Array<{ path: string }>).map((r) => r.path));\n }\n const paths = allPaths ?? (await allFrontmatterPaths(store));\n return new Set(paths.filter((p) => inScope(p, include, exclude)));\n}\n\nasync function allFrontmatterPaths(store: Store): Promise<string[]> {\n const stmt = await store.prepare('SELECT \"path\" FROM frontmatter');\n return ((await stmt.all()) as Array<{ path: string }>).map((r) => r.path);\n}\n\nexport async function narrowByWhere(store: Store, paths: Set<string>, where: string | undefined): Promise<Set<string>> {\n if (!where) return paths;\n let whereRows: Array<{ path: string }>;\n try {\n const stmt = await store.prepare(`SELECT \"path\" FROM frontmatter f WHERE (${where})`);\n whereRows = (await stmt.all()) as Array<{ path: string }>;\n } catch (err) {\n throw columnHint(await store.docs.columns(), 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 async function scopedPaths(store: Store, cfg: ResolvedConfig, overrides: SearchOverrides): Promise<Set<string>> {\n const effective = resolveSearch(cfg, overrides);\n return narrowByWhere(store, await rawScope(store, 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 async function materializeScope(store: Store, table: string, paths: Set<string>): Promise<void> {\n await store.exec(`DROP TABLE IF EXISTS ${table}`);\n await store.exec(`CREATE TEMP TABLE ${table} (\"path\" TEXT PRIMARY KEY)`);\n await store.runBatch(\n `INSERT INTO ${table} (\"path\") VALUES (?)`,\n [...paths].map((p) => [p])\n );\n}\n\nexport async function setupMapScope(store: Store, paths: Set<string>): Promise<void> {\n await materializeScope(store, '_map_scope', paths);\n}\n"],"names":["INTERNAL_COLUMNS","inScope","materializeScope","narrowByWhere","rawScope","scopeHasEmbeddings","scopedPaths","setupMapScope","Set","path","include","exclude","some","g","matchesGlob","store","cfg","stmt","rows","anyPresetEmbeds","prepare","all","r","has","overrides","allPaths","effective","adHocScope","paths","resolveSearch","undefined","noExclude","presetName","map","allFrontmatterPaths","filter","p","where","whereRows","err","wherePaths","docs","columns","columnHint","table","exec","runBatch"],"mappings":"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"}
@@ -282,9 +282,8 @@ function bestWindowStart(occ, windowSize) {
282
282
  function computeExcerpt(text, terms) {
283
283
  var occ = findOccurrences(text.toLowerCase(), terms);
284
284
  if (occ.length === 0) {
285
- // This is a raw substring scan, not porter-stemmed: a doc matched only through a
286
- // stemmed variant (query "negotiate" vs doc "negotiating") finds no occurrence here.
287
- // Fall back to the doc's start, unmarked, rather than claim a match that isn't there.
285
+ // Raw substring scan, not porter-stemmed: a doc matched only through a stemmed variant
286
+ // finds no occurrence here, so fall back to the doc's start, unmarked.
288
287
  var end = Math.min(text.length, EXCERPT_WINDOW);
289
288
  return {
290
289
  excerpt: "".concat(text.slice(0, end).replace(/\s+/g, ' ').trim()).concat(end < text.length ? '…' : ''),
@@ -557,12 +556,11 @@ function search(_0, _1, _2) {
557
556
  _state.sent();
558
557
  _state.label = 23;
559
558
  case 23:
560
- // All three candidate paths (match, link, vector) already filtered to scope+where before
561
- // reaching _search; this reapplies --where anyway since the join to frontmatter is already
562
- // needed for the path column.
559
+ // Reapplies --where even though _search is already scope+where filtered, since the join to
560
+ // frontmatter is already needed for the path column.
563
561
  where = scope ? "WHERE (".concat(scope, ")") : '';
564
- // lines is always present now: semantic rows carry their chunk's range, oversized-doc
565
- // lexical rows gain one below, everything else stays null. similarity stays semantic-only.
562
+ // lines: semantic rows carry their chunk's range, oversized-doc lexical rows gain one
563
+ // below, everything else stays null; similarity stays semantic-only.
566
564
  similarityCol = semanticEnabled ? ', _search.similarity' : '';
567
565
  return [
568
566
  4,
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/search.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { ResolvedConfig } from '../config/index.ts';\nimport { embedConfig, featureEnabled, resolveSearch } from '../config/index.ts';\nimport { localModelMissing, MODEL_FILENAMES } from '../embed/store.ts';\nimport { SenseError } from '../errors.ts';\nimport type { Row } from '../output/output.ts';\nimport { searchError } from '../output/search-error.ts';\nimport type { LexicalHit, Store } from '../store/types.ts';\nimport { materializeScope, narrowByWhere, rawScope, scopeHasEmbeddings } from './scope.ts';\nimport { linksCandidates, vectorsCandidates, wordsCandidates } from './signals.ts';\n\n// snippet() re-tokenizes each candidate doc, superlinearly: ~10s for one 1MB doc\n// (benchmark/reports/2026-08-23-hub-release-battery.md). Past this bound, rows get the JS excerpt.\nconst EXCERPT_WINDOW = 160;\n\n// Bare terms from an FTS5 query string: strips operators/quoting so the oversized-doc excerpt\n// scan matches the same words the query matched on, not FTS5 syntax.\nfunction extractBareTerms(query: string): string[] {\n const cleaned = query\n .replace(/\"/g, ' ')\n .replace(/[()*]/g, ' ')\n .replace(/\\b(AND|OR|NOT|NEAR)\\b(\\/\\d+)?/gi, ' ');\n return cleaned\n .split(/\\s+/)\n .map((tok) => tok.replace(/^[A-Za-z_]\\w*:/, '')) // column filter, e.g. title:term\n .map((tok) => tok.toLowerCase().trim())\n .filter((tok) => tok.length > 0);\n}\n\nfunction findOccurrences(haystackLower: string, terms: string[]): Array<{ start: number; end: number; term: string }> {\n const occ: Array<{ start: number; end: number; term: string }> = [];\n for (const term of terms) {\n let idx = 0;\n for (;;) {\n const found = haystackLower.indexOf(term, idx);\n if (found === -1) break;\n occ.push({ start: found, end: found + term.length, term });\n idx = found + term.length;\n }\n }\n // Longest span first at equal start, so \"tests\" beats its substring \"test\" and the\n // whole word gets highlighted; the emit loop then absorbs the shorter overlap.\n return occ.sort((a, b) => a.start - b.start || b.end - a.end);\n}\n\n// Slides a window over the sorted occurrences, same semantics as FTS5's own best-window\n// pick: most distinct terms, ties broken by most total hits.\nfunction bestWindowStart(occ: Array<{ start: number; end: number; term: string }>, windowSize: number): number {\n let best = occ[0].start;\n let bestDistinct = 0;\n let bestCount = 0;\n for (let i = 0; i < occ.length; i++) {\n const winEnd = occ[i].start + windowSize;\n const seen = new Set<string>();\n let count = 0;\n for (let j = i; j < occ.length && occ[j].start < winEnd; j++) {\n seen.add(occ[j].term);\n count++;\n }\n if (seen.size > bestDistinct || (seen.size === bestDistinct && count > bestCount)) {\n best = occ[i].start;\n bestDistinct = seen.size;\n bestCount = count;\n }\n }\n return best;\n}\n\n// snippet()-shaped excerpt: matched terms wrapped in «», … at cut edges. Linear in doc\n// length, only run for rows actually returned (<= k), unlike snippet()'s per-row cost.\nfunction computeExcerpt(text: string, terms: string[]): { excerpt: string; offset: number } {\n const occ = findOccurrences(text.toLowerCase(), terms);\n if (occ.length === 0) {\n // This is a raw substring scan, not porter-stemmed: a doc matched only through a\n // stemmed variant (query \"negotiate\" vs doc \"negotiating\") finds no occurrence here.\n // Fall back to the doc's start, unmarked, rather than claim a match that isn't there.\n const end = Math.min(text.length, EXCERPT_WINDOW);\n return { excerpt: `${text.slice(0, end).replace(/\\s+/g, ' ').trim()}${end < text.length ? '…' : ''}`, offset: 0 };\n }\n const start = bestWindowStart(occ, EXCERPT_WINDOW);\n const end = Math.min(text.length, start + EXCERPT_WINDOW);\n let out = '';\n let cursor = start;\n for (const o of occ) {\n if (o.start < start || o.end > end) continue;\n // Occurrences of duplicate or substring-overlapping terms (\"test tests\") can overlap;\n // emitting each would duplicate document text. Keep the first, absorb the rest.\n if (o.start < cursor) continue;\n out += `${text.slice(cursor, o.start)}«${text.slice(o.start, o.end)}»`;\n cursor = o.end;\n }\n out += text.slice(cursor, end);\n const prefix = start > 0 ? '…' : '';\n const suffix = end < text.length ? '…' : '';\n return { excerpt: `${prefix}${out.replace(/\\s+/g, ' ')}${suffix}`, offset: start };\n}\n\nfunction lineNumberAt(text: string, offset: number): number {\n let line = 1;\n for (let i = 0; i < offset; i++) if (text.charCodeAt(i) === 10) line++;\n return line;\n}\n\nasync function lineRangeFor(store: Store, path: string, line: number): Promise<string | null> {\n const stmt = await store.prepare('SELECT start_line, end_line FROM sections WHERE \"path\" = ? AND start_line <= ? AND end_line >= ? ORDER BY start_line DESC LIMIT 1');\n const row = (await stmt.get(path, line, line)) as { start_line: number; end_line: number } | undefined;\n return row ? `L${row.start_line}-${row.end_line}` : null;\n}\n\nexport interface SearchOptions {\n k?: number;\n where?: string; // SQL fragment against frontmatter alias `f`, e.g. \"f.status = 'active'\"\n preset?: string; // named preset; unknown name throws listing declared presets, undefined -> \"default\"\n include?: string[]; // ad hoc scope override (repeatable --include); independent of exclude\n exclude?: string[]; // ad hoc scope override (repeatable --exclude); independent of include\n noExclude?: boolean; // --no-exclude: drop the preset's exclude for this command\n}\n\n// The declared or defaulted signals compose via RRF; `via` names which ones produced each row.\n// `opts` arrives already resolved (config.ts:resolveSearch).\nexport async function search(store: Store, cfg: ResolvedConfig, terms: string, opts: SearchOptions = {}): Promise<Row[]> {\n const effective = resolveSearch(cfg, opts);\n const { k, signals } = effective;\n\n const allPaths = ((await (await store.prepare('SELECT \"path\" FROM frontmatter')).all()) as Array<{ path: string }>).map((r) => r.path);\n const scopePaths = await rawScope(store, cfg, opts, allPaths);\n const scopeActive = scopePaths.size < allPaths.length;\n // The set every candidate pool must be filtered to before truncation: scope narrowed by\n // --where, the same composition scopedPaths() gives the other commands. Runs the same where\n // fragment matchSql does, so a bad column gets the same attributed error either way.\n let allowedPaths: Set<string>;\n try {\n allowedPaths = await narrowByWhere(store, scopePaths, effective.where);\n } catch (err) {\n throw searchError(err as Error, terms, effective.where);\n }\n const fetch = Math.max(k * 3, 30);\n\n // A downloadable HF id proceeds -- getProvider fetches it lazily on consent. Only a\n // local path with missing files errors here, since nothing will ever fetch it for itself.\n const wantsVectors = signals.vectors !== undefined;\n if (wantsVectors) {\n const e = embedConfig(cfg); // validate.ts guarantees this is set whenever \"vectors\" is declared\n if (localModelMissing(e)) {\n throw new SenseError('EMBED_MODEL_MISSING', `preset \"${effective.presetName}\" searches with vectors, but the local model path \"${e.model}\" is missing ${MODEL_FILENAMES}; point embed.model at a directory containing them, or drop \"vectors\" from that preset's signals to search without them`);\n }\n }\n const semanticEnabled = wantsVectors && (await scopeHasEmbeddings(store, cfg, allowedPaths));\n\n // --where applies inside the candidate query (a post-filter would drop matches ranked past\n // the pool) and again on the final select, for link-derived rows.\n const scope = effective.where;\n const whereJoin = scope ? `JOIN frontmatter f ON f.\"path\" = content.path` : '';\n const whereCond = scope ? `AND (${scope})` : '';\n // A scope narrower than the whole index must filter the candidate pool before LIMIT, not\n // after -- otherwise scoped notes ranking below the global top-`fetch` never reach the\n // filter. A join against a temp table, not a bound parameter list: real scopes run to\n // thousands of paths, past SQLITE_MAX_VARIABLE_NUMBER on older builds.\n if (scopeActive) await materializeScope(store, '_search_scope', scopePaths);\n const scopeCond = scopeActive ? `AND content.path IN (SELECT \"path\" FROM _search_scope)` : '';\n\n const candidates = new Map<string, { score: number; via: string }>();\n let matchRows: LexicalHit[] = [];\n // A query that is only whitespace has no searchable words: zero lexical rows, and the other\n // signals still compose. Any store-specific rewrite of `terms` (sqlite's grapheme phrase for\n // unspaced scripts, duckdb's word/substring split) happens inside store.lexical.query itself.\n if (signals.words !== undefined && terms.trim() !== '') {\n try {\n matchRows = await wordsCandidates(store, candidates, terms, whereJoin, whereCond, scopeCond, fetch, signals.words);\n } catch (err) {\n throw searchError(err as Error, terms, scope);\n }\n }\n const hits = new Map(matchRows.map((r) => [r.path, r.hit]));\n // hit === null here means the bound suppressed snippet(), not \"no match\" -- distinguish\n // from via='link' rows (never in matchRows, so absent from this set) below.\n const oversized = new Set(matchRows.filter((r) => r.hit === null).map((r) => r.path));\n\n if (signals.links !== undefined) await linksCandidates(store, candidates, matchRows, allPaths, allowedPaths, fetch, signals.links);\n\n let chunkLines = new Map<string, string>();\n let chunkSimilarity = new Map<string, number>();\n if (semanticEnabled) {\n ({ chunkLines, chunkSimilarity } = await vectorsCandidates(store, cfg, candidates, terms, fetch, allowedPaths, signals.vectors as number));\n }\n\n await store.exec('DROP TABLE IF EXISTS _search');\n // DOUBLE, not REAL: sqlite's REAL is an 8-byte double but duckdb's is a 4-byte float, and the\n // rounded score/similarity are printed at full precision in rows.\n await store.exec('CREATE TEMP TABLE _search (\"path\" TEXT PRIMARY KEY, score DOUBLE, via TEXT, hit TEXT, lines TEXT, similarity DOUBLE)');\n if (candidates.size > 0) {\n await store.runBatch(\n 'INSERT INTO _search (\"path\", score, via, hit, lines, similarity) VALUES (?, ?, ?, ?, ?, ?)',\n [...candidates].map(([path, c]) => [path, c.score, c.via, hits.get(path) ?? null, chunkLines.get(path) ?? null, chunkSimilarity.get(path) ?? null])\n );\n }\n\n // All three candidate paths (match, link, vector) already filtered to scope+where before\n // reaching _search; this reapplies --where anyway since the join to frontmatter is already\n // needed for the path column.\n const where = scope ? `WHERE (${scope})` : '';\n // lines is always present now: semantic rows carry their chunk's range, oversized-doc\n // lexical rows gain one below, everything else stays null. similarity stays semantic-only.\n const similarityCol = semanticEnabled ? ', _search.similarity' : '';\n const selectStmt = await store.prepare(\n `SELECT f.\"path\" AS path, content.title, content.summary, _search.hit, _search.via, round(_search.score, 4) AS score, _search.lines${similarityCol}\n FROM _search JOIN frontmatter f ON f.\"path\" = _search.\"path\" JOIN content ON content.path = _search.\"path\"\n ${where} ORDER BY _search.score DESC LIMIT ?`\n );\n const rows = (await selectStmt.all(k)) as Row[];\n\n if (oversized.size > 0) {\n const bareTerms = extractBareTerms(terms);\n for (const row of rows) {\n if (row.hit !== null || !oversized.has(row.path as string)) continue;\n let text: string;\n try {\n text = readFileSync(join(cfg.baseDir, row.path as string), 'utf8');\n } catch {\n continue; // vanished since the match; leave hit/lines null rather than throw\n }\n const { excerpt, offset } = computeExcerpt(text, bareTerms);\n row.hit = excerpt;\n if (row.lines == null) row.lines = featureEnabled(cfg, 'sections') ? await lineRangeFor(store, row.path as string, lineNumberAt(text, offset)) : null;\n }\n }\n\n return rows;\n}\n"],"names":["search","EXCERPT_WINDOW","extractBareTerms","query","cleaned","replace","split","map","tok","toLowerCase","trim","filter","length","findOccurrences","haystackLower","terms","occ","term","idx","found","indexOf","push","start","end","sort","a","b","bestWindowStart","windowSize","best","bestDistinct","bestCount","i","winEnd","seen","Set","count","j","add","size","computeExcerpt","text","Math","min","excerpt","slice","offset","out","cursor","o","prefix","suffix","lineNumberAt","line","charCodeAt","lineRangeFor","store","path","stmt","row","prepare","get","start_line","end_line","cfg","opts","effective","k","signals","allPaths","scopePaths","scopeActive","allowedPaths","err","fetch","wantsVectors","e","semanticEnabled","scope","whereJoin","whereCond","scopeCond","candidates","matchRows","hits","oversized","chunkLines","chunkSimilarity","where","similarityCol","selectStmt","rows","bareTerms","resolveSearch","all","r","rawScope","narrowByWhere","searchError","max","vectors","undefined","embedConfig","localModelMissing","SenseError","presetName","MODEL_FILENAMES","model","scopeHasEmbeddings","materializeScope","Map","words","wordsCandidates","hit","links","linksCandidates","vectorsCandidates","exec","runBatch","c","score","via","has","readFileSync","join","baseDir","lines","featureEnabled"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/search.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { ResolvedConfig } from '../config/index.ts';\nimport { embedConfig, featureEnabled, resolveSearch } from '../config/index.ts';\nimport { localModelMissing, MODEL_FILENAMES } from '../embed/store.ts';\nimport { SenseError } from '../errors.ts';\nimport type { Row } from '../output/output.ts';\nimport { searchError } from '../output/search-error.ts';\nimport type { LexicalHit, Store } from '../store/types.ts';\nimport { materializeScope, narrowByWhere, rawScope, scopeHasEmbeddings } from './scope.ts';\nimport { linksCandidates, vectorsCandidates, wordsCandidates } from './signals.ts';\n\n// snippet() re-tokenizes each candidate doc, superlinearly: ~10s for one 1MB doc\n// (benchmark/reports/2026-08-23-hub-release-battery.md). Past this bound, rows get the JS excerpt.\nconst EXCERPT_WINDOW = 160;\n\n// Bare terms from an FTS5 query string: strips operators/quoting so the oversized-doc excerpt\n// scan matches the same words the query matched on, not FTS5 syntax.\nfunction extractBareTerms(query: string): string[] {\n const cleaned = query\n .replace(/\"/g, ' ')\n .replace(/[()*]/g, ' ')\n .replace(/\\b(AND|OR|NOT|NEAR)\\b(\\/\\d+)?/gi, ' ');\n return cleaned\n .split(/\\s+/)\n .map((tok) => tok.replace(/^[A-Za-z_]\\w*:/, '')) // column filter, e.g. title:term\n .map((tok) => tok.toLowerCase().trim())\n .filter((tok) => tok.length > 0);\n}\n\nfunction findOccurrences(haystackLower: string, terms: string[]): Array<{ start: number; end: number; term: string }> {\n const occ: Array<{ start: number; end: number; term: string }> = [];\n for (const term of terms) {\n let idx = 0;\n for (;;) {\n const found = haystackLower.indexOf(term, idx);\n if (found === -1) break;\n occ.push({ start: found, end: found + term.length, term });\n idx = found + term.length;\n }\n }\n // Longest span first at equal start, so \"tests\" beats its substring \"test\" and the\n // whole word gets highlighted; the emit loop then absorbs the shorter overlap.\n return occ.sort((a, b) => a.start - b.start || b.end - a.end);\n}\n\n// Slides a window over the sorted occurrences, same semantics as FTS5's own best-window\n// pick: most distinct terms, ties broken by most total hits.\nfunction bestWindowStart(occ: Array<{ start: number; end: number; term: string }>, windowSize: number): number {\n let best = occ[0].start;\n let bestDistinct = 0;\n let bestCount = 0;\n for (let i = 0; i < occ.length; i++) {\n const winEnd = occ[i].start + windowSize;\n const seen = new Set<string>();\n let count = 0;\n for (let j = i; j < occ.length && occ[j].start < winEnd; j++) {\n seen.add(occ[j].term);\n count++;\n }\n if (seen.size > bestDistinct || (seen.size === bestDistinct && count > bestCount)) {\n best = occ[i].start;\n bestDistinct = seen.size;\n bestCount = count;\n }\n }\n return best;\n}\n\n// snippet()-shaped excerpt: matched terms wrapped in «», … at cut edges. Linear in doc\n// length, only run for rows actually returned (<= k), unlike snippet()'s per-row cost.\nfunction computeExcerpt(text: string, terms: string[]): { excerpt: string; offset: number } {\n const occ = findOccurrences(text.toLowerCase(), terms);\n if (occ.length === 0) {\n // Raw substring scan, not porter-stemmed: a doc matched only through a stemmed variant\n // finds no occurrence here, so fall back to the doc's start, unmarked.\n const end = Math.min(text.length, EXCERPT_WINDOW);\n return { excerpt: `${text.slice(0, end).replace(/\\s+/g, ' ').trim()}${end < text.length ? '…' : ''}`, offset: 0 };\n }\n const start = bestWindowStart(occ, EXCERPT_WINDOW);\n const end = Math.min(text.length, start + EXCERPT_WINDOW);\n let out = '';\n let cursor = start;\n for (const o of occ) {\n if (o.start < start || o.end > end) continue;\n // Occurrences of duplicate or substring-overlapping terms (\"test tests\") can overlap;\n // emitting each would duplicate document text. Keep the first, absorb the rest.\n if (o.start < cursor) continue;\n out += `${text.slice(cursor, o.start)}«${text.slice(o.start, o.end)}»`;\n cursor = o.end;\n }\n out += text.slice(cursor, end);\n const prefix = start > 0 ? '…' : '';\n const suffix = end < text.length ? '…' : '';\n return { excerpt: `${prefix}${out.replace(/\\s+/g, ' ')}${suffix}`, offset: start };\n}\n\nfunction lineNumberAt(text: string, offset: number): number {\n let line = 1;\n for (let i = 0; i < offset; i++) if (text.charCodeAt(i) === 10) line++;\n return line;\n}\n\nasync function lineRangeFor(store: Store, path: string, line: number): Promise<string | null> {\n const stmt = await store.prepare('SELECT start_line, end_line FROM sections WHERE \"path\" = ? AND start_line <= ? AND end_line >= ? ORDER BY start_line DESC LIMIT 1');\n const row = (await stmt.get(path, line, line)) as { start_line: number; end_line: number } | undefined;\n return row ? `L${row.start_line}-${row.end_line}` : null;\n}\n\nexport interface SearchOptions {\n k?: number;\n where?: string; // SQL fragment against frontmatter alias `f`, e.g. \"f.status = 'active'\"\n preset?: string; // named preset; unknown name throws listing declared presets, undefined -> \"default\"\n include?: string[]; // ad hoc scope override (repeatable --include); independent of exclude\n exclude?: string[]; // ad hoc scope override (repeatable --exclude); independent of include\n noExclude?: boolean; // --no-exclude: drop the preset's exclude for this command\n}\n\n// The declared or defaulted signals compose via RRF; `via` names which ones produced each row.\n// `opts` arrives already resolved (config.ts:resolveSearch).\nexport async function search(store: Store, cfg: ResolvedConfig, terms: string, opts: SearchOptions = {}): Promise<Row[]> {\n const effective = resolveSearch(cfg, opts);\n const { k, signals } = effective;\n\n const allPaths = ((await (await store.prepare('SELECT \"path\" FROM frontmatter')).all()) as Array<{ path: string }>).map((r) => r.path);\n const scopePaths = await rawScope(store, cfg, opts, allPaths);\n const scopeActive = scopePaths.size < allPaths.length;\n // The set every candidate pool must be filtered to before truncation: scope narrowed by\n // --where, the same composition scopedPaths() gives the other commands.\n let allowedPaths: Set<string>;\n try {\n allowedPaths = await narrowByWhere(store, scopePaths, effective.where);\n } catch (err) {\n throw searchError(err as Error, terms, effective.where);\n }\n const fetch = Math.max(k * 3, 30);\n\n // A downloadable HF id proceeds -- getProvider fetches it lazily on consent. Only a\n // local path with missing files errors here, since nothing will ever fetch it for itself.\n const wantsVectors = signals.vectors !== undefined;\n if (wantsVectors) {\n const e = embedConfig(cfg); // validate.ts guarantees this is set whenever \"vectors\" is declared\n if (localModelMissing(e)) {\n throw new SenseError('EMBED_MODEL_MISSING', `preset \"${effective.presetName}\" searches with vectors, but the local model path \"${e.model}\" is missing ${MODEL_FILENAMES}; point embed.model at a directory containing them, or drop \"vectors\" from that preset's signals to search without them`);\n }\n }\n const semanticEnabled = wantsVectors && (await scopeHasEmbeddings(store, cfg, allowedPaths));\n\n // --where applies inside the candidate query (a post-filter would drop matches ranked past\n // the pool) and again on the final select, for link-derived rows.\n const scope = effective.where;\n const whereJoin = scope ? `JOIN frontmatter f ON f.\"path\" = content.path` : '';\n const whereCond = scope ? `AND (${scope})` : '';\n // Filtered before LIMIT, not after, or scoped notes ranking below the global top-`fetch`\n // never reach the filter; joined against a temp table since real scopes exceed SQLITE_MAX_VARIABLE_NUMBER.\n if (scopeActive) await materializeScope(store, '_search_scope', scopePaths);\n const scopeCond = scopeActive ? `AND content.path IN (SELECT \"path\" FROM _search_scope)` : '';\n\n const candidates = new Map<string, { score: number; via: string }>();\n let matchRows: LexicalHit[] = [];\n // A query that is only whitespace has no searchable words: zero lexical rows, and the other\n // signals compose normally.\n if (signals.words !== undefined && terms.trim() !== '') {\n try {\n matchRows = await wordsCandidates(store, candidates, terms, whereJoin, whereCond, scopeCond, fetch, signals.words);\n } catch (err) {\n throw searchError(err as Error, terms, scope);\n }\n }\n const hits = new Map(matchRows.map((r) => [r.path, r.hit]));\n // hit === null here means the bound suppressed snippet(), not \"no match\" -- distinguish\n // from via='link' rows (never in matchRows, so absent from this set) below.\n const oversized = new Set(matchRows.filter((r) => r.hit === null).map((r) => r.path));\n\n if (signals.links !== undefined) await linksCandidates(store, candidates, matchRows, allPaths, allowedPaths, fetch, signals.links);\n\n let chunkLines = new Map<string, string>();\n let chunkSimilarity = new Map<string, number>();\n if (semanticEnabled) {\n ({ chunkLines, chunkSimilarity } = await vectorsCandidates(store, cfg, candidates, terms, fetch, allowedPaths, signals.vectors as number));\n }\n\n await store.exec('DROP TABLE IF EXISTS _search');\n // DOUBLE, not REAL: sqlite's REAL is an 8-byte double but duckdb's is a 4-byte float, and the\n // rounded score/similarity are printed at full precision in rows.\n await store.exec('CREATE TEMP TABLE _search (\"path\" TEXT PRIMARY KEY, score DOUBLE, via TEXT, hit TEXT, lines TEXT, similarity DOUBLE)');\n if (candidates.size > 0) {\n await store.runBatch(\n 'INSERT INTO _search (\"path\", score, via, hit, lines, similarity) VALUES (?, ?, ?, ?, ?, ?)',\n [...candidates].map(([path, c]) => [path, c.score, c.via, hits.get(path) ?? null, chunkLines.get(path) ?? null, chunkSimilarity.get(path) ?? null])\n );\n }\n\n // Reapplies --where even though _search is already scope+where filtered, since the join to\n // frontmatter is already needed for the path column.\n const where = scope ? `WHERE (${scope})` : '';\n // lines: semantic rows carry their chunk's range, oversized-doc lexical rows gain one\n // below, everything else stays null; similarity stays semantic-only.\n const similarityCol = semanticEnabled ? ', _search.similarity' : '';\n const selectStmt = await store.prepare(\n `SELECT f.\"path\" AS path, content.title, content.summary, _search.hit, _search.via, round(_search.score, 4) AS score, _search.lines${similarityCol}\n FROM _search JOIN frontmatter f ON f.\"path\" = _search.\"path\" JOIN content ON content.path = _search.\"path\"\n ${where} ORDER BY _search.score DESC LIMIT ?`\n );\n const rows = (await selectStmt.all(k)) as Row[];\n\n if (oversized.size > 0) {\n const bareTerms = extractBareTerms(terms);\n for (const row of rows) {\n if (row.hit !== null || !oversized.has(row.path as string)) continue;\n let text: string;\n try {\n text = readFileSync(join(cfg.baseDir, row.path as string), 'utf8');\n } catch {\n continue; // vanished since the match; leave hit/lines null rather than throw\n }\n const { excerpt, offset } = computeExcerpt(text, bareTerms);\n row.hit = excerpt;\n if (row.lines == null) row.lines = featureEnabled(cfg, 'sections') ? await lineRangeFor(store, row.path as string, lineNumberAt(text, offset)) : null;\n }\n }\n\n return rows;\n}\n"],"names":["search","EXCERPT_WINDOW","extractBareTerms","query","cleaned","replace","split","map","tok","toLowerCase","trim","filter","length","findOccurrences","haystackLower","terms","occ","term","idx","found","indexOf","push","start","end","sort","a","b","bestWindowStart","windowSize","best","bestDistinct","bestCount","i","winEnd","seen","Set","count","j","add","size","computeExcerpt","text","Math","min","excerpt","slice","offset","out","cursor","o","prefix","suffix","lineNumberAt","line","charCodeAt","lineRangeFor","store","path","stmt","row","prepare","get","start_line","end_line","cfg","opts","effective","k","signals","allPaths","scopePaths","scopeActive","allowedPaths","err","fetch","wantsVectors","e","semanticEnabled","scope","whereJoin","whereCond","scopeCond","candidates","matchRows","hits","oversized","chunkLines","chunkSimilarity","where","similarityCol","selectStmt","rows","bareTerms","resolveSearch","all","r","rawScope","narrowByWhere","searchError","max","vectors","undefined","embedConfig","localModelMissing","SenseError","presetName","MODEL_FILENAMES","model","scopeHasEmbeddings","materializeScope","Map","words","wordsCandidates","hit","links","linksCandidates","vectorsCandidates","exec","runBatch","c","score","via","has","readFileSync","join","baseDir","lines","featureEnabled"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/signals.ts"],"sourcesContent":["import type { ResolvedConfig } from '../config/index.ts';\nimport { semanticCandidates } from '../embed/query.ts';\nimport { LINK_EDGES_SQL, toEdges } from '../features/index.ts';\nimport { personalizedRank } from '../graph/graph.ts';\nimport type { LexicalHit, Store } from '../store/types.ts';\n\n// RRF composes whatever the preset declares; the constant lives here since it belongs to\n// the fusion these three functions share, not to search() itself.\nconst RRF_K = 60;\n\nexport type Candidates = Map<string, { score: number; via: string }>;\n\n// BM25 match rows (store.lexical.query), folded into `candidates` by reciprocal rank scaled by\n// the preset's declared weight for this signal (default 1, bit-identical to the unweighted\n// score). Every other signal is seeded from its output, so search() runs this one first when\n// \"words\" is declared.\nexport async function wordsCandidates(store: Store, candidates: Candidates, query: string, whereJoin: string, whereCond: string, scopeCond: string, fetch: number, weight: number): Promise<LexicalHit[]> {\n const matchRows = await store.lexical.query(query, { whereJoin, whereCond, scopeCond, limit: fetch });\n matchRows.forEach((r, i) => {\n candidates.set(r.path, { score: weight / (RRF_K + i), via: 'match' });\n });\n return matchRows;\n}\n\n// Personalized-PageRank expansion from the word-match seeds, folded into `candidates` at this\n// signal's weight. A no-op when there is nothing to seed from (matchRows empty), same as before\n// this was a signal.\nexport async function linksCandidates(store: Store, candidates: Candidates, matchRows: LexicalHit[], allPaths: string[], allowedPaths: Set<string>, fetch: number, weight: number): Promise<void> {\n if (matchRows.length === 0) return;\n const stmt = await store.prepare(LINK_EDGES_SQL);\n const edges = toEdges((await stmt.all()) as Array<{ src: string; dst: string }>);\n if (edges.length === 0) return;\n // Gates the label only, not the score: restart mass ranks every seed without an incident\n // edge, but dropping it from the score reweights fusion (FEVER hit@10 0.997 -> 0.907).\n const linked = new Set(edges.flat());\n const seeds = new Map(matchRows.map((r, i) => [r.path, 1 / (i + 1)]));\n const ranked = [...personalizedRank(allPaths, edges, seeds)]\n .filter(([path, score]) => score > 1e-9 && allowedPaths.has(path))\n .sort((a, b) => b[1] - a[1])\n .slice(0, fetch);\n ranked.forEach(([path], i) => {\n const existing = candidates.get(path);\n if (existing) {\n existing.score += weight / (RRF_K + i);\n if (linked.has(path)) existing.via = 'match+link';\n } else {\n candidates.set(path, { score: weight / (RRF_K + i), via: 'link' });\n }\n });\n}\n\n// Vector expansion at the swept flat-region constants (pool = fetch), folded into `candidates`\n// at this signal's weight. Each row also carries its best chunk's line range and similarity,\n// for the caller.\nexport async function vectorsCandidates(store: Store, cfg: ResolvedConfig, candidates: Candidates, terms: string, fetch: number, allowedPaths: Set<string>, weight: number): Promise<{ chunkLines: Map<string, string>; chunkSimilarity: Map<string, number> }> {\n const chunkLines = new Map<string, string>();\n const chunkSimilarity = new Map<string, number>();\n const vec = await semanticCandidates(store, cfg, terms, fetch, allowedPaths);\n vec.forEach(({ path, lines, similarity }, i) => {\n chunkLines.set(path, lines);\n chunkSimilarity.set(path, similarity);\n const existing = candidates.get(path);\n if (existing) {\n existing.score += weight / (RRF_K + i);\n existing.via = `${existing.via}+vector`;\n } else {\n candidates.set(path, { score: weight / (RRF_K + i), via: 'vector' });\n }\n });\n return { chunkLines, chunkSimilarity };\n}\n"],"names":["linksCandidates","vectorsCandidates","wordsCandidates","RRF_K","store","candidates","query","whereJoin","whereCond","scopeCond","fetch","weight","matchRows","lexical","limit","forEach","r","i","set","path","score","via","allPaths","allowedPaths","stmt","edges","linked","seeds","ranked","length","prepare","LINK_EDGES_SQL","all","toEdges","Set","flat","Map","map","personalizedRank","filter","has","sort","a","b","slice","existing","get","cfg","terms","chunkLines","chunkSimilarity","vec","semanticCandidates","lines","similarity"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/commands/signals.ts"],"sourcesContent":["import type { ResolvedConfig } from '../config/index.ts';\nimport { semanticCandidates } from '../embed/query.ts';\nimport { LINK_EDGES_SQL, toEdges } from '../features/index.ts';\nimport { personalizedRank } from '../graph/graph.ts';\nimport type { LexicalHit, Store } from '../store/types.ts';\n\n// RRF composes whatever the preset declares; the constant lives here since it belongs to\n// the fusion these three functions share, not to search() itself.\nconst RRF_K = 60;\n\nexport type Candidates = Map<string, { score: number; via: string }>;\n\n// BM25 match rows (store.lexical.query), folded into `candidates` by reciprocal rank scaled by\n// the preset's declared weight for this signal. Every other signal is seeded from its output.\nexport async function wordsCandidates(store: Store, candidates: Candidates, query: string, whereJoin: string, whereCond: string, scopeCond: string, fetch: number, weight: number): Promise<LexicalHit[]> {\n const matchRows = await store.lexical.query(query, { whereJoin, whereCond, scopeCond, limit: fetch });\n matchRows.forEach((r, i) => {\n candidates.set(r.path, { score: weight / (RRF_K + i), via: 'match' });\n });\n return matchRows;\n}\n\n// Personalized-PageRank expansion from the word-match seeds, folded into `candidates` at this\n// signal's weight. A no-op when there is nothing to seed from (matchRows empty).\nexport async function linksCandidates(store: Store, candidates: Candidates, matchRows: LexicalHit[], allPaths: string[], allowedPaths: Set<string>, fetch: number, weight: number): Promise<void> {\n if (matchRows.length === 0) return;\n const stmt = await store.prepare(LINK_EDGES_SQL);\n const edges = toEdges((await stmt.all()) as Array<{ src: string; dst: string }>);\n if (edges.length === 0) return;\n // Gates the label only, not the score: restart mass ranks every seed without an incident\n // edge, but dropping it from the score reweights fusion (FEVER hit@10 0.997 -> 0.907).\n const linked = new Set(edges.flat());\n const seeds = new Map(matchRows.map((r, i) => [r.path, 1 / (i + 1)]));\n const ranked = [...personalizedRank(allPaths, edges, seeds)]\n .filter(([path, score]) => score > 1e-9 && allowedPaths.has(path))\n .sort((a, b) => b[1] - a[1])\n .slice(0, fetch);\n ranked.forEach(([path], i) => {\n const existing = candidates.get(path);\n if (existing) {\n existing.score += weight / (RRF_K + i);\n if (linked.has(path)) existing.via = 'match+link';\n } else {\n candidates.set(path, { score: weight / (RRF_K + i), via: 'link' });\n }\n });\n}\n\n// Vector expansion at the swept flat-region constants (pool = fetch), folded into `candidates`\n// at this signal's weight; each row also carries its best chunk's line range and similarity.\nexport async function vectorsCandidates(store: Store, cfg: ResolvedConfig, candidates: Candidates, terms: string, fetch: number, allowedPaths: Set<string>, weight: number): Promise<{ chunkLines: Map<string, string>; chunkSimilarity: Map<string, number> }> {\n const chunkLines = new Map<string, string>();\n const chunkSimilarity = new Map<string, number>();\n const vec = await semanticCandidates(store, cfg, terms, fetch, allowedPaths);\n vec.forEach(({ path, lines, similarity }, i) => {\n chunkLines.set(path, lines);\n chunkSimilarity.set(path, similarity);\n const existing = candidates.get(path);\n if (existing) {\n existing.score += weight / (RRF_K + i);\n existing.via = `${existing.via}+vector`;\n } else {\n candidates.set(path, { score: weight / (RRF_K + i), via: 'vector' });\n }\n });\n return { chunkLines, chunkSimilarity };\n}\n"],"names":["linksCandidates","vectorsCandidates","wordsCandidates","RRF_K","store","candidates","query","whereJoin","whereCond","scopeCond","fetch","weight","matchRows","lexical","limit","forEach","r","i","set","path","score","via","allPaths","allowedPaths","stmt","edges","linked","seeds","ranked","length","prepare","LINK_EDGES_SQL","all","toEdges","Set","flat","Map","map","personalizedRank","filter","has","sort","a","b","slice","existing","get","cfg","terms","chunkLines","chunkSimilarity","vec","semanticCandidates","lines","similarity"],"mappings":"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"}