sensemaking 0.16.0 → 0.17.1

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 (322) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/chunk/extract.d.cts +2 -0
  3. package/dist/cjs/chunk/extract.d.ts +2 -0
  4. package/dist/cjs/chunk/extract.js +139 -0
  5. package/dist/cjs/chunk/extract.js.map +1 -0
  6. package/dist/cjs/chunk/group.d.cts +4 -0
  7. package/dist/cjs/chunk/group.d.ts +4 -0
  8. package/dist/cjs/chunk/group.js +489 -0
  9. package/dist/cjs/chunk/group.js.map +1 -0
  10. package/dist/cjs/chunk/index.d.cts +8 -0
  11. package/dist/cjs/chunk/index.d.ts +8 -0
  12. package/dist/cjs/chunk/index.js +44 -0
  13. package/dist/cjs/chunk/index.js.map +1 -0
  14. package/dist/cjs/chunk/parse.d.cts +2 -0
  15. package/dist/cjs/chunk/parse.d.ts +2 -0
  16. package/dist/cjs/chunk/parse.js +71 -0
  17. package/dist/cjs/chunk/parse.js.map +1 -0
  18. package/dist/cjs/chunk/types.d.cts +19 -0
  19. package/dist/cjs/chunk/types.d.ts +19 -0
  20. package/dist/cjs/chunk/types.js +5 -0
  21. package/dist/cjs/chunk/types.js.map +1 -0
  22. package/dist/cjs/chunk/version.d.cts +1 -0
  23. package/dist/cjs/chunk/version.d.ts +1 -0
  24. package/dist/cjs/chunk/version.js +14 -0
  25. package/dist/cjs/chunk/version.js.map +1 -0
  26. package/dist/cjs/cli/map.js +5 -5
  27. package/dist/cjs/cli/map.js.map +1 -1
  28. package/dist/cjs/cli/named.js +3 -3
  29. package/dist/cjs/cli/named.js.map +1 -1
  30. package/dist/cjs/cli/path.js +9 -8
  31. package/dist/cjs/cli/path.js.map +1 -1
  32. package/dist/cjs/cli/peek.js +5 -5
  33. package/dist/cjs/cli/peek.js.map +1 -1
  34. package/dist/cjs/cli/related.js +5 -5
  35. package/dist/cjs/cli/related.js.map +1 -1
  36. package/dist/cjs/cli/search.js +5 -5
  37. package/dist/cjs/cli/search.js.map +1 -1
  38. package/dist/cjs/cli/shared.d.cts +1 -1
  39. package/dist/cjs/cli/shared.d.ts +1 -1
  40. package/dist/cjs/cli/shared.js +3 -3
  41. package/dist/cjs/cli/shared.js.map +1 -1
  42. package/dist/cjs/cli/status.js +19 -19
  43. package/dist/cjs/cli/status.js.map +1 -1
  44. package/dist/cjs/commands/map.d.cts +1 -1
  45. package/dist/cjs/commands/map.d.ts +1 -1
  46. package/dist/cjs/commands/map.js.map +1 -1
  47. package/dist/cjs/commands/peek.d.cts +1 -1
  48. package/dist/cjs/commands/peek.d.ts +1 -1
  49. package/dist/cjs/commands/peek.js +13 -6
  50. package/dist/cjs/commands/peek.js.map +1 -1
  51. package/dist/cjs/commands/scope.js +1 -1
  52. package/dist/cjs/commands/scope.js.map +1 -1
  53. package/dist/cjs/commands/search.d.cts +1 -1
  54. package/dist/cjs/commands/search.d.ts +1 -1
  55. package/dist/cjs/commands/search.js +3 -3
  56. package/dist/cjs/commands/search.js.map +1 -1
  57. package/dist/cjs/commands/signals.js +1 -1
  58. package/dist/cjs/commands/signals.js.map +1 -1
  59. package/dist/cjs/config/access.d.cts +3 -1
  60. package/dist/cjs/config/access.d.ts +3 -1
  61. package/dist/cjs/config/access.js +11 -11
  62. package/dist/cjs/config/access.js.map +1 -1
  63. package/dist/cjs/config/index.d.cts +1 -0
  64. package/dist/cjs/config/index.d.ts +1 -0
  65. package/dist/cjs/config/index.js +4 -0
  66. package/dist/cjs/config/index.js.map +1 -1
  67. package/dist/cjs/config/types.d.cts +1 -0
  68. package/dist/cjs/config/types.d.ts +1 -0
  69. package/dist/cjs/config/types.js.map +1 -1
  70. package/dist/cjs/config/validate.d.cts +1 -0
  71. package/dist/cjs/config/validate.d.ts +1 -0
  72. package/dist/cjs/config/validate.js +8 -1
  73. package/dist/cjs/config/validate.js.map +1 -1
  74. package/dist/cjs/db/open.d.cts +1 -1
  75. package/dist/cjs/db/open.d.ts +1 -1
  76. package/dist/cjs/db/open.js +4 -4
  77. package/dist/cjs/db/open.js.map +1 -1
  78. package/dist/cjs/db/reconcile.js +8 -8
  79. package/dist/cjs/db/reconcile.js.map +1 -1
  80. package/dist/cjs/{sql-functions.js → db/sql-functions.js} +1 -1
  81. package/dist/cjs/db/sql-functions.js.map +1 -0
  82. package/dist/cjs/embed/distribution.d.cts +4 -0
  83. package/dist/cjs/embed/distribution.d.ts +4 -0
  84. package/dist/cjs/embed/distribution.js +30 -0
  85. package/dist/cjs/embed/distribution.js.map +1 -0
  86. package/dist/cjs/embed/langfit.d.cts +0 -3
  87. package/dist/cjs/embed/langfit.d.ts +0 -3
  88. package/dist/cjs/embed/langfit.js +53 -96
  89. package/dist/cjs/embed/langfit.js.map +1 -1
  90. package/dist/cjs/embed/languages.js.map +1 -1
  91. package/dist/cjs/embed/query.js +6 -6
  92. package/dist/cjs/embed/query.js.map +1 -1
  93. package/dist/cjs/embed/static.js +8 -35
  94. package/dist/cjs/embed/static.js.map +1 -1
  95. package/dist/cjs/features/embed.d.cts +2 -5
  96. package/dist/cjs/features/embed.d.ts +2 -5
  97. package/dist/cjs/features/embed.js +36 -58
  98. package/dist/cjs/features/embed.js.map +1 -1
  99. package/dist/cjs/{fences.js → features/fences.js} +1 -1
  100. package/dist/cjs/features/fences.js.map +1 -0
  101. package/dist/cjs/features/links.js +1 -1
  102. package/dist/cjs/features/links.js.map +1 -1
  103. package/dist/cjs/features/rank.js +1 -1
  104. package/dist/cjs/features/rank.js.map +1 -1
  105. package/dist/cjs/features/sections.js +4 -3
  106. package/dist/cjs/features/sections.js.map +1 -1
  107. package/dist/cjs/features/tags.js +1 -1
  108. package/dist/cjs/features/tags.js.map +1 -1
  109. package/dist/cjs/features/types.d.cts +4 -2
  110. package/dist/cjs/features/types.d.ts +4 -2
  111. package/dist/cjs/graph/graph.js.map +1 -0
  112. package/dist/cjs/graph/traverse.js.map +1 -0
  113. package/dist/cjs/index.d.cts +4 -4
  114. package/dist/cjs/index.d.ts +4 -4
  115. package/dist/cjs/index.js +4 -1
  116. package/dist/cjs/index.js.map +1 -1
  117. package/dist/cjs/output/column-hint.js.map +1 -0
  118. package/dist/cjs/output/output.js.map +1 -0
  119. package/dist/cjs/output/progress.js.map +1 -0
  120. package/dist/cjs/{search-error.js → output/search-error.js} +1 -1
  121. package/dist/cjs/output/search-error.js.map +1 -0
  122. package/dist/cjs/scan/frontmatter.d.cts +13 -0
  123. package/dist/cjs/scan/frontmatter.d.ts +13 -0
  124. package/dist/cjs/scan/frontmatter.js +229 -0
  125. package/dist/cjs/scan/frontmatter.js.map +1 -0
  126. package/dist/cjs/scan/index.d.cts +25 -0
  127. package/dist/cjs/scan/index.d.ts +25 -0
  128. package/dist/cjs/scan/index.js +107 -0
  129. package/dist/cjs/scan/index.js.map +1 -0
  130. package/dist/cjs/scan/list.d.cts +12 -0
  131. package/dist/cjs/scan/list.d.ts +12 -0
  132. package/dist/cjs/scan/list.js +154 -0
  133. package/dist/cjs/scan/list.js.map +1 -0
  134. package/dist/cjs/text/segment.d.cts +3 -0
  135. package/dist/cjs/text/segment.d.ts +3 -0
  136. package/dist/cjs/{segment.js → text/segment.js} +17 -14
  137. package/dist/cjs/text/segment.js.map +1 -0
  138. package/dist/cjs/text/strip.d.cts +3 -0
  139. package/dist/cjs/text/strip.d.ts +3 -0
  140. package/dist/cjs/text/strip.js +32 -0
  141. package/dist/cjs/text/strip.js.map +1 -0
  142. package/dist/esm/chunk/extract.d.ts +2 -0
  143. package/dist/esm/chunk/extract.js +114 -0
  144. package/dist/esm/chunk/extract.js.map +1 -0
  145. package/dist/esm/chunk/group.d.ts +4 -0
  146. package/dist/esm/chunk/group.js +253 -0
  147. package/dist/esm/chunk/group.js.map +1 -0
  148. package/dist/esm/chunk/index.d.ts +8 -0
  149. package/dist/esm/chunk/index.js +16 -0
  150. package/dist/esm/chunk/index.js.map +1 -0
  151. package/dist/esm/chunk/parse.d.ts +2 -0
  152. package/dist/esm/chunk/parse.js +63 -0
  153. package/dist/esm/chunk/parse.js.map +1 -0
  154. package/dist/esm/chunk/types.d.ts +19 -0
  155. package/dist/esm/chunk/types.js +2 -0
  156. package/dist/esm/chunk/types.js.map +1 -0
  157. package/dist/esm/chunk/version.d.ts +1 -0
  158. package/dist/esm/chunk/version.js +3 -0
  159. package/dist/esm/chunk/version.js.map +1 -0
  160. package/dist/esm/cli/map.js +2 -2
  161. package/dist/esm/cli/map.js.map +1 -1
  162. package/dist/esm/cli/named.js +2 -2
  163. package/dist/esm/cli/named.js.map +1 -1
  164. package/dist/esm/cli/path.js +4 -3
  165. package/dist/esm/cli/path.js.map +1 -1
  166. package/dist/esm/cli/peek.js +2 -2
  167. package/dist/esm/cli/peek.js.map +1 -1
  168. package/dist/esm/cli/related.js +2 -2
  169. package/dist/esm/cli/related.js.map +1 -1
  170. package/dist/esm/cli/search.js +2 -2
  171. package/dist/esm/cli/search.js.map +1 -1
  172. package/dist/esm/cli/shared.d.ts +1 -1
  173. package/dist/esm/cli/shared.js +3 -3
  174. package/dist/esm/cli/shared.js.map +1 -1
  175. package/dist/esm/cli/status.js +3 -3
  176. package/dist/esm/cli/status.js.map +1 -1
  177. package/dist/esm/commands/map.d.ts +1 -1
  178. package/dist/esm/commands/map.js.map +1 -1
  179. package/dist/esm/commands/peek.d.ts +1 -1
  180. package/dist/esm/commands/peek.js +8 -1
  181. package/dist/esm/commands/peek.js.map +1 -1
  182. package/dist/esm/commands/scope.js +1 -1
  183. package/dist/esm/commands/scope.js.map +1 -1
  184. package/dist/esm/commands/search.d.ts +1 -1
  185. package/dist/esm/commands/search.js +3 -3
  186. package/dist/esm/commands/search.js.map +1 -1
  187. package/dist/esm/commands/signals.js +1 -1
  188. package/dist/esm/commands/signals.js.map +1 -1
  189. package/dist/esm/config/access.d.ts +3 -1
  190. package/dist/esm/config/access.js +9 -9
  191. package/dist/esm/config/access.js.map +1 -1
  192. package/dist/esm/config/index.d.ts +1 -0
  193. package/dist/esm/config/index.js +1 -0
  194. package/dist/esm/config/index.js.map +1 -1
  195. package/dist/esm/config/types.d.ts +1 -0
  196. package/dist/esm/config/types.js.map +1 -1
  197. package/dist/esm/config/validate.d.ts +1 -0
  198. package/dist/esm/config/validate.js +8 -2
  199. package/dist/esm/config/validate.js.map +1 -1
  200. package/dist/esm/db/open.d.ts +1 -1
  201. package/dist/esm/db/open.js +5 -5
  202. package/dist/esm/db/open.js.map +1 -1
  203. package/dist/esm/db/reconcile.js +4 -4
  204. package/dist/esm/db/reconcile.js.map +1 -1
  205. package/dist/esm/{sql-functions.js → db/sql-functions.js} +1 -1
  206. package/dist/esm/db/sql-functions.js.map +1 -0
  207. package/dist/esm/embed/distribution.d.ts +4 -0
  208. package/dist/esm/embed/distribution.js +11 -0
  209. package/dist/esm/embed/distribution.js.map +1 -0
  210. package/dist/esm/embed/langfit.d.ts +0 -3
  211. package/dist/esm/embed/langfit.js +8 -8
  212. package/dist/esm/embed/langfit.js.map +1 -1
  213. package/dist/esm/embed/languages.js.map +1 -1
  214. package/dist/esm/embed/query.js +5 -5
  215. package/dist/esm/embed/query.js.map +1 -1
  216. package/dist/esm/embed/static.js +6 -2
  217. package/dist/esm/embed/static.js.map +1 -1
  218. package/dist/esm/features/embed.d.ts +2 -5
  219. package/dist/esm/features/embed.js +34 -32
  220. package/dist/esm/features/embed.js.map +1 -1
  221. package/dist/esm/{fences.js → features/fences.js} +1 -1
  222. package/dist/esm/features/fences.js.map +1 -0
  223. package/dist/esm/features/links.js +1 -1
  224. package/dist/esm/features/links.js.map +1 -1
  225. package/dist/esm/features/rank.js +1 -1
  226. package/dist/esm/features/rank.js.map +1 -1
  227. package/dist/esm/features/sections.js +4 -3
  228. package/dist/esm/features/sections.js.map +1 -1
  229. package/dist/esm/features/tags.js +1 -1
  230. package/dist/esm/features/tags.js.map +1 -1
  231. package/dist/esm/features/types.d.ts +4 -2
  232. package/dist/esm/features/types.js.map +1 -1
  233. package/dist/esm/graph/graph.js.map +1 -0
  234. package/dist/esm/graph/traverse.js.map +1 -0
  235. package/dist/esm/index.d.ts +4 -4
  236. package/dist/esm/index.js +2 -2
  237. package/dist/esm/index.js.map +1 -1
  238. package/dist/esm/output/column-hint.js.map +1 -0
  239. package/dist/esm/output/output.js.map +1 -0
  240. package/dist/esm/output/progress.js.map +1 -0
  241. package/dist/esm/{search-error.js → output/search-error.js} +1 -1
  242. package/dist/esm/output/search-error.js.map +1 -0
  243. package/dist/esm/scan/frontmatter.d.ts +13 -0
  244. package/dist/esm/{scan.js → scan/frontmatter.js} +4 -123
  245. package/dist/esm/scan/frontmatter.js.map +1 -0
  246. package/dist/esm/scan/index.d.ts +25 -0
  247. package/dist/esm/scan/index.js +58 -0
  248. package/dist/esm/scan/index.js.map +1 -0
  249. package/dist/esm/scan/list.d.ts +12 -0
  250. package/dist/esm/scan/list.js +58 -0
  251. package/dist/esm/scan/list.js.map +1 -0
  252. package/dist/esm/text/segment.d.ts +3 -0
  253. package/dist/esm/{segment.js → text/segment.js} +3 -3
  254. package/dist/esm/text/segment.js.map +1 -0
  255. package/dist/esm/text/strip.d.ts +3 -0
  256. package/dist/esm/text/strip.js +12 -0
  257. package/dist/esm/text/strip.js.map +1 -0
  258. package/package.json +15 -2
  259. package/schema.json +8 -1
  260. package/skills/sense/SKILL.md +1 -1
  261. package/skills/sense-setup/SKILL.md +3 -3
  262. package/dist/cjs/column-hint.js.map +0 -1
  263. package/dist/cjs/fences.js.map +0 -1
  264. package/dist/cjs/graph.js.map +0 -1
  265. package/dist/cjs/output.js.map +0 -1
  266. package/dist/cjs/progress.js.map +0 -1
  267. package/dist/cjs/scan.d.cts +0 -35
  268. package/dist/cjs/scan.d.ts +0 -35
  269. package/dist/cjs/scan.js +0 -436
  270. package/dist/cjs/scan.js.map +0 -1
  271. package/dist/cjs/search-error.js.map +0 -1
  272. package/dist/cjs/segment.d.cts +0 -2
  273. package/dist/cjs/segment.d.ts +0 -2
  274. package/dist/cjs/segment.js.map +0 -1
  275. package/dist/cjs/sql-functions.js.map +0 -1
  276. package/dist/cjs/traverse.js.map +0 -1
  277. package/dist/esm/column-hint.js.map +0 -1
  278. package/dist/esm/fences.js.map +0 -1
  279. package/dist/esm/graph.js.map +0 -1
  280. package/dist/esm/output.js.map +0 -1
  281. package/dist/esm/progress.js.map +0 -1
  282. package/dist/esm/scan.d.ts +0 -35
  283. package/dist/esm/scan.js.map +0 -1
  284. package/dist/esm/search-error.js.map +0 -1
  285. package/dist/esm/segment.d.ts +0 -2
  286. package/dist/esm/segment.js.map +0 -1
  287. package/dist/esm/sql-functions.js.map +0 -1
  288. package/dist/esm/traverse.js.map +0 -1
  289. /package/dist/cjs/{sql-functions.d.cts → db/sql-functions.d.cts} +0 -0
  290. /package/dist/cjs/{sql-functions.d.ts → db/sql-functions.d.ts} +0 -0
  291. /package/dist/cjs/{fences.d.cts → features/fences.d.cts} +0 -0
  292. /package/dist/cjs/{fences.d.ts → features/fences.d.ts} +0 -0
  293. /package/dist/cjs/{graph.d.cts → graph/graph.d.cts} +0 -0
  294. /package/dist/cjs/{graph.d.ts → graph/graph.d.ts} +0 -0
  295. /package/dist/cjs/{graph.js → graph/graph.js} +0 -0
  296. /package/dist/cjs/{traverse.d.cts → graph/traverse.d.cts} +0 -0
  297. /package/dist/cjs/{traverse.d.ts → graph/traverse.d.ts} +0 -0
  298. /package/dist/cjs/{traverse.js → graph/traverse.js} +0 -0
  299. /package/dist/cjs/{column-hint.d.cts → output/column-hint.d.cts} +0 -0
  300. /package/dist/cjs/{column-hint.d.ts → output/column-hint.d.ts} +0 -0
  301. /package/dist/cjs/{column-hint.js → output/column-hint.js} +0 -0
  302. /package/dist/cjs/{output.d.cts → output/output.d.cts} +0 -0
  303. /package/dist/cjs/{output.d.ts → output/output.d.ts} +0 -0
  304. /package/dist/cjs/{output.js → output/output.js} +0 -0
  305. /package/dist/cjs/{progress.d.cts → output/progress.d.cts} +0 -0
  306. /package/dist/cjs/{progress.d.ts → output/progress.d.ts} +0 -0
  307. /package/dist/cjs/{progress.js → output/progress.js} +0 -0
  308. /package/dist/cjs/{search-error.d.cts → output/search-error.d.cts} +0 -0
  309. /package/dist/cjs/{search-error.d.ts → output/search-error.d.ts} +0 -0
  310. /package/dist/esm/{sql-functions.d.ts → db/sql-functions.d.ts} +0 -0
  311. /package/dist/esm/{fences.d.ts → features/fences.d.ts} +0 -0
  312. /package/dist/esm/{graph.d.ts → graph/graph.d.ts} +0 -0
  313. /package/dist/esm/{graph.js → graph/graph.js} +0 -0
  314. /package/dist/esm/{traverse.d.ts → graph/traverse.d.ts} +0 -0
  315. /package/dist/esm/{traverse.js → graph/traverse.js} +0 -0
  316. /package/dist/esm/{column-hint.d.ts → output/column-hint.d.ts} +0 -0
  317. /package/dist/esm/{column-hint.js → output/column-hint.js} +0 -0
  318. /package/dist/esm/{output.d.ts → output/output.d.ts} +0 -0
  319. /package/dist/esm/{output.js → output/output.js} +0 -0
  320. /package/dist/esm/{progress.d.ts → output/progress.d.ts} +0 -0
  321. /package/dist/esm/{progress.js → output/progress.js} +0 -0
  322. /package/dist/esm/{search-error.d.ts → output/search-error.d.ts} +0 -0
@@ -30,9 +30,9 @@ A preset is a named, self-contained bundle of settings. `default` (required) is
30
30
  - Presets may overlap; they are views, not partitions.
31
31
  - Global `features` (`links`, `sections`, `rank`) still toggle tree-wide; most trees never touch them.
32
32
 
33
- **Vectors take two decisions, in two places.** The top-level `"embed": { "model", "provider": "static"|"openai"|"cohere", "url", "key" }` block names the model and says whether the tree has vectors at all. A preset's `signals` says which engines that scope uses: a layer searched for exact wording (ingested sources, archives, generated output) declares `"signals": {"words": 1, "links": 1}`, costs no embedding, and its searches run on words and links. That is the main scale lever, and it is the llm-wiki split: compiled pages searched by meaning, raw sources searched for the phrasing you are citing. Each named signal's number is its RRF weight, not a toggle -- 1 is the default and reproduces equal-weight fusion; a preset can instead raise one signal's number, e.g. `{"words": 1, "vectors": 4}`, to shift the fused ranking toward that signal without dropping the others. Whether that helps is corpus- and model-contingent, not a fixed rule: BENCHMARKING.md's 2026-08-27 weight-sweep table measures equal weight against {0.5, 1, 2, 4} and vectors-only on nfcorpus and on MIRACL zh with an HTTP encoder, and the two corpora do not agree on which weight wins. `static` is the built-in pure-JS Model2Vec loader and handles paraphrase and reworded concepts; tight domain jargon ("heart attack" for "myocardial infarction") is where an `openai`- or `cohere`-shaped encoder model tends to do better, measured in BENCHMARKING.md, "Retrieval quality". Naming the model in the config is the consent to fetch it: the first vector search downloads it once per machine into `~/.sense/models` (or `sense download` prefetches) (huggingface_hub's cache layout, one snapshot directory per resolved revision), so several models coexist and switching between them rebuilds the index rather than mixing vector spaces. A `model` holding a path instead of a Hugging Face id points at a local directory, which `sense download` reports as nothing to fetch. The first search after that embeds the tree (progress on stderr; minutes on tens of thousands of notes, seconds on small trees). A config edit that changes coverage or features rebuilds the cache, vectors included, so settle presets before the first vector search on a large tree or that embedding run is paid twice.
33
+ **Vectors take two decisions, in two places.** The top-level `"embed": { "model", "provider": "static"|"openai"|"cohere", "url", "key", "chunkTokens" }` block names the model and says whether the tree has vectors at all. `chunkTokens` is a chunk size ceiling in estimated tokens for small-context models; default 500. A preset's `signals` says which engines that scope uses: a layer searched for exact wording (ingested sources, archives, generated output) declares `"signals": {"words": 1, "links": 1}`, costs no embedding, and its searches run on words and links. That is the main scale lever, and it is the llm-wiki split: compiled pages searched by meaning, raw sources searched for the phrasing you are citing. Each named signal's number is its RRF weight, not a toggle -- 1 is the default and reproduces equal-weight fusion; a preset can instead raise one signal's number, e.g. `{"words": 1, "vectors": 4}`, to shift the fused ranking toward that signal without dropping the others. Whether that helps is corpus- and model-contingent, not a fixed rule: benchmark/reports/2026-08-27-embedding-model-selection.md's weight-sweep table measures equal weight against {0.5, 1, 2, 4} and vectors-only on nfcorpus and on MIRACL zh with an HTTP encoder, and the two corpora do not agree on which weight wins. `static` is the built-in pure-JS Model2Vec loader and handles paraphrase and reworded concepts; tight domain jargon ("heart attack" for "myocardial infarction") is where an `openai`- or `cohere`-shaped encoder model tends to do better, measured in the same report's encoder-tier tables. Naming the model in the config is the consent to fetch it: the first vector search downloads it once per machine into `~/.sense/models` (or `sense download` prefetches) (huggingface_hub's cache layout, one snapshot directory per resolved revision), so several models coexist and switching between them rebuilds the index rather than mixing vector spaces. A `model` holding a path instead of a Hugging Face id points at a local directory, which `sense download` reports as nothing to fetch. The first search after that embeds the tree (progress on stderr; minutes on tens of thousands of notes, seconds on small trees). A config edit that changes coverage or features rebuilds the cache, vectors included, so settle presets before the first vector search on a large tree or that embedding run is paid twice.
34
34
 
35
- **Finding a model.** The default, `potion-retrieval-32M`, is English only. A tree whose text is mostly a language the model does not declare fails loudly at embed time (`EMBED_MODEL_MISMATCH`, naming the fix), and `sense status` shows the detected language mix beside the model's declared languages. A model whose card declares no languages leaves that check off, and a mismatched pairing then degrades silently -- nearest-neighbour search always returns a neighbour regardless of fit -- so check the card's languages yourself when the tree is not English. Picking a model is a lookup against the source, not a name to memorize: for a static model, filter Hugging Face's model2vec library for the target language and read the card for its declared languages, its safetensors shape, and F32 weights (an int8 republish fails the loader's dtype check by design). For an encoder reached over HTTP, Ollama's embedding-model library and LM Studio's catalog list each model's languages and context length; both serve an OpenAI-shaped endpoint, so `provider: "openai"` with `url` pointing at the local port reaches either with no other config. Cohere's hosted models are reached with `provider: "cohere"` instead. One dated measurement stands in for a name table that would go stale: `potion-retrieval-32M` was the best-measured static English retrieval model as of 2026-08, per BENCHMARKING.md's bake-off.
35
+ **Finding a model.** The default, `potion-retrieval-32M`, is English only. A tree whose text is mostly a language the model does not declare fails loudly at embed time (`EMBED_MODEL_MISMATCH`, naming the fix), and `sense status` shows the detected language mix beside the model's declared languages. A model whose card declares no languages leaves that check off, and a mismatched pairing then degrades silently -- nearest-neighbour search always returns a neighbour regardless of fit -- so check the card's languages yourself when the tree is not English. Picking a model is a lookup against the source, not a name to memorize: for a static model, filter Hugging Face's model2vec library for the target language and read the card for its declared languages, its safetensors shape, and F32 weights (an int8 republish fails the loader's dtype check by design). For an encoder reached over HTTP, Ollama's embedding-model library and LM Studio's catalog list each model's languages and context length; both serve an OpenAI-shaped endpoint, so `provider: "openai"` with `url` pointing at the local port reaches either with no other config. Cohere's hosted models are reached with `provider: "cohere"` instead. One dated measurement stands in for a name table that would go stale: `potion-retrieval-32M` was the best-measured static English retrieval model as of 2026-08, per benchmark/reports/2026-08-27-embedding-model-selection.md's static-ladder table.
36
36
 
37
37
  **Large vaults**: everything except the vector build is measured linear to 100k notes with no tuning (BENCHMARKING.md). The knobs that matter are `k` (more, smaller results; rows carry `lines` section ranges, so agents read sections, not files) and `"signals": {"words": 1, "links": 1}` on the layers that do not earn vectors.
38
38
 
@@ -47,6 +47,6 @@ These belong to the tree's owner. sense works with any of them and reads no inst
47
47
  - **Language.** No decision needed. A language written without word spaces (Chinese, Japanese, Thai, Khmer, Lao, Burmese) is indexed per grapheme and searched as an ordered grapheme phrase, so `sense search "全文"` finds what it should. This is substring semantics, what `grep` gives: a query matches wherever its exact text occurs, including inside a longer run, and needs no minimum length. A language written with spaces is left exactly as it was, storing nothing extra, and its stemming is unaffected. The one place this does not reach is a hand-written `content MATCH '...'`, which cannot be rewritten for its author: pass the terms through `segment()` there. `content.tokenize` is a separate lever with a different purpose, substring matching inside a Latin word (`trigram`) or keeping hyphenated terms whole (`unicode61 tokenchars '-_'`); naming one turns the grapheme-phrase scheme off, since the tree has then chosen its own scheme. Changing it rebuilds the text index only; vectors, links, and sections are kept.
48
48
  - **Summaries.** A one-line `summary:` is optional and pays twice: it shows in every result row (often answering a question with no file read) and is a weighted search field ranked above body text. The cost is writing and maintaining the line as notes change.
49
49
  - **Folder shape.** Globs find the files, paths are queryable text, links resolve by basename at any depth, but presets make folders meaningful: a folder is the natural unit that gets its own coverage and settings.
50
- - **Note size.** Many small notes: precise search hits, whole-file reads stay cheap, more links to maintain. Fewer large notes: `sections`, `peek`, and the `lines` column carry the cost down to line-range reads. Both work.
50
+ - **Note size.** Many small notes: precise search hits, whole-file reads stay cheap, more links to maintain. Fewer large notes: `sections`, `peek`, and the `lines` column carry the cost down to line-range reads. Both work. A long section no longer becomes one oversized vector either: chunking splits at headings and caps each chunk around 500 estimated tokens (CJK counted 1:1, spaced scripts ~4:1), so an oversized note degrades to more, smaller chunks rather than one truncated one; `embed.chunkTokens` lowers that cap further for a small-context model.
51
51
  - **Recurring questions.** Save a scenario an agent will repeat under `queries`, naming the verb it runs: `{ "sql": "..." }` for filters and reports, or `{ "search": "...", "preset": "raw", "k": 5 }` for a ranked search. Either runs as `sense <name>`, and running one is how it is validated: a typo'd column or an unknown preset errors and exits nonzero. A parameterised entry validates with any argument, since SQL is prepared before parameters bind.
52
52
  - **Where decisions live.** Choices that should outlive one conversation can be recorded in the agent's own instruction or skill files, or in a note in the tree itself; a one-off search over an existing corpus needs none of that.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/column-hint.ts"],"sourcesContent":["import type { DatabaseSync } from 'node:sqlite';\n\n// A frontmatter key with punctuation (`plugin-id`, `a.b`) is a real column, but naming it\n// unquoted in SQL parses as an expression: `plugin-id` is `plugin - id`, and SQLite's error\n// names a fragment (`plugin`) the user never wrote. This maps that fragment back to the\n// columns it could have come from, so the error names the actual fix instead.\n\nfunction startsWithBoundary(name: string, prefix: string): boolean {\n return name.length > prefix.length && name.startsWith(prefix) && /\\W/.test(name[prefix.length]);\n}\n\nexport function columnHint(db: DatabaseSync, err: Error): Error {\n const match = /no such column: (\\S+)/.exec(err.message);\n if (!match) return err;\n const token = match[1];\n // `f.plugin` -> `plugin`; left as-is when there's no leading alias segment, which also\n // covers a column literally named `a.b` -- the full-token check below matches that case\n // directly, so stripping here never needs to special-case it.\n const aliasStripped = token.replace(/^[A-Za-z_]\\w*\\./, '');\n const forms = new Set([token, aliasStripped]);\n const columns = (db.prepare('PRAGMA table_info(frontmatter)').all() as Array<{ name: string }>).map((c) => c.name);\n const candidates = new Set<string>();\n for (const name of columns) {\n for (const form of forms) {\n if (name === form || startsWithBoundary(name, form)) candidates.add(name);\n }\n }\n if (candidates.size === 0) return err;\n const quoted = [...candidates].map((name) => `\"${name.split('\"').join('\"\"')}\"`).join(', ');\n return new Error(`${err.message} -- ${quoted} needs double quotes in SQL: unquoted, SQLite parses the punctuation as an operator instead of column syntax.`);\n}\n"],"names":["columnHint","startsWithBoundary","name","prefix","length","startsWith","test","db","err","match","exec","message","token","aliasStripped","replace","forms","Set","columns","prepare","all","map","c","candidates","form","add","size","quoted","split","join","Error"],"mappings":";;;;+BAWgBA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAThB,0FAA0F;AAC1F,4FAA4F;AAC5F,wFAAwF;AACxF,8EAA8E;AAE9E,SAASC,mBAAmBC,IAAY,EAAEC,MAAc;IACtD,OAAOD,KAAKE,MAAM,GAAGD,OAAOC,MAAM,IAAIF,KAAKG,UAAU,CAACF,WAAW,KAAKG,IAAI,CAACJ,IAAI,CAACC,OAAOC,MAAM,CAAC;AAChG;AAEO,SAASJ,WAAWO,EAAgB,EAAEC,GAAU;IACrD,IAAMC,QAAQ,wBAAwBC,IAAI,CAACF,IAAIG,OAAO;IACtD,IAAI,CAACF,OAAO,OAAOD;IACnB,IAAMI,QAAQH,KAAK,CAAC,EAAE;IACtB,uFAAuF;IACvF,wFAAwF;IACxF,8DAA8D;IAC9D,IAAMI,gBAAgBD,MAAME,OAAO,CAAC,mBAAmB;IACvD,IAAMC,QAAQ,IAAIC,IAAI;QAACJ;QAAOC;KAAc;IAC5C,IAAMI,UAAU,AAACV,GAAGW,OAAO,CAAC,kCAAkCC,GAAG,GAA+BC,GAAG,CAAC,SAACC;eAAMA,EAAEnB,IAAI;;IACjH,IAAMoB,aAAa,IAAIN;QAClB,kCAAA,2BAAA;;QAAL,QAAK,YAAcC,4BAAd,SAAA,6BAAA,QAAA,yBAAA,iCAAuB;YAAvB,IAAMf,OAAN;gBACE,mCAAA,4BAAA;;gBAAL,QAAK,aAAca,0BAAd,UAAA,8BAAA,SAAA,0BAAA,kCAAqB;oBAArB,IAAMQ,OAAN;oBACH,IAAIrB,SAASqB,QAAQtB,mBAAmBC,MAAMqB,OAAOD,WAAWE,GAAG,CAACtB;gBACtE;;gBAFK;gBAAA;;;yBAAA,8BAAA;wBAAA;;;wBAAA;8BAAA;;;;QAGP;;QAJK;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAKL,IAAIoB,WAAWG,IAAI,KAAK,GAAG,OAAOjB;IAClC,IAAMkB,SAAS,AAAC,qBAAGJ,YAAYF,GAAG,CAAC,SAAClB;eAAS,AAAC,IAA8B,OAA3BA,KAAKyB,KAAK,CAAC,KAAKC,IAAI,CAAC,OAAM;OAAIA,IAAI,CAAC;IACrF,OAAO,IAAIC,MAAM,AAAC,GAAoBH,OAAlBlB,IAAIG,OAAO,EAAC,QAAa,OAAPe,QAAO;AAC/C"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/fences.ts"],"sourcesContent":["// Shared line-fence tracker for tags/sections/embed. Opener: >=3 backticks or tildes at column\n// 0 -- no indent allowance, a deliberate divergence from CommonMark's up-to-3-space rule (see\n// test/unit/fences.test.ts DIVERGENCES table). A backtick opener's info string must not itself\n// contain a backtick (spec rule). A closer is a run of the SAME character, length >= the\n// opener's, holding nothing but trailing spaces after the run.\n\nexport interface FenceTracker {\n feed(line: string): boolean; // true iff this line is a fence delimiter (open or close)\n readonly inFence: boolean;\n}\n\nconst BACKTICK_OPEN = /^(`{3,})(.*)$/;\nconst TILDE_OPEN = /^(~{3,})(.*)$/;\n\nexport function fenceTracker(): FenceTracker {\n let inFence = false;\n let fenceChar = '';\n let fenceLen = 0;\n return {\n feed(line: string): boolean {\n if (!inFence) {\n const bt = BACKTICK_OPEN.exec(line);\n if (bt && !bt[2].includes('`')) {\n inFence = true;\n fenceChar = '`';\n fenceLen = bt[1].length;\n return true;\n }\n const td = TILDE_OPEN.exec(line);\n if (td) {\n inFence = true;\n fenceChar = '~';\n fenceLen = td[1].length;\n return true;\n }\n return false;\n }\n const run = fenceChar === '`' ? /^(`+)(.*)$/ : /^(~+)(.*)$/;\n const m = run.exec(line);\n if (m && m[1].length >= fenceLen && m[2].trim() === '') {\n inFence = false;\n return true;\n }\n return false;\n },\n get inFence() {\n return inFence;\n },\n };\n}\n\n// Masks <!-- ... --> spans that may cross line boundaries, one line at a time so callers can\n// interleave it with their own per-line state. In isolation an unclosed <!-- stays open forever\n// (mask() has no notion of a line boundary that should kill it); maskRegions() below is what\n// calls close() at the point an unclosed comment actually dies -- a blank line at paragraph\n// level, or its enclosing HTML block's end.\nexport interface CommentTracker {\n mask(line: string): string;\n close(): void; // force-ends an unclosed comment (paragraph blank line, or its HTML block ending)\n readonly inComment: boolean;\n}\n\nexport function commentTracker(): CommentTracker {\n let inComment = false;\n return {\n mask(line: string): string {\n let out = '';\n let i = 0;\n while (i < line.length) {\n if (inComment) {\n const end = line.indexOf('-->', i);\n if (end === -1) {\n out += ' '.repeat(line.length - i);\n i = line.length;\n } else {\n out += ' '.repeat(end + 3 - i);\n i = end + 3;\n inComment = false;\n }\n continue;\n }\n const start = line.indexOf('<!--', i);\n if (start === -1) {\n out += line.slice(i);\n i = line.length;\n } else {\n out += `${line.slice(i, start)} `;\n i = start + 4;\n inComment = true;\n }\n }\n return out;\n },\n close() {\n inComment = false;\n },\n get inComment() {\n return inComment;\n },\n };\n}\n\n// CommonMark's HTML-block type-6 list (fixed by the spec, not a drifting enumeration): a line\n// starting with an open or close tag of one of these, at column 0 (leading whitespace/`>`\n// blockquote markers tolerated), opens a block that swallows following lines -- tags, links,\n// and comments alike -- until a blank line closes it.\nconst HTML_BLOCK_TAGS = new Set([\n 'address',\n 'article',\n 'aside',\n 'base',\n 'basefont',\n 'blockquote',\n 'body',\n 'caption',\n 'center',\n 'col',\n 'colgroup',\n 'dd',\n 'details',\n 'dialog',\n 'dir',\n 'div',\n 'dl',\n 'dt',\n 'fieldset',\n 'figcaption',\n 'figure',\n 'footer',\n 'form',\n 'frame',\n 'frameset',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'head',\n 'header',\n 'hr',\n 'html',\n 'iframe',\n 'legend',\n 'li',\n 'link',\n 'main',\n 'menu',\n 'menuitem',\n 'nav',\n 'noframes',\n 'ol',\n 'optgroup',\n 'option',\n 'p',\n 'param',\n 'search',\n 'section',\n 'summary',\n 'table',\n 'tbody',\n 'td',\n 'tfoot',\n 'th',\n 'thead',\n 'title',\n 'tr',\n 'track',\n 'ul',\n]);\n// Type-1 blocks (script/pre/style/textarea): closes on the line holding the matching end tag,\n// not on a blank line, and that line is the last one swallowed.\nconst HTML_PRE_TAGS = new Set(['script', 'pre', 'style', 'textarea']);\nconst HTML_PRE_CLOSE_RE = /<\\/(?:script|pre|style|textarea)>/i; // any of the four closers ends the block, not only the tag that opened it\n// An opening or closing tag at column 0, tag name captured for the lookups above.\nconst HTML_BLOCK_OPEN_RE = /^<\\/?([a-zA-Z][a-zA-Z0-9]*)(?:[ \\t]|\\/?>|$)/;\nconst BLANK_LINE_RE = /^[ \\t>]*$/; // whitespace/blockquote-markers only -- a paragraph break, and what ends a type-6 block\n\n// Body with fenced-code, HTML-block, and <!-- --> comment regions replaced by spaces (newlines\n// preserved, so line numbers and offsets survive) plus inline code spans masked. The single\n// region masker for tags/links: fence and HTML-block delimiter+content lines are opaque, an\n// unclosed comment dies at its containing block's end (or the next blank line at paragraph\n// level -- never silently to end of file), and a closed comment masks exactly its span.\n// Bodies without a backtick/tilde/`<` fast-path out untouched.\nexport function maskRegions(body: string): string {\n if (!/[`~<]/.test(body)) return body;\n const fence = fenceTracker();\n const comment = commentTracker();\n let inHtmlBlock = false;\n let htmlBlockClose: RegExp | null = null; // set while inside a type-1 (script/pre/style/textarea) block\n return body\n .split('\\n')\n .map((line) => {\n if (inHtmlBlock) {\n if (htmlBlockClose) {\n if (htmlBlockClose.test(line)) {\n inHtmlBlock = false;\n htmlBlockClose = null;\n }\n return ' '.repeat(line.length);\n }\n if (BLANK_LINE_RE.test(line)) {\n // Block content never feeds the comment tracker, so an inner <!-- was only ever\n // masked text; nothing to close here.\n inHtmlBlock = false;\n return line;\n }\n return ' '.repeat(line.length);\n }\n if (!comment.inComment) {\n const isDelim = fence.feed(line);\n if (isDelim || fence.inFence) return ' '.repeat(line.length);\n }\n const uncommented = comment.inComment || line.includes('<!--') ? comment.mask(line) : line;\n if (comment.inComment && BLANK_LINE_RE.test(line)) comment.close(); // paragraph-level: dies at the next blank line\n // Indented or blockquoted HTML blocks still swallow their content in Obsidian, so the\n // opener test runs after stripping leading whitespace and > markers.\n const stripped = uncommented.replace(/^[ \\t>]*/, '');\n if (stripped[0] === '<') {\n const openMatch = HTML_BLOCK_OPEN_RE.exec(stripped);\n if (openMatch) {\n const tagName = openMatch[1].toLowerCase();\n const isClosingTag = stripped[1] === '/';\n if (!isClosingTag && HTML_PRE_TAGS.has(tagName)) {\n // The end condition can be met on the opening line itself: <script>x</script>\n // is a one-line block and the next line parses (Obsidian-verified).\n if (!HTML_PRE_CLOSE_RE.test(stripped.slice(openMatch[0].length))) {\n inHtmlBlock = true;\n htmlBlockClose = HTML_PRE_CLOSE_RE;\n }\n return ' '.repeat(line.length);\n }\n if (HTML_BLOCK_TAGS.has(tagName)) {\n inHtmlBlock = true;\n return ' '.repeat(line.length);\n }\n }\n }\n // Inline code spans hide their content too: `[[x]]` in prose is not a link.\n return uncommented.includes('`') ? maskCodeSpans(uncommented) : uncommented;\n })\n .join('\\n');\n}\n\n// A code span opens on a run of N backticks and closes at the next run of exactly N -- a\n// shorter or longer run in between is literal text, not a delimiter (CommonMark code spans).\n// Masked with spaces so column positions and tag-boundary whitespace are unaffected.\nexport function maskCodeSpans(line: string): string {\n let out = '';\n let i = 0;\n while (i < line.length) {\n if (line[i] !== '`') {\n out += line[i];\n i++;\n continue;\n }\n let j = i;\n while (line[j] === '`') j++;\n const n = j - i;\n let k = j;\n let closeStart = -1;\n let closeEnd = -1;\n while (k < line.length) {\n if (line[k] !== '`') {\n k++;\n continue;\n }\n let m = k;\n while (line[m] === '`') m++;\n if (m - k === n) {\n closeStart = k;\n closeEnd = m;\n break;\n }\n k = m;\n }\n if (closeStart >= 0) {\n out += ' '.repeat(closeEnd - i);\n i = closeEnd;\n } else {\n out += line.slice(i, j);\n i = j;\n }\n }\n return out;\n}\n"],"names":["commentTracker","fenceTracker","maskCodeSpans","maskRegions","BACKTICK_OPEN","TILDE_OPEN","inFence","fenceChar","fenceLen","feed","line","bt","exec","includes","length","td","run","m","trim","inComment","mask","out","i","end","indexOf","repeat","start","slice","close","HTML_BLOCK_TAGS","Set","HTML_PRE_TAGS","HTML_PRE_CLOSE_RE","HTML_BLOCK_OPEN_RE","BLANK_LINE_RE","body","test","fence","comment","inHtmlBlock","htmlBlockClose","split","map","isDelim","uncommented","stripped","replace","openMatch","tagName","toLowerCase","isClosingTag","has","join","j","n","k","closeStart","closeEnd"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/graph.ts"],"sourcesContent":["// Link-graph math: PageRank at reconcile, personalized PageRank at query time. Pure JS, no deps.\n\nexport type Edge = [src: string, dst: string];\n\n// Power iteration. `personal` biases both teleport and dangling mass toward seed nodes;\n// without it this is plain PageRank (uniform base). Returns scores summing to ~1.\nexport function pagerank(nodes: string[], edges: Edge[], opts: { damping?: number; iterations?: number; personal?: Map<string, number> } = {}): Map<string, number> {\n const damping = opts.damping ?? 0.85;\n const iterations = opts.iterations ?? 30;\n const n = nodes.length;\n if (n === 0) return new Map();\n\n const index = new Map(nodes.map((node, i) => [node, i]));\n const out: number[][] = nodes.map(() => []);\n for (const [src, dst] of edges) {\n const si = index.get(src);\n const di = index.get(dst);\n if (si !== undefined && di !== undefined) out[si].push(di);\n }\n\n let base: number[];\n if (opts.personal) {\n base = nodes.map(() => 0);\n let total = 0;\n for (const [node, weight] of opts.personal) {\n const i = index.get(node);\n if (i !== undefined && weight > 0) {\n base[i] = weight;\n total += weight;\n }\n }\n if (total === 0) return new Map(nodes.map((node) => [node, 0]));\n base = base.map((b) => b / total);\n } else {\n base = nodes.map(() => 1 / n);\n }\n\n let rank = [...base];\n for (let iter = 0; iter < iterations; iter++) {\n const next = base.map((b) => (1 - damping) * b);\n let dangling = 0;\n for (let i = 0; i < n; i++) {\n if (out[i].length === 0) {\n dangling += rank[i];\n continue;\n }\n const share = (damping * rank[i]) / out[i].length;\n for (const j of out[i]) next[j] += share;\n }\n for (let i = 0; i < n; i++) next[i] += damping * dangling * base[i];\n rank = next;\n }\n return new Map(nodes.map((node, i) => [node, rank[i]]));\n}\n\n// Connective expansion: walk the graph (undirected -- backlinks relate as much as links)\n// from a seed result set. Answers \"what is linked to the notes that matched\".\nexport function personalizedRank(nodes: string[], edges: Edge[], seeds: Map<string, number>): Map<string, number> {\n const undirected: Edge[] = [];\n for (const [src, dst] of edges) {\n undirected.push([src, dst], [dst, src]);\n }\n return pagerank(nodes, undirected, { damping: 0.7, iterations: 15, personal: seeds });\n}\n"],"names":["pagerank","personalizedRank","nodes","edges","opts","damping","iterations","n","length","Map","index","map","node","i","out","src","dst","si","get","di","undefined","push","base","personal","total","weight","b","rank","iter","next","dangling","share","j","seeds","undirected"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/output.ts"],"sourcesContent":["// rows -> table (default) | json | csv\n\nexport type Row = Record<string, unknown>;\n\n// map/peek/status/path render structures rather than a row set, so csv has nothing to mean\n// there; the commands that emit rows take RowFormat.\nexport type Format = 'table' | 'json';\nexport type RowFormat = Format | 'csv';\n\n// Warned about on stderr (keeps --format json stdout machine-readable), never truncated.\nconst OVERSIZE_BYTES = 50_000;\n\n// Flatten embedded newlines so they can't break table column alignment; JSON output is left alone.\nfunction cell(value: unknown): string {\n return String(value ?? '').replace(/\\s*\\n\\s*/g, ' ');\n}\n\n// RFC 4180, and deliberately not cell(): csv is the format for redirecting a result to a\n// file, so it keeps every character, embedded newlines included. What it cannot carry is\n// NULL vs empty string, or a value's type -- that is what json is for.\nfunction csvField(value: unknown): string {\n const text = value === null || value === undefined ? '' : String(value);\n return /[\"\\r\\n,]/.test(text) ? `\"${text.replace(/\"/g, '\"\"')}\"` : text;\n}\n\nfunction csvLine(values: unknown[]): string {\n return values.map(csvField).join(',');\n}\n\nfunction warnOversize(bytes: number, rowCount: number): void {\n if (bytes <= OVERSIZE_BYTES) return;\n console.warn(`warning: result is ${Math.round(bytes / 1000)} KB across ${rowCount} row(s); consider a LIMIT, fewer columns, snippet() instead of whole values, or --format csv redirected to a file`);\n}\n\n// Header names come from a row wherever there is one: a statement's column list keeps\n// duplicates that the row object has already collapsed, so `SELECT a AS x, b AS x` would print\n// b's value under both headers. `columns` is the fallback that labels a 0-row result, and with\n// no rows and no statement (a bounded command that found nothing) csv writes nothing at all --\n// a bare newline would read to a csv parser as one empty record.\nexport function printRows(rows: Row[], format: RowFormat, columns?: string[]): void {\n if (format === 'csv') {\n // Collapsed the same way a row object collapses them, so a statement naming a column\n // twice describes itself identically whether it matched anything or not.\n const names = rows.length > 0 ? Object.keys(rows[0]) : [...new Set(columns ?? [])];\n if (names.length === 0) return;\n const rendered = [csvLine(names), ...rows.map((row) => csvLine(names.map((name) => row[name])))].join('\\n');\n console.log(rendered);\n // Bytes, not code units -- CJK is 3 bytes per character.\n warnOversize(Buffer.byteLength(rendered), rows.length);\n return;\n }\n const rendered = renderRows(rows, format);\n console.log(rendered);\n warnOversize(Buffer.byteLength(rendered), rows.length);\n}\n\n// Streaming counterpart for the one unbounded caller, `sense sql`: rows arrive from an\n// iterator, so a large result is never held here as rows and again as a rendered string.\n// Table buffers by necessity (a column is as wide as its widest cell, which the last row can\n// change); json and csv write row by row. The writes are synchronous, so when stdout is a pipe\n// Node buffers what the reader has not taken yet -- the saving is this module's copies, not\n// the operating system's.\nexport function printRowStream(rows: Iterable<Row>, format: RowFormat, columns: string[]): void {\n const iterator = rows[Symbol.iterator]();\n // One step before any write. FTS5 parses a MATCH expression at step time rather than at\n // prepare time, so a bad search string throws here, with stdout still clean for the error.\n const first = iterator.next();\n const rest: Iterable<Row> = { [Symbol.iterator]: () => iterator };\n\n if (format === 'table') {\n printRows(first.done ? [] : [first.value, ...rest], format, columns);\n return;\n }\n\n let bytes = 0;\n let rowCount = 0;\n const write = (text: string): void => {\n // Bytes, not code units -- CJK is 3 bytes per character.\n bytes += Buffer.byteLength(text);\n process.stdout.write(text);\n };\n\n if (format === 'json') {\n // Byte-identical to JSON.stringify(rows, null, 2) + newline: each row re-indented one\n // level, comma-joined, inside the array brackets written here.\n // JSON.stringify throws on BigInt, so a row with an int64 past 2^53 (setReadBigInts) is\n // converted via the replacer: a value that fits a safe integer stays a number, a larger one\n // becomes its decimal string, since a JSON number cannot carry it losslessly.\n const MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);\n const bigintSafe = (_key: string, value: unknown) => (typeof value === 'bigint' ? (value >= -MAX_SAFE && value <= MAX_SAFE ? Number(value) : value.toString()) : value);\n const indent = (row: Row) =>\n JSON.stringify(row, bigintSafe, 2)\n .split('\\n')\n .map((line) => ` ${line}`)\n .join('\\n');\n if (first.done) {\n write('[]\\n');\n } else {\n write('[\\n');\n write(indent(first.value));\n rowCount = 1;\n for (const row of rest) {\n write(',\\n');\n write(indent(row));\n rowCount++;\n }\n write('\\n]\\n');\n }\n } else if (first.done) {\n const names = [...new Set(columns)];\n if (names.length > 0) write(`${csvLine(names)}\\n`);\n } else {\n const names = Object.keys(first.value);\n write(`${csvLine(names)}\\n`);\n write(`${csvLine(names.map((name) => first.value[name]))}\\n`);\n rowCount = 1;\n for (const row of rest) {\n write(`${csvLine(names.map((name) => row[name]))}\\n`);\n rowCount++;\n }\n }\n warnOversize(bytes, rowCount);\n}\n\n// Tables are for reading, and a row wider than the terminal wraps unreadably: widest columns\n// give up space first, down to a floor. --format json is never truncated.\nconst MIN_COLUMN = 12;\nconst TRUNCATED = '…';\n\nfunction fitWidths(widths: number[], limit: number): number[] {\n const gaps = (widths.length - 1) * 2;\n const fitted = [...widths];\n for (;;) {\n const total = fitted.reduce((a, b) => a + b, 0) + gaps;\n if (total <= limit) return fitted;\n const widest = fitted.indexOf(Math.max(...fitted));\n if (fitted[widest] <= MIN_COLUMN) return fitted;\n fitted[widest] = Math.max(MIN_COLUMN, fitted[widest] - Math.max(1, total - limit));\n }\n}\n\nfunction renderRows(rows: Row[], format: Format, width = process.stdout.columns): string {\n if (format === 'json') return JSON.stringify(rows, null, 2);\n if (rows.length === 0) return '(0 rows)';\n\n const columns = Object.keys(rows[0]);\n const cells = rows.map((row) => columns.map((col) => cell(row[col])));\n const natural = columns.map((col, i) => Math.max(col.length, ...cells.map((row) => row[i].length)));\n const widths = width && width > MIN_COLUMN ? fitWidths(natural, width) : natural;\n\n const clip = (value: string, w: number) => (value.length <= w ? value.padEnd(w) : `${value.slice(0, w - 1)}${TRUNCATED}`);\n const formatRow = (values: string[]) =>\n values\n .map((value, i) => clip(value, widths[i]))\n .join(' ')\n .trimEnd();\n\n return [formatRow(columns), widths.map((w) => '-'.repeat(w)).join(' '), ...cells.map(formatRow)].join('\\n');\n}\n\n// Text renderers for the top-level commands; cli.ts prints what these return.\n\n// Names the config key that turns a feature back on. Only the three features-block toggles\n// reach here; `embed` has its own status line.\nexport function featureOffHint(name: string): string {\n return `features.${name}`;\n}\n\nexport function featuresLine(features: { on: string[]; off: string[] }): string {\n const off = features.off.length > 0 ? ` · off: ${features.off.map((name) => `${name} (${featureOffHint(name)})`).join(', ')}` : '';\n return `features: ${features.on.join(', ')}${off}`;\n}\n\n// name, or name:weight when the weight is not the default 1.\nfunction signalLabels(signals: Record<string, number>): string {\n return Object.entries(signals)\n .map(([name, weight]) => (weight === 1 ? name : `${name}:${weight}`))\n .join(', ');\n}\n\nexport function presetsLines(presets: Array<{ name: string; files: number; embedded: number; signals: Record<string, number> }>): string[] {\n // \"0 embedded\" is ambiguous between a scope that declined vectors and one that has not built\n // them yet, so a preset without the vectors signal says what it uses instead.\n return ['presets:', ...presets.map((p) => ` ${p.name}: ${p.files} file(s), ${p.embedded} embedded${p.signals.vectors !== undefined ? '' : ` (signals: ${signalLabels(p.signals)})`}`)];\n}\n\nexport function renderMap(result: {\n docs: { count: number; bytes: number };\n fields: Row[];\n fieldsTotal: number;\n features: { on: string[]; off: string[] };\n presets: Array<{ name: string; files: number; embedded: number; signals: Record<string, number> }>;\n hubs: Row[];\n recent: Row[];\n recentCaveat: string | null;\n}): string {\n const parts = [`docs: ${result.docs.count} (${Math.round(result.docs.bytes / 1024)} KB)`, featuresLine(result.features), '', ...presetsLines(result.presets), '', renderRows(result.fields, 'table')];\n if (result.fieldsTotal > result.fields.length) parts.push(`(+${result.fieldsTotal - result.fields.length} more fields)`);\n if (result.hubs.length > 0) parts.push('\\nhubs (by link rank):', renderRows(result.hubs, 'table'));\n else if (result.features.off.includes('rank')) parts.push(`\\nhubs: off (${featureOffHint('rank')})`);\n parts.push('\\nrecent:');\n if (result.recentCaveat) parts.push(result.recentCaveat);\n parts.push(renderRows(result.recent, 'table'));\n return parts.join('\\n');\n}\n\nexport function renderPeek(result: { path: string; tokens: number; frontmatter: Row; parseError?: string | null; sections: Row[]; outbound: string[]; backlinks: string[]; unresolved: string[]; sectionsTotal: number; outboundTotal: number; backlinksTotal: number; unresolvedTotal: number; off: string[] }): string {\n const lines = [`${result.path} (~${result.tokens} tokens)`];\n // Otherwise a refused parse is indistinguishable from a note that has no frontmatter, which\n // is the confusion the whole quarantine design exists to remove.\n if (result.parseError) lines.push(` frontmatter: did not parse, so none of it is indexed (${result.parseError})`);\n for (const [key, value] of Object.entries(result.frontmatter)) lines.push(` ${key}: ${value}`);\n if (result.sections.length > 0) {\n lines.push('', 'sections:');\n for (const s of result.sections) lines.push(` ${'#'.repeat(s.level as number)} ${s.heading} [L${s.start_line}-${s.end_line}, ~${s.tokens}t]`);\n if (result.sectionsTotal > result.sections.length) lines.push(` (+${result.sectionsTotal - result.sections.length} more sections -- sections table has all of them)`);\n } else if (result.off.includes('sections')) lines.push('', 'sections: off (features.sections)');\n if (result.off.includes('links')) {\n lines.push('', 'links: off (features.links)');\n } else {\n const linkLine = (label: string, shown: string[], total: number) => {\n if (total > 0) lines.push(`${label} (${total}): ${shown.join(', ')}${total > shown.length ? `, +${total - shown.length} more` : ''}`);\n };\n if (result.outboundTotal + result.unresolvedTotal + result.backlinksTotal > 0) lines.push('');\n linkLine('links out', result.outbound, result.outboundTotal);\n linkLine('unresolved', result.unresolved, result.unresolvedTotal);\n linkLine('backlinks', result.backlinks, result.backlinksTotal);\n }\n return lines.join('\\n');\n}\n"],"names":["featureOffHint","featuresLine","presetsLines","printRowStream","printRows","renderMap","renderPeek","OVERSIZE_BYTES","cell","value","String","replace","csvField","text","undefined","test","csvLine","values","map","join","warnOversize","bytes","rowCount","console","warn","Math","round","rows","format","columns","names","length","Object","keys","Set","rendered","row","name","log","Buffer","byteLength","renderRows","iterator","Symbol","first","next","rest","done","write","process","stdout","MAX_SAFE","BigInt","Number","MAX_SAFE_INTEGER","bigintSafe","_key","toString","indent","JSON","stringify","split","line","MIN_COLUMN","TRUNCATED","fitWidths","widths","limit","gaps","fitted","total","reduce","a","b","widest","indexOf","max","width","cells","col","natural","i","clip","w","padEnd","slice","formatRow","trimEnd","repeat","features","off","on","signalLabels","signals","entries","weight","presets","p","files","embedded","vectors","result","parts","docs","count","fields","fieldsTotal","push","hubs","includes","recentCaveat","recent","lines","path","tokens","parseError","frontmatter","key","sections","s","level","heading","start_line","end_line","sectionsTotal","linkLine","label","shown","outboundTotal","unresolvedTotal","backlinksTotal","outbound","unresolved","backlinks"],"mappings":"AAAA,uCAAuC;;;;;;;;;;;;QAoKvBA;eAAAA;;QAIAC;eAAAA;;QAYAC;eAAAA;;QAtHAC;eAAAA;;QAvBAC;eAAAA;;QAmJAC;eAAAA;;QAoBAC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AArMhB,yFAAyF;AACzF,IAAMC,iBAAiB;AAEvB,mGAAmG;AACnG,SAASC,KAAKC,KAAc;IAC1B,OAAOC,OAAOD,kBAAAA,mBAAAA,QAAS,IAAIE,OAAO,CAAC,aAAa;AAClD;AAEA,yFAAyF;AACzF,yFAAyF;AACzF,uEAAuE;AACvE,SAASC,SAASH,KAAc;IAC9B,IAAMI,OAAOJ,UAAU,QAAQA,UAAUK,YAAY,KAAKJ,OAAOD;IACjE,OAAO,WAAWM,IAAI,CAACF,QAAQ,AAAC,IAA4B,OAAzBA,KAAKF,OAAO,CAAC,MAAM,OAAM,OAAKE;AACnE;AAEA,SAASG,QAAQC,MAAiB;IAChC,OAAOA,OAAOC,GAAG,CAACN,UAAUO,IAAI,CAAC;AACnC;AAEA,SAASC,aAAaC,KAAa,EAAEC,QAAgB;IACnD,IAAID,SAASd,gBAAgB;IAC7BgB,QAAQC,IAAI,CAAC,AAAC,sBAA2DF,OAAtCG,KAAKC,KAAK,CAACL,QAAQ,OAAM,eAAsB,OAATC,UAAS;AACpF;AAOO,SAASlB,UAAUuB,IAAW,EAAEC,MAAiB,EAAEC,OAAkB;IAC1E,IAAID,WAAW,OAAO;QACpB,qFAAqF;QACrF,yEAAyE;QACzE,IAAME,QAAQH,KAAKI,MAAM,GAAG,IAAIC,OAAOC,IAAI,CAACN,IAAI,CAAC,EAAE,IAAK,qBAAG,IAAIO,IAAIL,oBAAAA,qBAAAA,UAAW,EAAE;QAChF,IAAIC,MAAMC,MAAM,KAAK,GAAG;QACxB,IAAMI,WAAW;YAACnB,QAAQc;SAAsE,CAA/E,OAAiB,qBAAGH,KAAKT,GAAG,CAAC,SAACkB;mBAAQpB,QAAQc,MAAMZ,GAAG,CAAC,SAACmB;uBAASD,GAAG,CAACC,KAAK;;aAAKlB,IAAI,CAAC;QACtGI,QAAQe,GAAG,CAACH;QACZ,yDAAyD;QACzDf,aAAamB,OAAOC,UAAU,CAACL,WAAWR,KAAKI,MAAM;QACrD;IACF;IACA,IAAMI,YAAWM,WAAWd,MAAMC;IAClCL,QAAQe,GAAG,CAACH;IACZf,aAAamB,OAAOC,UAAU,CAACL,YAAWR,KAAKI,MAAM;AACvD;AAQO,SAAS5B,eAAewB,IAAmB,EAAEC,MAAiB,EAAEC,OAAiB;IACtF,IAAMa,WAAWf,IAAI,CAACgB,OAAOD,QAAQ,CAAC;IACtC,wFAAwF;IACxF,2FAA2F;IAC3F,IAAME,QAAQF,SAASG,IAAI;IAC3B,IAAMC,OAAwB,qBAACH,OAAOD,QAAQ,EAAG;eAAMA;;IAEvD,IAAId,WAAW,SAAS;QACtBxB,UAAUwC,MAAMG,IAAI,GAAG,EAAE,GAAG;YAACH,MAAMnC,KAAK;SAAU,CAAtB,OAAc,qBAAGqC,QAAOlB,QAAQC;QAC5D;IACF;IAEA,IAAIR,QAAQ;IACZ,IAAIC,WAAW;IACf,IAAM0B,QAAQ,eAACnC;QACb,yDAAyD;QACzDQ,SAASkB,OAAOC,UAAU,CAAC3B;QAC3BoC,QAAQC,MAAM,CAACF,KAAK,CAACnC;IACvB;IAEA,IAAIe,WAAW,QAAQ;QACrB,sFAAsF;QACtF,+DAA+D;QAC/D,wFAAwF;QACxF,4FAA4F;QAC5F,8EAA8E;QAC9E,IAAMuB,WAAWC,OAAOC,OAAOC,gBAAgB;QAC/C,IAAMC,aAAa,oBAACC,MAAc/C;mBAAoB,CAAA,OAAOA,sCAAP,SAAOA,MAAI,MAAM,WAAYA,SAAS,CAAC0C,YAAY1C,SAAS0C,WAAWE,OAAO5C,SAASA,MAAMgD,QAAQ,KAAMhD;;QACjK,IAAMiD,SAAS,gBAACtB;mBACduB,KAAKC,SAAS,CAACxB,KAAKmB,YAAY,GAC7BM,KAAK,CAAC,MACN3C,GAAG,CAAC,SAAC4C;uBAAS,AAAC,KAAS,OAALA;eACnB3C,IAAI,CAAC;;QACV,IAAIyB,MAAMG,IAAI,EAAE;YACdC,MAAM;QACR,OAAO;YACLA,MAAM;YACNA,MAAMU,OAAOd,MAAMnC,KAAK;YACxBa,WAAW;gBACN,kCAAA,2BAAA;;gBAAL,QAAK,YAAawB,yBAAb,SAAA,6BAAA,QAAA,yBAAA,iCAAmB;oBAAnB,IAAMV,MAAN;oBACHY,MAAM;oBACNA,MAAMU,OAAOtB;oBACbd;gBACF;;gBAJK;gBAAA;;;yBAAA,6BAAA;wBAAA;;;wBAAA;8BAAA;;;;YAKL0B,MAAM;QACR;IACF,OAAO,IAAIJ,MAAMG,IAAI,EAAE;QACrB,IAAMjB,QAAS,qBAAG,IAAII,IAAIL;QAC1B,IAAIC,MAAMC,MAAM,GAAG,GAAGiB,MAAM,AAAC,GAAiB,OAAfhC,QAAQc,QAAO;IAChD,OAAO;QACL,IAAMA,SAAQE,OAAOC,IAAI,CAACW,MAAMnC,KAAK;QACrCuC,MAAM,AAAC,GAAiB,OAAfhC,QAAQc,SAAO;QACxBkB,MAAM,AAAC,GAAkD,OAAhDhC,QAAQc,OAAMZ,GAAG,CAAC,SAACmB;mBAASO,MAAMnC,KAAK,CAAC4B,KAAK;aAAG;QACzDf,WAAW;YACN,mCAAA,4BAAA;;;gBAAA,IAAMc,MAAN;gBACHY,MAAM,AAAC,GAA0C,OAAxChC,QAAQc,OAAMZ,GAAG,CAAC,SAACmB;2BAASD,GAAG,CAACC,KAAK;qBAAG;gBACjDf;YACF;YAHA,QAAK,aAAawB,yBAAb,UAAA,8BAAA,SAAA,0BAAA;;YAAA;YAAA;;;qBAAA,8BAAA;oBAAA;;;oBAAA;0BAAA;;;;IAIP;IACA1B,aAAaC,OAAOC;AACtB;AAEA,6FAA6F;AAC7F,0EAA0E;AAC1E,IAAMyC,aAAa;AACnB,IAAMC,YAAY;AAElB,SAASC,UAAUC,MAAgB,EAAEC,KAAa;IAChD,IAAMC,OAAO,AAACF,CAAAA,OAAOnC,MAAM,GAAG,CAAA,IAAK;IACnC,IAAMsC,SAAU,qBAAGH;IACnB,OAAS;YAGuBzC;QAF9B,IAAM6C,QAAQD,OAAOE,MAAM,CAAC,SAACC,GAAGC;mBAAMD,IAAIC;WAAG,KAAKL;QAClD,IAAIE,SAASH,OAAO,OAAOE;QAC3B,IAAMK,SAASL,OAAOM,OAAO,CAAClD,CAAAA,QAAAA,MAAKmD,GAAG,OAARnD,OAAS,qBAAG4C;QAC1C,IAAIA,MAAM,CAACK,OAAO,IAAIX,YAAY,OAAOM;QACzCA,MAAM,CAACK,OAAO,GAAGjD,KAAKmD,GAAG,CAACb,YAAYM,MAAM,CAACK,OAAO,GAAGjD,KAAKmD,GAAG,CAAC,GAAGN,QAAQH;IAC7E;AACF;AAEA,SAAS1B,WAAWd,IAAW,EAAEC,MAAc;QAAEiD,QAAAA,iEAAQ5B,QAAQC,MAAM,CAACrB,OAAO;QAMrCJ;IALxC,IAAIG,WAAW,QAAQ,OAAO+B,KAAKC,SAAS,CAACjC,MAAM,MAAM;IACzD,IAAIA,KAAKI,MAAM,KAAK,GAAG,OAAO;IAE9B,IAAMF,UAAUG,OAAOC,IAAI,CAACN,IAAI,CAAC,EAAE;IACnC,IAAMmD,QAAQnD,KAAKT,GAAG,CAAC,SAACkB;eAAQP,QAAQX,GAAG,CAAC,SAAC6D;mBAAQvE,KAAK4B,GAAG,CAAC2C,IAAI;;;IAClE,IAAMC,UAAUnD,QAAQX,GAAG,CAAC,SAAC6D,KAAKE;eAAMxD,CAAAA,QAAAA,MAAKmD,GAAG,OAARnD,OAAAA;YAASsD,IAAIhD,MAAM;SAAuC,CAA1DN,OAAqB,qBAAGqD,MAAM5D,GAAG,CAAC,SAACkB;mBAAQA,GAAG,CAAC6C,EAAE,CAAClD,MAAM;;;IAChG,IAAMmC,SAASW,SAASA,QAAQd,aAAaE,UAAUe,SAASH,SAASG;IAEzE,IAAME,OAAO,cAACzE,OAAe0E;eAAe1E,MAAMsB,MAAM,IAAIoD,IAAI1E,MAAM2E,MAAM,CAACD,KAAK,AAAC,GAA0BnB,OAAxBvD,MAAM4E,KAAK,CAAC,GAAGF,IAAI,IAAe,OAAVnB;;IAC7G,IAAMsB,YAAY,mBAACrE;eACjBA,OACGC,GAAG,CAAC,SAACT,OAAOwE;mBAAMC,KAAKzE,OAAOyD,MAAM,CAACe,EAAE;WACvC9D,IAAI,CAAC,MACLoE,OAAO;;IAEZ,OAAO;QAACD,UAAUzD;QAAUqC,OAAOhD,GAAG,CAAC,SAACiE;mBAAM,IAAIK,MAAM,CAACL;WAAIhE,IAAI,CAAC;KAA+B,CAA1F,OAAkE,qBAAG2D,MAAM5D,GAAG,CAACoE,aAAYnE,IAAI,CAAC;AACzG;AAMO,SAASnB,eAAeqC,IAAY;IACzC,OAAO,AAAC,YAAgB,OAALA;AACrB;AAEO,SAASpC,aAAawF,QAAyC;IACpE,IAAMC,MAAMD,SAASC,GAAG,CAAC3D,MAAM,GAAG,IAAI,AAAC,cAAqF,OAA3E0D,SAASC,GAAG,CAACxE,GAAG,CAAC,SAACmB;eAAS,AAAC,GAAWrC,OAATqC,MAAK,MAAyB,OAArBrC,eAAeqC,OAAM;OAAIlB,IAAI,CAAC,SAAU;IAChI,OAAO,AAAC,aAAqCuE,OAAzBD,SAASE,EAAE,CAACxE,IAAI,CAAC,OAAY,OAAJuE;AAC/C;AAEA,6DAA6D;AAC7D,SAASE,aAAaC,OAA+B;IACnD,OAAO7D,OAAO8D,OAAO,CAACD,SACnB3E,GAAG,CAAC;iDAAEmB,kBAAM0D;eAAaA,WAAW,IAAI1D,OAAO,AAAC,GAAU0D,OAAR1D,MAAK,KAAU,OAAP0D;OAC1D5E,IAAI,CAAC;AACV;AAEO,SAASjB,aAAa8F,OAAkG;IAC7H,6FAA6F;IAC7F,8EAA8E;IAC9E,OAAO;QAAC;KAA+K,CAAhL,OAAa,qBAAGA,QAAQ9E,GAAG,CAAC,SAAC+E;eAAM,AAAC,KAAeA,OAAXA,EAAE5D,IAAI,EAAC,MAAwB4D,OAApBA,EAAEC,KAAK,EAAC,cAAkCD,OAAtBA,EAAEE,QAAQ,EAAC,aAA2F,OAAhFF,EAAEJ,OAAO,CAACO,OAAO,KAAKtF,YAAY,KAAK,AAAC,cAAqC,OAAxB8E,aAAaK,EAAEJ,OAAO,GAAE;;AACnL;AAEO,SAASxF,UAAUgG,MASzB;IACC,IAAMC,QAAQ;QAAE,SAA8B7E,OAAtB4E,OAAOE,IAAI,CAACC,KAAK,EAAC,MAAyC,OAArC/E,KAAKC,KAAK,CAAC2E,OAAOE,IAAI,CAAClF,KAAK,GAAG,OAAM;QAAOpB,aAAaoG,OAAOZ,QAAQ;QAAG;KAA4E,CAAvL,OAA+G,qBAAGvF,aAAamG,OAAOL,OAAO,IAA7I;QAAgJ;QAAIvD,WAAW4D,OAAOI,MAAM,EAAE;KAAS;IACrM,IAAIJ,OAAOK,WAAW,GAAGL,OAAOI,MAAM,CAAC1E,MAAM,EAAEuE,MAAMK,IAAI,CAAC,AAAC,KAA8C,OAA1CN,OAAOK,WAAW,GAAGL,OAAOI,MAAM,CAAC1E,MAAM,EAAC;IACzG,IAAIsE,OAAOO,IAAI,CAAC7E,MAAM,GAAG,GAAGuE,MAAMK,IAAI,CAAC,0BAA0BlE,WAAW4D,OAAOO,IAAI,EAAE;SACpF,IAAIP,OAAOZ,QAAQ,CAACC,GAAG,CAACmB,QAAQ,CAAC,SAASP,MAAMK,IAAI,CAAC,AAAC,gBAAsC,OAAvB3G,eAAe,SAAQ;IACjGsG,MAAMK,IAAI,CAAC;IACX,IAAIN,OAAOS,YAAY,EAAER,MAAMK,IAAI,CAACN,OAAOS,YAAY;IACvDR,MAAMK,IAAI,CAAClE,WAAW4D,OAAOU,MAAM,EAAE;IACrC,OAAOT,MAAMnF,IAAI,CAAC;AACpB;AAEO,SAASb,WAAW+F,MAAoR;IAC7S,IAAMW,QAAQ;QAAE,GAAoBX,OAAlBA,OAAOY,IAAI,EAAC,QAAoB,OAAdZ,OAAOa,MAAM,EAAC;KAAU;IAC5D,4FAA4F;IAC5F,iEAAiE;IACjE,IAAIb,OAAOc,UAAU,EAAEH,MAAML,IAAI,CAAC,AAAC,2DAA4E,OAAlBN,OAAOc,UAAU,EAAC;QAC1G,kCAAA,2BAAA;;QAAL,QAAK,YAAsBnF,OAAO8D,OAAO,CAACO,OAAOe,WAAW,sBAAvD,SAAA,6BAAA,QAAA,yBAAA;YAAA,mCAAA,iBAAOC,sBAAK5G;YAA8CuG,MAAML,IAAI,CAAC,AAAC,KAAYlG,OAAR4G,KAAI,MAAU,OAAN5G;;;QAAlF;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IACL,IAAI4F,OAAOiB,QAAQ,CAACvF,MAAM,GAAG,GAAG;QAC9BiF,MAAML,IAAI,CAAC,IAAI;YACV,mCAAA,4BAAA;;YAAL,QAAK,aAAWN,OAAOiB,QAAQ,qBAA1B,UAAA,8BAAA,SAAA,0BAAA;gBAAA,IAAMC,IAAN;gBAA4BP,MAAML,IAAI,CAAC,AAAC,KAAqCY,OAAjC,IAAI/B,MAAM,CAAC+B,EAAEC,KAAK,GAAY,KAAmBD,OAAhBA,EAAEE,OAAO,EAAC,QAAsBF,OAAhBA,EAAEG,UAAU,EAAC,KAAmBH,OAAhBA,EAAEI,QAAQ,EAAC,OAAc,OAATJ,EAAEL,MAAM,EAAC;;;YAAtI;YAAA;;;qBAAA,8BAAA;oBAAA;;;oBAAA;0BAAA;;;;QACL,IAAIb,OAAOuB,aAAa,GAAGvB,OAAOiB,QAAQ,CAACvF,MAAM,EAAEiF,MAAML,IAAI,CAAC,AAAC,OAAoD,OAA9CN,OAAOuB,aAAa,GAAGvB,OAAOiB,QAAQ,CAACvF,MAAM,EAAC;IACrH,OAAO,IAAIsE,OAAOX,GAAG,CAACmB,QAAQ,CAAC,aAAaG,MAAML,IAAI,CAAC,IAAI;IAC3D,IAAIN,OAAOX,GAAG,CAACmB,QAAQ,CAAC,UAAU;QAChCG,MAAML,IAAI,CAAC,IAAI;IACjB,OAAO;QACL,IAAMkB,WAAW,kBAACC,OAAeC,OAAiBzD;YAChD,IAAIA,QAAQ,GAAG0C,MAAML,IAAI,CAAC,AAAC,GAAYrC,OAAVwD,OAAM,MAAeC,OAAXzD,OAAM,OAAwBA,OAAnByD,MAAM5G,IAAI,CAAC,OAAsE,OAA9DmD,QAAQyD,MAAMhG,MAAM,GAAG,AAAC,MAA0B,OAArBuC,QAAQyD,MAAMhG,MAAM,EAAC,WAAS;QAClI;QACA,IAAIsE,OAAO2B,aAAa,GAAG3B,OAAO4B,eAAe,GAAG5B,OAAO6B,cAAc,GAAG,GAAGlB,MAAML,IAAI,CAAC;QAC1FkB,SAAS,aAAaxB,OAAO8B,QAAQ,EAAE9B,OAAO2B,aAAa;QAC3DH,SAAS,cAAcxB,OAAO+B,UAAU,EAAE/B,OAAO4B,eAAe;QAChEJ,SAAS,aAAaxB,OAAOgC,SAAS,EAAEhC,OAAO6B,cAAc;IAC/D;IACA,OAAOlB,MAAM7F,IAAI,CAAC;AACpB"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/progress.ts"],"sourcesContent":["// Progress on stderr only, so it can never corrupt --format json. A TTY gets one\n// self-overwriting line; a pipe gets a few append-only ones, not redraw frames.\n\nconst NON_TTY_MILESTONES = 4;\n\nexport interface Progress {\n tick(done: number): void;\n finish(): void;\n}\n\n// `total` known upfront; `label` names the work (\"embedding notes\", \"reparsing files\").\n// Silent entirely below `threshold` -- short work needs no narration.\nexport function progress(label: string, total: number, threshold = 200): Progress {\n if (total < threshold) return { tick() {}, finish() {} };\n\n const started = Date.now();\n const isTTY = process.stderr.isTTY === true;\n let lastShown = 0;\n let wrote = false;\n\n const line = (done: number) => {\n const elapsed = (Date.now() - started) / 1000;\n // Estimate from observed rate, only once there is a rate to observe.\n const eta = done > 0 && done < total ? `, ~${Math.max(1, Math.round((elapsed / done) * (total - done)))}s left` : '';\n return `${label}: ${done}/${total}${eta}`;\n };\n\n return {\n tick(done: number) {\n if (isTTY) {\n process.stderr.write(`\\r${line(done)}`);\n wrote = true;\n return;\n }\n // Sparse milestones: first tick, then every 1/NON_TTY_MILESTONES of the total.\n if (done === lastShown) return;\n if (lastShown === 0 || done - lastShown >= total / NON_TTY_MILESTONES) {\n process.stderr.write(`${line(done)}\\n`);\n lastShown = done;\n wrote = true;\n }\n },\n finish() {\n if (!wrote) return;\n if (isTTY) process.stderr.write(`\\r${line(total)}\\n`);\n else if (lastShown < total) process.stderr.write(`${line(total)}\\n`);\n },\n };\n}\n"],"names":["progress","NON_TTY_MILESTONES","label","total","threshold","tick","finish","started","Date","now","isTTY","process","stderr","lastShown","wrote","line","done","elapsed","eta","Math","max","round","write"],"mappings":";;;;+BAYgBA;;;eAAAA;;;AAZhB,iFAAiF;AACjF,gFAAgF;AAEhF,IAAMC,qBAAqB;AASpB,SAASD,SAASE,KAAa,EAAEC,KAAa;QAAEC,YAAAA,iEAAY;IACjE,IAAID,QAAQC,WAAW,OAAO;QAAEC,MAAAA,SAAAA,QAAQ;QAAGC,QAAAA,SAAAA,UAAU;IAAE;IAEvD,IAAMC,UAAUC,KAAKC,GAAG;IACxB,IAAMC,QAAQC,QAAQC,MAAM,CAACF,KAAK,KAAK;IACvC,IAAIG,YAAY;IAChB,IAAIC,QAAQ;IAEZ,IAAMC,OAAO,cAACC;QACZ,IAAMC,UAAU,AAACT,CAAAA,KAAKC,GAAG,KAAKF,OAAM,IAAK;QACzC,qEAAqE;QACrE,IAAMW,MAAMF,OAAO,KAAKA,OAAOb,QAAQ,AAAC,MAAgE,OAA3DgB,KAAKC,GAAG,CAAC,GAAGD,KAAKE,KAAK,CAAC,AAACJ,UAAUD,OAASb,CAAAA,QAAQa,IAAG,KAAK,YAAU;QAClH,OAAO,AAAC,GAAYA,OAAVd,OAAM,MAAYC,OAARa,MAAK,KAAWE,OAARf,OAAY,OAAJe;IACtC;IAEA,OAAO;QACLb,MAAAA,SAAAA,KAAKW,IAAY;YACf,IAAIN,OAAO;gBACTC,QAAQC,MAAM,CAACU,KAAK,CAAC,AAAC,KAAe,OAAXP,KAAKC;gBAC/BF,QAAQ;gBACR;YACF;YACA,+EAA+E;YAC/E,IAAIE,SAASH,WAAW;YACxB,IAAIA,cAAc,KAAKG,OAAOH,aAAaV,QAAQF,oBAAoB;gBACrEU,QAAQC,MAAM,CAACU,KAAK,CAAC,AAAC,GAAa,OAAXP,KAAKC,OAAM;gBACnCH,YAAYG;gBACZF,QAAQ;YACV;QACF;QACAR,QAAAA,SAAAA;YACE,IAAI,CAACQ,OAAO;YACZ,IAAIJ,OAAOC,QAAQC,MAAM,CAACU,KAAK,CAAC,AAAC,KAAgB,OAAZP,KAAKZ,QAAO;iBAC5C,IAAIU,YAAYV,OAAOQ,QAAQC,MAAM,CAACU,KAAK,CAAC,AAAC,GAAc,OAAZP,KAAKZ,QAAO;QAClE;IACF;AACF"}
@@ -1,35 +0,0 @@
1
- import type { Config } from './config/index.js';
2
- import type { Feature } from './features/types.js';
3
- export declare const RESERVED_COLUMNS: Set<string>;
4
- export interface FileStat {
5
- relPath: string;
6
- absPath: string;
7
- mtimeMs: number;
8
- ctimeMs: number;
9
- size: number;
10
- presets: string[];
11
- embed: boolean;
12
- }
13
- export declare function toPosixPath(relPath: string, separator?: string): string;
14
- export declare function listFiles(cfg: Config, baseDir: string): FileStat[];
15
- export interface ParsedDoc {
16
- relPath: string;
17
- mtimeMs: number;
18
- ctimeMs: number;
19
- size: number;
20
- presets: string[];
21
- data: Record<string, string | number | bigint | null>;
22
- parseError: string | null;
23
- search: {
24
- title: string;
25
- summary: string;
26
- text: string;
27
- };
28
- extracted: Record<string, unknown>;
29
- }
30
- export declare function looksLikeDatetime(value: string): boolean;
31
- export declare function normalizeDate(value: string): string;
32
- export declare function parseFile(file: FileStat, extractors?: Feature[]): {
33
- doc: ParsedDoc;
34
- warnings: string[];
35
- };
@@ -1,35 +0,0 @@
1
- import type { Config } from './config/index.js';
2
- import type { Feature } from './features/types.js';
3
- export declare const RESERVED_COLUMNS: Set<string>;
4
- export interface FileStat {
5
- relPath: string;
6
- absPath: string;
7
- mtimeMs: number;
8
- ctimeMs: number;
9
- size: number;
10
- presets: string[];
11
- embed: boolean;
12
- }
13
- export declare function toPosixPath(relPath: string, separator?: string): string;
14
- export declare function listFiles(cfg: Config, baseDir: string): FileStat[];
15
- export interface ParsedDoc {
16
- relPath: string;
17
- mtimeMs: number;
18
- ctimeMs: number;
19
- size: number;
20
- presets: string[];
21
- data: Record<string, string | number | bigint | null>;
22
- parseError: string | null;
23
- search: {
24
- title: string;
25
- summary: string;
26
- text: string;
27
- };
28
- extracted: Record<string, unknown>;
29
- }
30
- export declare function looksLikeDatetime(value: string): boolean;
31
- export declare function normalizeDate(value: string): string;
32
- export declare function parseFile(file: FileStat, extractors?: Feature[]): {
33
- doc: ParsedDoc;
34
- warnings: string[];
35
- };