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
package/dist/cjs/scan.js DELETED
@@ -1,436 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- function _export(target, all) {
6
- for(var name in all)Object.defineProperty(target, name, {
7
- enumerable: true,
8
- get: Object.getOwnPropertyDescriptor(all, name).get
9
- });
10
- }
11
- _export(exports, {
12
- get RESERVED_COLUMNS () {
13
- return RESERVED_COLUMNS;
14
- },
15
- get listFiles () {
16
- return listFiles;
17
- },
18
- get looksLikeDatetime () {
19
- return looksLikeDatetime;
20
- },
21
- get normalizeDate () {
22
- return normalizeDate;
23
- },
24
- get parseFile () {
25
- return parseFile;
26
- },
27
- get toPosixPath () {
28
- return toPosixPath;
29
- }
30
- });
31
- var _nodefs = require("node:fs");
32
- var _nodepath = require("node:path");
33
- var _removemarkdown = /*#__PURE__*/ _interop_require_default(require("remove-markdown"));
34
- var _yaml = require("yaml");
35
- var _indexts = require("./config/index.js");
36
- function _array_like_to_array(arr, len) {
37
- if (len == null || len > arr.length) len = arr.length;
38
- for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
39
- return arr2;
40
- }
41
- function _array_with_holes(arr) {
42
- if (Array.isArray(arr)) return arr;
43
- }
44
- function _array_without_holes(arr) {
45
- if (Array.isArray(arr)) return _array_like_to_array(arr);
46
- }
47
- function _interop_require_default(obj) {
48
- return obj && obj.__esModule ? obj : {
49
- default: obj
50
- };
51
- }
52
- function _iterable_to_array(iter) {
53
- if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) {
54
- return Array.from(iter);
55
- }
56
- }
57
- function _iterable_to_array_limit(arr, i) {
58
- var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
59
- if (_i == null) return;
60
- var _arr = [];
61
- var _n = true;
62
- var _d = false;
63
- var _s, _e;
64
- try {
65
- for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
66
- _arr.push(_s.value);
67
- if (i && _arr.length === i) break;
68
- }
69
- } catch (err) {
70
- _d = true;
71
- _e = err;
72
- } finally{
73
- try {
74
- if (!_n && _i["return"] != null) _i["return"]();
75
- } finally{
76
- if (_d) throw _e;
77
- }
78
- }
79
- return _arr;
80
- }
81
- function _non_iterable_rest() {
82
- throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
83
- }
84
- function _non_iterable_spread() {
85
- throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
86
- }
87
- function _sliced_to_array(arr, i) {
88
- return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
89
- }
90
- function _to_consumable_array(arr) {
91
- return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
92
- }
93
- function _type_of(obj) {
94
- "@swc/helpers - typeof";
95
- return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
96
- }
97
- function _unsupported_iterable_to_array(o, minLen) {
98
- if (!o) return;
99
- if (typeof o === "string") return _array_like_to_array(o, minLen);
100
- var n = Object.prototype.toString.call(o).slice(8, -1);
101
- if (n === "Object" && o.constructor) n = o.constructor.name;
102
- if (n === "Map" || n === "Set") return Array.from(n);
103
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
104
- }
105
- var RESERVED_COLUMNS = new Set([
106
- 'path',
107
- '_mtime',
108
- '_ctime',
109
- '_size',
110
- '_rank',
111
- '_parse_error',
112
- 'content',
113
- 'links',
114
- 'sections'
115
- ]);
116
- // YAML error codes whose recovery is unambiguous, so the parse is accepted rather than
117
- // quarantined. Only one qualifies: YAML 1.2 reserves `@` and `` ` `` at the start of a plain
118
- // scalar for future use, so they can never be valid and the text can only be what was typed
119
- // (`aliases: [@handle]` -> ["@handle"]). Every other code has a second reading -- an unquoted
120
- // `:` swallows the keys after it, an unquoted `[..](..)` drops the URL, a duplicate key picks
121
- // one value in silence -- so it writes values nobody wrote.
122
- var ACCEPTED_YAML_CODES = new Set([
123
- 'BAD_SCALAR_START'
124
- ]);
125
- function normalizeText(value) {
126
- if (value === null || value === undefined) return '';
127
- return String(value).replace(/\s+/g, ' ').trim();
128
- }
129
- // Keeps URL query strings, asset filenames, and HTML attributes out of the index: rare terms
130
- // carry high IDF, so they outrank prose. remove-markdown misses wikilinks and tables.
131
- function stripText(value) {
132
- var withoutWikilinks = value.replace(/\[\[([^\]|]+)\|([^\]]+)\]\]/g, '$2').replace(/\[\[([^\]]+)\]\]/g, '$1');
133
- // remove-markdown deletes footnote definitions wholesale ("[^1]: text" -> ""), so unwrap
134
- // them (and drop inline refs) before it runs; the definition text stays indexed.
135
- var withoutFootnotes = withoutWikilinks.replace(/^\[\^[^\]]+\]:[ \t]?/gm, '').replace(/\[\^[^\]]+\]/g, '');
136
- var withoutMarkdown = (0, _removemarkdown.default)(withoutFootnotes);
137
- var withoutTables = withoutMarkdown.replace(/^\s*\|?[-\s|:]+\|\s*$/gm, '').replace(/\|/g, ' ');
138
- return normalizeText(withoutTables);
139
- }
140
- function toPosixPath(relPath) {
141
- var separator = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : _nodepath.sep;
142
- return separator === '\\' ? relPath.split(separator).join('/') : relPath;
143
- }
144
- // Every command pays listFiles before it answers (the freshness check stats each file), so
145
- // per-file work here is the hottest path in the package. Everything derivable from the config
146
- // alone is computed once, above the loop.
147
- var NO_THROW = {
148
- throwIfNoEntry: false
149
- };
150
- function listFiles(cfg, baseDir) {
151
- var coverage = new Map();
152
- var posixNeeded = _nodepath.sep === '\\';
153
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
154
- try {
155
- for(var _iterator = (0, _indexts.presetNames)(cfg)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
156
- var name = _step.value;
157
- var preset = cfg.presets[name];
158
- var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined;
159
- try {
160
- for(var _iterator1 = (0, _nodefs.globSync)(preset.include, {
161
- cwd: baseDir,
162
- exclude: preset.exclude
163
- })[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
164
- var matched = _step1.value;
165
- var _coverage_get;
166
- var relPath = posixNeeded ? toPosixPath(matched) : matched;
167
- var set = (_coverage_get = coverage.get(relPath)) !== null && _coverage_get !== void 0 ? _coverage_get : new Set();
168
- set.add(name);
169
- coverage.set(relPath, set);
170
- }
171
- } catch (err) {
172
- _didIteratorError1 = true;
173
- _iteratorError1 = err;
174
- } finally{
175
- try {
176
- if (!_iteratorNormalCompletion1 && _iterator1.return != null) {
177
- _iterator1.return();
178
- }
179
- } finally{
180
- if (_didIteratorError1) {
181
- throw _iteratorError1;
182
- }
183
- }
184
- }
185
- }
186
- } catch (err) {
187
- _didIteratorError = true;
188
- _iteratorError = err;
189
- } finally{
190
- try {
191
- if (!_iteratorNormalCompletion && _iterator.return != null) {
192
- _iterator.return();
193
- }
194
- } finally{
195
- if (_didIteratorError) {
196
- throw _iteratorError;
197
- }
198
- }
199
- }
200
- // Which presets want vectors is a property of the config, not of any file.
201
- var embedding = (0, _indexts.embedEnabled)(cfg);
202
- var vectorPresets = embedding ? new Set((0, _indexts.presetNames)(cfg).filter(function(name) {
203
- return (0, _indexts.presetHasSignal)(cfg, name, 'vectors');
204
- })) : null;
205
- var files = [];
206
- var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = undefined;
207
- try {
208
- for(var _iterator2 = _to_consumable_array(coverage.keys()).sort()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true){
209
- var relPath1 = _step2.value;
210
- var absPath = (0, _nodepath.join)(baseDir, relPath1); // join re-applies the platform separator for fs calls
211
- // node:fs glob matches directories and dangling symlinks; fast-glob returned neither, so
212
- // one stat filters both back out (throwIfNoEntry keeps a dangling link from throwing).
213
- var st = (0, _nodefs.statSync)(absPath, NO_THROW);
214
- if (!(st === null || st === void 0 ? void 0 : st.isFile())) continue;
215
- var presets = _to_consumable_array(coverage.get(relPath1)).sort();
216
- var embed = vectorPresets !== null && presets.some(function(name) {
217
- return vectorPresets.has(name);
218
- });
219
- files.push({
220
- relPath: relPath1,
221
- absPath: absPath,
222
- mtimeMs: st.mtimeMs,
223
- ctimeMs: st.birthtimeMs,
224
- size: st.size,
225
- presets: presets,
226
- embed: embed
227
- });
228
- }
229
- } catch (err) {
230
- _didIteratorError2 = true;
231
- _iteratorError2 = err;
232
- } finally{
233
- try {
234
- if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
235
- _iterator2.return();
236
- }
237
- } finally{
238
- if (_didIteratorError2) {
239
- throw _iteratorError2;
240
- }
241
- }
242
- }
243
- return files;
244
- }
245
- // SQLite's datetime() rejects a colonless offset (`-0800`) and a space separator, which ISO 8601
246
- // allows and producers emit. A rejected date is invisible, not excluded: every comparison is NULL.
247
- var ISO_DATETIME = /^(\d{4}-\d{2}-\d{2})[T ](\d{2}:\d{2}(?::\d{2})?(?:\.\d+)?)(Z|[+-]\d{2}(?::?\d{2})?)?$/;
248
- // A value opening `YYYY-MM-DDT` was meant to be a datetime; prose never is. Reported when it
249
- // cannot be normalized, so a typo surfaces on the next crawl instead of at some later audit.
250
- var MEANT_AS_DATETIME = /^\d{4}-\d{2}-\d{2}[T ]\d/;
251
- function looksLikeDatetime(value) {
252
- return MEANT_AS_DATETIME.test(value);
253
- }
254
- function normalizeDate(value) {
255
- var m = ISO_DATETIME.exec(value);
256
- if (m === null) return value;
257
- var _m = _sliced_to_array(m, 4), date = _m[1], time = _m[2], zone = _m[3];
258
- var digits = zone === undefined || zone === 'Z' ? '' : zone.replace(':', '');
259
- var offset = digits === '' ? zone !== null && zone !== void 0 ? zone : '' : digits.length === 3 ? "".concat(digits, ":00") : "".concat(digits.slice(0, 3), ":").concat(digits.slice(3));
260
- var normalized = "".concat(date, "T").concat(time).concat(offset);
261
- return Number.isNaN(Date.parse(normalized)) ? value : normalized;
262
- }
263
- // Storage class follows the YAML scalar. Booleans store as 1/0, so `WHERE flag = 1` matches
264
- // and `WHERE flag = 'true'` cannot; `map` prints observed types so the mismatch is visible.
265
- function mapValue(value) {
266
- if (value === null || value === undefined) return null;
267
- if (typeof value === 'boolean') return BigInt(value ? 1 : 0);
268
- if (typeof value === 'number') return Number.isSafeInteger(value) ? BigInt(value) : value;
269
- if (typeof value === 'string') return normalizeDate(value);
270
- return JSON.stringify(value);
271
- }
272
- // The delimiter split is all this package used gray-matter for.
273
- function splitFrontmatter(raw) {
274
- var open = raw.match(/^---\r?\n/);
275
- if (!open) return {
276
- fm: null,
277
- body: raw
278
- };
279
- var rest = raw.slice(open[0].length);
280
- var close = rest.match(/^---\r?(\n|$)/m);
281
- if (!close || close.index === undefined) return {
282
- fm: null,
283
- body: raw
284
- };
285
- return {
286
- fm: rest.slice(0, close.index),
287
- body: rest.slice(close.index + close[0].length)
288
- };
289
- }
290
- // A well-formed document can still hold a value nobody meant: `created: {{date}}` is valid
291
- // YAML for a flow map used as a mapping key, so it raises no error and stores
292
- // {"{ date }": null}. No error code can catch that, but yaml notices the stringified key, so
293
- // this reports it with the path instead (yaml's own warning has none, fires once per document,
294
- // and is what trains readers to discard stderr).
295
- function warnStringifiedKeys(relPath, doc, warnings) {
296
- var found = false;
297
- // Nested, not top level: `created: {{date}}` puts the collection key one level down, inside
298
- // the flow map that `{{...}}` parses as.
299
- (0, _yaml.visit)(doc, {
300
- Pair: function Pair(_key, pair) {
301
- if (!(0, _yaml.isCollection)(pair.key)) return undefined;
302
- found = true;
303
- return _yaml.visit.BREAK;
304
- }
305
- });
306
- // One per file: a template repeats the same mistake on every field it stamps.
307
- if (found) warnings.push("warning: ".concat(relPath, " frontmatter has a key that is itself a list or mapping, stored as text; this is usually an unrendered template placeholder like {{date}}"));
308
- }
309
- // Accept a clean parse, and one whose every error is unambiguous (ACCEPTED_YAML_CODES).
310
- // Anything else is quarantined: no frontmatter columns at all, and `_parse_error` carries the
311
- // reason. Recovering it would write values nobody wrote, which is worse than absence because
312
- // no query can see it. The file is still indexed -- content, links and sections never touch
313
- // frontmatter -- so a broken note stays searchable while it is being hunted for.
314
- // yaml's message continues onto a source excerpt, so the first line is the sentence -- minus
315
- // the colon that introduced the part being dropped.
316
- function firstLine(message) {
317
- return message.split('\n')[0].replace(/:\s*$/, '');
318
- }
319
- function parseFrontmatter(relPath, fm, warnings) {
320
- // logLevel silences yaml's own pathless warnings; warnStringifiedKeys re-reports the one
321
- // that carries information, with the file it came from.
322
- var doc = (0, _yaml.parseDocument)(fm, {
323
- logLevel: 'silent'
324
- });
325
- var refused = doc.errors.filter(function(err) {
326
- return !ACCEPTED_YAML_CODES.has(err.code);
327
- });
328
- if (refused.length > 0) {
329
- var detail = refused.length > 1 ? " (and ".concat(refused.length - 1, " more)") : '';
330
- var parseError = "".concat(firstLine(refused[0].message)).concat(detail);
331
- warnings.push("warning: ".concat(relPath, " frontmatter did not parse, so none of it is indexed: ").concat(parseError));
332
- return {
333
- data: {},
334
- parseError: parseError
335
- };
336
- }
337
- var data;
338
- try {
339
- data = doc.toJS();
340
- } catch (err) {
341
- // Reaches here with doc.errors empty: `title: **Bold**` parses, then opens an alias on
342
- // materialisation. An empty error list is not a successful parse.
343
- var parseError1 = firstLine(err.message);
344
- warnings.push("warning: ".concat(relPath, " frontmatter did not parse, so none of it is indexed: ").concat(parseError1));
345
- return {
346
- data: {},
347
- parseError: parseError1
348
- };
349
- }
350
- if (data === null || data === undefined) return {
351
- data: {},
352
- parseError: null
353
- };
354
- if ((typeof data === "undefined" ? "undefined" : _type_of(data)) !== 'object' || Array.isArray(data)) {
355
- var parseError2 = 'frontmatter is not a key-value mapping';
356
- warnings.push("warning: ".concat(relPath, " ").concat(parseError2, "; none of it is indexed"));
357
- return {
358
- data: {},
359
- parseError: parseError2
360
- };
361
- }
362
- warnStringifiedKeys(relPath, doc, warnings);
363
- return {
364
- data: data,
365
- parseError: null
366
- };
367
- }
368
- function parseFile(file) {
369
- var extractors = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : [];
370
- var raw = (0, _nodefs.readFileSync)(file.absPath, 'utf8');
371
- var warnings = [];
372
- var _splitFrontmatter = splitFrontmatter(raw), fm = _splitFrontmatter.fm, content = _splitFrontmatter.body;
373
- var _ref = fm === null ? {
374
- data: {},
375
- parseError: null
376
- } : parseFrontmatter(file.relPath, fm, warnings), data = _ref.data, parseError = _ref.parseError;
377
- var mapped = {};
378
- var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
379
- try {
380
- for(var _iterator = Object.keys(data)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
381
- var key = _step.value;
382
- if (RESERVED_COLUMNS.has(key)) {
383
- warnings.push("warning: ".concat(file.relPath, ' has a frontmatter key named "').concat(key, '", which is reserved; ignoring it'));
384
- continue;
385
- }
386
- var value = mapValue(data[key]);
387
- if (typeof value === 'string' && looksLikeDatetime(value) && Number.isNaN(Date.parse(value))) {
388
- warnings.push("warning: ".concat(file.relPath, ": ").concat(key, " is not a valid date (").concat(value, "), so it is invisible to every date comparison"));
389
- }
390
- mapped[key] = value;
391
- }
392
- } catch (err) {
393
- _didIteratorError = true;
394
- _iteratorError = err;
395
- } finally{
396
- try {
397
- if (!_iteratorNormalCompletion && _iterator.return != null) {
398
- _iterator.return();
399
- }
400
- } finally{
401
- if (_didIteratorError) {
402
- throw _iteratorError;
403
- }
404
- }
405
- }
406
- // title/summary are plain YAML strings -- whitespace-collapse only;
407
- // the prose gets the full markdown strip.
408
- var search = {
409
- title: normalizeText(data.title),
410
- summary: normalizeText(data.summary),
411
- text: stripText(content)
412
- };
413
- return {
414
- doc: {
415
- relPath: file.relPath,
416
- mtimeMs: file.mtimeMs,
417
- ctimeMs: file.ctimeMs,
418
- size: file.size,
419
- presets: file.presets,
420
- data: mapped,
421
- parseError: parseError,
422
- search: search,
423
- extracted: Object.fromEntries(extractors.filter(function(f) {
424
- return f.extract;
425
- }).map(function(f) {
426
- var _f_extract;
427
- return [
428
- f.name,
429
- (_f_extract = f.extract) === null || _f_extract === void 0 ? void 0 : _f_extract.call(f, raw, content, search, data)
430
- ];
431
- }))
432
- },
433
- warnings: warnings
434
- };
435
- }
436
- /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/scan.ts"],"sourcesContent":["import { globSync, readFileSync, statSync } from 'node:fs';\nimport { join, sep } from 'node:path';\nimport removeMarkdown from 'remove-markdown';\nimport { isCollection, parseDocument, visit } from 'yaml';\nimport type { Config } from './config/index.ts';\nimport { embedEnabled, presetHasSignal, presetNames } from './config/index.ts';\nimport type { Feature } from './features/types.ts';\n\n// Filesystem -> rows. Pure data in, data + warnings out; db.ts does the SQL.\n\n// Frontmatter keys that would collide with table columns. Exported so db.ts's upsert can tell\n// a feature-owned column (`_rank`) from a parsed one and leave it alone on reparse.\nexport const RESERVED_COLUMNS = new Set(['path', '_mtime', '_ctime', '_size', '_rank', '_parse_error', 'content', 'links', 'sections']);\n\n// YAML error codes whose recovery is unambiguous, so the parse is accepted rather than\n// quarantined. Only one qualifies: YAML 1.2 reserves `@` and `` ` `` at the start of a plain\n// scalar for future use, so they can never be valid and the text can only be what was typed\n// (`aliases: [@handle]` -> [\"@handle\"]). Every other code has a second reading -- an unquoted\n// `:` swallows the keys after it, an unquoted `[..](..)` drops the URL, a duplicate key picks\n// one value in silence -- so it writes values nobody wrote.\nconst ACCEPTED_YAML_CODES = new Set(['BAD_SCALAR_START']);\n\nfunction normalizeText(value: unknown): string {\n if (value === null || value === undefined) return '';\n return String(value).replace(/\\s+/g, ' ').trim();\n}\n\n// Keeps URL query strings, asset filenames, and HTML attributes out of the index: rare terms\n// carry high IDF, so they outrank prose. remove-markdown misses wikilinks and tables.\nfunction stripText(value: string): string {\n const withoutWikilinks = value.replace(/\\[\\[([^\\]|]+)\\|([^\\]]+)\\]\\]/g, '$2').replace(/\\[\\[([^\\]]+)\\]\\]/g, '$1');\n // remove-markdown deletes footnote definitions wholesale (\"[^1]: text\" -> \"\"), so unwrap\n // them (and drop inline refs) before it runs; the definition text stays indexed.\n const withoutFootnotes = withoutWikilinks.replace(/^\\[\\^[^\\]]+\\]:[ \\t]?/gm, '').replace(/\\[\\^[^\\]]+\\]/g, '');\n const withoutMarkdown = removeMarkdown(withoutFootnotes);\n const withoutTables = withoutMarkdown.replace(/^\\s*\\|?[-\\s|:]+\\|\\s*$/gm, '').replace(/\\|/g, ' ');\n return normalizeText(withoutTables);\n}\n\nexport interface FileStat {\n relPath: string;\n absPath: string;\n mtimeMs: number;\n ctimeMs: number; // filesystem birthtime; a clone or copy resets it, like _mtime\n size: number;\n presets: string[]; // every declared preset covering this file (>= 1; union, overlap allowed)\n embed: boolean; // true iff a model is named and some covering preset's signals include vectors\n}\n\n// Presets are views, not partitions: they overlap freely, and a file's covering set (not one\n// owner) drives indexing. Globs resolve relative to baseDir; unmatched files are not indexed.\nexport function toPosixPath(relPath: string, separator: string = sep): string {\n return separator === '\\\\' ? relPath.split(separator).join('/') : relPath;\n}\n\n// Every command pays listFiles before it answers (the freshness check stats each file), so\n// per-file work here is the hottest path in the package. Everything derivable from the config\n// alone is computed once, above the loop.\nconst NO_THROW = { throwIfNoEntry: false } as const;\n\nexport function listFiles(cfg: Config, baseDir: string): FileStat[] {\n const coverage = new Map<string, Set<string>>();\n const posixNeeded = sep === '\\\\';\n for (const name of presetNames(cfg)) {\n const preset = cfg.presets[name];\n for (const matched of globSync(preset.include, { cwd: baseDir, exclude: preset.exclude })) {\n const relPath = posixNeeded ? toPosixPath(matched) : matched;\n const set = coverage.get(relPath) ?? new Set<string>();\n set.add(name);\n coverage.set(relPath, set);\n }\n }\n\n // Which presets want vectors is a property of the config, not of any file.\n const embedding = embedEnabled(cfg);\n const vectorPresets = embedding ? new Set(presetNames(cfg).filter((name) => presetHasSignal(cfg, name, 'vectors'))) : null;\n\n const files: FileStat[] = [];\n for (const relPath of [...coverage.keys()].sort()) {\n const absPath = join(baseDir, relPath); // join re-applies the platform separator for fs calls\n // node:fs glob matches directories and dangling symlinks; fast-glob returned neither, so\n // one stat filters both back out (throwIfNoEntry keeps a dangling link from throwing).\n const st = statSync(absPath, NO_THROW);\n if (!st?.isFile()) continue;\n const presets = [...(coverage.get(relPath) as Set<string>)].sort();\n const embed = vectorPresets !== null && presets.some((name) => vectorPresets.has(name));\n files.push({ relPath, absPath, mtimeMs: st.mtimeMs, ctimeMs: st.birthtimeMs, size: st.size, presets, embed });\n }\n return files;\n}\n\nexport interface ParsedDoc {\n relPath: string;\n mtimeMs: number;\n ctimeMs: number;\n size: number;\n presets: string[];\n data: Record<string, string | number | bigint | null>;\n // NULL when the frontmatter parsed, the first YAML message otherwise. In the row rather than\n // a side table so `SELECT *` and any `IS NULL` investigation trip over it without being asked.\n parseError: string | null;\n // title/summary are duplicated from frontmatter so bm25() can weight them above the body text.\n search: { title: string; summary: string; text: string };\n // Per-feature extraction results, keyed by feature name; features store them at reconcile.\n extracted: Record<string, unknown>;\n}\n\n// SQLite's datetime() rejects a colonless offset (`-0800`) and a space separator, which ISO 8601\n// allows and producers emit. A rejected date is invisible, not excluded: every comparison is NULL.\nconst ISO_DATETIME = /^(\\d{4}-\\d{2}-\\d{2})[T ](\\d{2}:\\d{2}(?::\\d{2})?(?:\\.\\d+)?)(Z|[+-]\\d{2}(?::?\\d{2})?)?$/;\n\n// A value opening `YYYY-MM-DDT` was meant to be a datetime; prose never is. Reported when it\n// cannot be normalized, so a typo surfaces on the next crawl instead of at some later audit.\nconst MEANT_AS_DATETIME = /^\\d{4}-\\d{2}-\\d{2}[T ]\\d/;\n\nexport function looksLikeDatetime(value: string): boolean {\n return MEANT_AS_DATETIME.test(value);\n}\n\n// Punctuation only, never a timezone conversion: the offset survives, so substr(d,1,10) is still\n// the local date. A shape that is not a real instant is left as written, and stays auditable.\nexport function normalizeDate(value: string): string {\n const m = ISO_DATETIME.exec(value);\n if (m === null) return value;\n const [, date, time, zone] = m;\n const digits = zone === undefined || zone === 'Z' ? '' : zone.replace(':', '');\n const offset = digits === '' ? (zone ?? '') : digits.length === 3 ? `${digits}:00` : `${digits.slice(0, 3)}:${digits.slice(3)}`;\n const normalized = `${date}T${time}${offset}`;\n return Number.isNaN(Date.parse(normalized)) ? value : normalized;\n}\n\n// Storage class follows the YAML scalar. Booleans store as 1/0, so `WHERE flag = 1` matches\n// and `WHERE flag = 'true'` cannot; `map` prints observed types so the mismatch is visible.\nfunction mapValue(value: unknown): string | number | bigint | null {\n if (value === null || value === undefined) return null;\n if (typeof value === 'boolean') return BigInt(value ? 1 : 0);\n if (typeof value === 'number') return Number.isSafeInteger(value) ? BigInt(value) : value;\n if (typeof value === 'string') return normalizeDate(value);\n return JSON.stringify(value);\n}\n\n// The delimiter split is all this package used gray-matter for.\nfunction splitFrontmatter(raw: string): { fm: string | null; body: string } {\n const open = raw.match(/^---\\r?\\n/);\n if (!open) return { fm: null, body: raw };\n const rest = raw.slice(open[0].length);\n const close = rest.match(/^---\\r?(\\n|$)/m);\n if (!close || close.index === undefined) return { fm: null, body: raw };\n return { fm: rest.slice(0, close.index), body: rest.slice(close.index + close[0].length) };\n}\n\n// A well-formed document can still hold a value nobody meant: `created: {{date}}` is valid\n// YAML for a flow map used as a mapping key, so it raises no error and stores\n// {\"{ date }\": null}. No error code can catch that, but yaml notices the stringified key, so\n// this reports it with the path instead (yaml's own warning has none, fires once per document,\n// and is what trains readers to discard stderr).\nfunction warnStringifiedKeys(relPath: string, doc: ReturnType<typeof parseDocument>, warnings: string[]): void {\n let found = false;\n // Nested, not top level: `created: {{date}}` puts the collection key one level down, inside\n // the flow map that `{{...}}` parses as.\n visit(doc, {\n Pair(_key, pair) {\n if (!isCollection(pair.key)) return undefined;\n found = true;\n return visit.BREAK;\n },\n });\n // One per file: a template repeats the same mistake on every field it stamps.\n if (found) warnings.push(`warning: ${relPath} frontmatter has a key that is itself a list or mapping, stored as text; this is usually an unrendered template placeholder like {{date}}`);\n}\n\n// Accept a clean parse, and one whose every error is unambiguous (ACCEPTED_YAML_CODES).\n// Anything else is quarantined: no frontmatter columns at all, and `_parse_error` carries the\n// reason. Recovering it would write values nobody wrote, which is worse than absence because\n// no query can see it. The file is still indexed -- content, links and sections never touch\n// frontmatter -- so a broken note stays searchable while it is being hunted for.\n// yaml's message continues onto a source excerpt, so the first line is the sentence -- minus\n// the colon that introduced the part being dropped.\nfunction firstLine(message: string): string {\n return message.split('\\n')[0].replace(/:\\s*$/, '');\n}\n\nfunction parseFrontmatter(relPath: string, fm: string, warnings: string[]): { data: Record<string, unknown>; parseError: string | null } {\n // logLevel silences yaml's own pathless warnings; warnStringifiedKeys re-reports the one\n // that carries information, with the file it came from.\n const doc = parseDocument(fm, { logLevel: 'silent' });\n const refused = doc.errors.filter((err) => !ACCEPTED_YAML_CODES.has(err.code));\n if (refused.length > 0) {\n const detail = refused.length > 1 ? ` (and ${refused.length - 1} more)` : '';\n const parseError = `${firstLine(refused[0].message)}${detail}`;\n warnings.push(`warning: ${relPath} frontmatter did not parse, so none of it is indexed: ${parseError}`);\n return { data: {}, parseError };\n }\n\n let data: unknown;\n try {\n data = doc.toJS();\n } catch (err) {\n // Reaches here with doc.errors empty: `title: **Bold**` parses, then opens an alias on\n // materialisation. An empty error list is not a successful parse.\n const parseError = firstLine((err as Error).message);\n warnings.push(`warning: ${relPath} frontmatter did not parse, so none of it is indexed: ${parseError}`);\n return { data: {}, parseError };\n }\n\n if (data === null || data === undefined) return { data: {}, parseError: null };\n if (typeof data !== 'object' || Array.isArray(data)) {\n const parseError = 'frontmatter is not a key-value mapping';\n warnings.push(`warning: ${relPath} ${parseError}; none of it is indexed`);\n return { data: {}, parseError };\n }\n warnStringifiedKeys(relPath, doc, warnings);\n return { data: data as Record<string, unknown>, parseError: null };\n}\n\nexport function parseFile(file: FileStat, extractors: Feature[] = []): { doc: ParsedDoc; warnings: string[] } {\n const raw = readFileSync(file.absPath, 'utf8');\n const warnings: string[] = [];\n\n const { fm, body: content } = splitFrontmatter(raw);\n const { data, parseError } = fm === null ? { data: {} as Record<string, unknown>, parseError: null } : parseFrontmatter(file.relPath, fm, warnings);\n const mapped: Record<string, string | number | bigint | null> = {};\n\n for (const key of Object.keys(data)) {\n if (RESERVED_COLUMNS.has(key)) {\n warnings.push(`warning: ${file.relPath} has a frontmatter key named \"${key}\", which is reserved; ignoring it`);\n continue;\n }\n const value = mapValue(data[key]);\n if (typeof value === 'string' && looksLikeDatetime(value) && Number.isNaN(Date.parse(value))) {\n warnings.push(`warning: ${file.relPath}: ${key} is not a valid date (${value}), so it is invisible to every date comparison`);\n }\n mapped[key] = value;\n }\n\n // title/summary are plain YAML strings -- whitespace-collapse only;\n // the prose gets the full markdown strip.\n const search = { title: normalizeText(data.title), summary: normalizeText(data.summary), text: stripText(content) };\n\n return {\n doc: {\n relPath: file.relPath,\n mtimeMs: file.mtimeMs,\n ctimeMs: file.ctimeMs,\n size: file.size,\n presets: file.presets,\n data: mapped,\n parseError,\n search,\n extracted: Object.fromEntries(extractors.filter((f) => f.extract).map((f) => [f.name, f.extract?.(raw, content, search, data)])),\n },\n warnings,\n };\n}\n"],"names":["RESERVED_COLUMNS","listFiles","looksLikeDatetime","normalizeDate","parseFile","toPosixPath","Set","ACCEPTED_YAML_CODES","normalizeText","value","undefined","String","replace","trim","stripText","withoutWikilinks","withoutFootnotes","withoutMarkdown","removeMarkdown","withoutTables","relPath","separator","sep","split","join","NO_THROW","throwIfNoEntry","cfg","baseDir","coverage","Map","posixNeeded","presetNames","name","preset","presets","globSync","include","cwd","exclude","matched","set","get","add","embedding","embedEnabled","vectorPresets","filter","presetHasSignal","files","keys","sort","absPath","st","statSync","isFile","embed","some","has","push","mtimeMs","ctimeMs","birthtimeMs","size","ISO_DATETIME","MEANT_AS_DATETIME","test","m","exec","date","time","zone","digits","offset","length","slice","normalized","Number","isNaN","Date","parse","mapValue","BigInt","isSafeInteger","JSON","stringify","splitFrontmatter","raw","open","match","fm","body","rest","close","index","warnStringifiedKeys","doc","warnings","found","visit","Pair","_key","pair","isCollection","key","BREAK","firstLine","message","parseFrontmatter","parseDocument","logLevel","refused","errors","err","code","detail","parseError","data","toJS","Array","isArray","file","extractors","readFileSync","content","mapped","Object","search","title","summary","text","extracted","fromEntries","f","extract","map"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/search-error.ts"],"sourcesContent":["import { SenseError } from './errors.ts';\n\n// FTS5 reads punctuation as syntax, so `end-to-end` parses as a filter on column `to` and\n// errors `no such column: to` -- true about the parse, misleading about the input. Matched as\n// \"not a bareword\": an operator list is a list to keep current, and missing a character costs\n// the remedy, not the error.\nconst FTS5_PUNCTUATION = /[^\\p{L}\\p{N}_\\s]/u;\n\nexport function searchError(err: Error, terms: string, scope?: string): Error {\n const message = err.message;\n if (!/no such column|fts5: syntax error|malformed MATCH/.test(message)) return err;\n const suspects = (terms.match(/\\S+/g) ?? []).filter((t) => !t.startsWith('\"') && FTS5_PUNCTUATION.test(t));\n // Blame the terms only when the failing token actually came from one -- a typo'd column\n // in --where (or the tree's default scope) raises \"no such column\" through this same\n // statement, and naming a term for it would state a false fact about the input.\n const col = /no such column: (\\S+)/.exec(message)?.[1];\n const fromTerms = col === undefined ? suspects.length > 0 : suspects.some((t) => t.split(/[^\\p{L}\\p{N}]+/u).includes(col));\n if (fromTerms && suspects.length > 0) {\n return new SenseError('SEARCH_SYNTAX', `${message} -- the punctuation in ${suspects.map((t) => `\\`${t}\\``).join(', ')} is FTS5 syntax, not literal text; search for it literally by double-quoting: '\"${suspects[0]}\"'. Searchable columns are title, summary, text.`);\n }\n if (col !== undefined && scope !== undefined) {\n return new SenseError('SEARCH_SYNTAX', `${message} -- the where condition (${scope}) references it; frontmatter columns are listed by sense sql \"SELECT name FROM pragma_table_info('frontmatter')\".`);\n }\n return new SenseError('SEARCH_SYNTAX', `${message} -- searchable columns are title, summary, text; frontmatter fields are queried with --where or sense sql (list them with pragma_table_info('frontmatter')).`);\n}\n"],"names":["searchError","FTS5_PUNCTUATION","err","terms","scope","message","test","suspects","match","filter","t","startsWith","col","exec","fromTerms","undefined","length","some","split","includes","SenseError","map","join"],"mappings":";;;;+BAQgBA;;;eAAAA;;;wBARW;AAE3B,0FAA0F;AAC1F,8FAA8F;AAC9F,8FAA8F;AAC9F,6BAA6B;AAC7B,IAAMC,mBAAmB;AAElB,SAASD,YAAYE,GAAU,EAAEC,KAAa,EAAEC,KAAc;QAGjDD;QAIN;IANZ,IAAME,UAAUH,IAAIG,OAAO;IAC3B,IAAI,CAAC,oDAAoDC,IAAI,CAACD,UAAU,OAAOH;IAC/E,IAAMK,WAAW,EAACJ,eAAAA,MAAMK,KAAK,CAAC,qBAAZL,0BAAAA,eAAuB,EAAE,EAAEM,MAAM,CAAC,SAACC;eAAM,CAACA,EAAEC,UAAU,CAAC,QAAQV,iBAAiBK,IAAI,CAACI;;IACvG,wFAAwF;IACxF,qFAAqF;IACrF,gFAAgF;IAChF,IAAME,OAAM,QAAA,wBAAwBC,IAAI,CAACR,sBAA7B,4BAAA,KAAuC,CAAC,EAAE;IACtD,IAAMS,YAAYF,QAAQG,YAAYR,SAASS,MAAM,GAAG,IAAIT,SAASU,IAAI,CAAC,SAACP;eAAMA,EAAEQ,KAAK,CAAC,8maAAmBC,QAAQ,CAACP;;IACrH,IAAIE,aAAaP,SAASS,MAAM,GAAG,GAAG;QACpC,OAAO,IAAII,oBAAU,CAAC,iBAAiB,AAAC,GAAmCb,OAAjCF,SAAQ,2BAAsJE,OAA7HA,SAASc,GAAG,CAAC,SAACX;mBAAM,AAAC,IAAM,OAAFA,GAAE;WAAKY,IAAI,CAAC,OAAM,qFAA8F,OAAZf,QAAQ,CAAC,EAAE,EAAC;IACtN;IACA,IAAIK,QAAQG,aAAaX,UAAUW,WAAW;QAC5C,OAAO,IAAIK,oBAAU,CAAC,iBAAiB,AAAC,GAAqChB,OAAnCC,SAAQ,6BAAiC,OAAND,OAAM;IACrF;IACA,OAAO,IAAIgB,oBAAU,CAAC,iBAAiB,AAAC,GAAU,OAARf,SAAQ;AACpD"}
@@ -1,2 +0,0 @@
1
- export declare function segmentField(text: string): string;
2
- export declare function segmentMatch(terms: string): string;
@@ -1,2 +0,0 @@
1
- export declare function segmentField(text: string): string;
2
- export declare function segmentMatch(terms: string): string;
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/segment.ts"],"sourcesContent":["// Word boundaries FTS5's tokenizers cannot find on their own.\n//\n// Segmentation is context-free: seg(query) appears inside seg(document) whenever the query is\n// a substring of the document. That is the contract -- substring semantics, what `grep` and\n// `LIKE '%..%'` give -- and it is what makes index and query agree on every input, always.\n// Intl.Segmenter's word mode is context-dependent (`东京都政府` splits as `东 | 京都 | 政府`\n// while the query `东京` splits as one word) and is rejected for that reason. Its grapheme\n// mode has no such dependency -- UAX #29 cluster boundaries never look past adjacent\n// characters -- so grapheme mode is used below; no dictionary, no word mode.\n\n// Scripts written without word spaces: a closed set of writing systems.\n// Script_Extensions, not Script: the katakana long-vowel mark ー is Script=Common.\nconst SCRIPTS = '\\\\p{scx=Han}\\\\p{scx=Hiragana}\\\\p{scx=Katakana}\\\\p{scx=Thai}\\\\p{scx=Khmer}\\\\p{scx=Lao}\\\\p{scx=Myanmar}';\n// A run is script BASE characters with their combining marks attached; a bare mark after a\n// Latin letter (decomposed é) never starts one.\nconst RUN = new RegExp(`((?:[${SCRIPTS}]\\\\p{M}*)+)`, 'gu');\nconst HAS_RUN = new RegExp(`[${SCRIPTS}]`, 'u');\n// Grapheme clusters, ECMA-402/UAX #29: base char plus its marks, ZWJ sequences, Hangul jamo.\n// Built once (construction cost amortizes) and used for both index and query splitting.\nconst GRAPHEME_SEGMENTER = new Intl.Segmenter(undefined, { granularity: 'grapheme' });\n// unicode61 drops Unicode punctuation as a separator. Some of it (。、「」) has Script_Extensions\n// into an unspaced script, so RUN keeps it -- a grapheme matching this becomes a split point.\nconst PUNCTUATION = /\\p{P}/u;\n// Token barrier between separate runs (or a punctuation split within one) so their graphemes\n// are never phrase-adjacent. U+A7F7: a letter (so FTS5 keeps it as a token) no one types.\nconst BARRIER = 'ꟷ';\n\nfunction graphemes(run: string): string[] {\n return Array.from(GRAPHEME_SEGMENTER.segment(run), (s) => s.segment);\n}\n\n// A run's graphemes, cut into punctuation-free groups at every punctuation grapheme (dropped,\n// matching unicode61). The one place punctuation is classified, so index and query agree.\nfunction splitOnPunctuation(run: string): string[][] {\n const groups: string[][] = [[]];\n for (const g of graphemes(run)) {\n if (PUNCTUATION.test(g)) groups.push([]);\n else groups[groups.length - 1].push(g);\n }\n return groups.filter((g) => g.length > 0);\n}\n\n// Index side: '' when the field has no unspaced-script run (the common case, paid for by\n// nothing). Otherwise each run explodes into its graphemes, barrier-delimited from its\n// neighbors and from a punctuation split within itself.\nexport function segmentField(text: string): string {\n if (!HAS_RUN.test(text)) return '';\n const out = text.replace(RUN, (run) => {\n const body = splitOnPunctuation(run)\n .map((g) => g.join(' '))\n .join(` ${BARRIER} `);\n return ` ${BARRIER} ${body} ${BARRIER} `;\n });\n return out.replace(/\\s+/g, ' ').trim();\n}\n\n// A `title:`/`summary:`/`text:` qualifier directly before a run that is about to become a\n// quoted grapheme phrase, so the rewrite can retarget it at the matching `_seg` column.\nconst QUALIFIER = /(^|[\\s(])(-?)(title|summary|text)\\s*:\\s*$/;\n\n// An unqualified run's target: raw title/summary/text drop punctuation as unicode61's token\n// separator, so two adjacent single-grapheme phrase positions match across punctuation the same\n// as across a real gap (`数数` vs `数。数`) -- a false positive only the barriered `_seg` columns\n// are safe from. FTS5's column-set filter, not parens+OR, so the group still composes under\n// AND/OR/NOT/juxtaposition exactly like the single-column qualifier form below.\nconst SIDECAR_COLUMNS = '{title_seg summary_seg text_seg}:';\n\n// A run's punctuation-free groups, each its own quoted phrase (bare token if one grapheme),\n// space-joined -- the same split points segmentField barriers, so query and index agree.\nfunction runQuery(run: string, columnPrefix: string): string {\n return splitOnPunctuation(run)\n .map((g) => `${columnPrefix}${g.length > 1 ? `\"${g.join(' ')}\"` : g[0]}`)\n .join(' ');\n}\n\n// Query side: each unspaced run becomes phrases of its graphemes, matching how segmentField\n// indexed it. A qualifier ahead of such a run maps to its `_seg` column; unqualified maps to all\n// three (SIDECAR_COLUMNS), since raw columns cannot express the contract. An author's own quoted\n// phrase is their explicit escape hatch to FTS5's native syntax, and passes through byte-identical.\nexport function segmentMatch(terms: string): string {\n if (!HAS_RUN.test(terms)) return terms;\n let out = '';\n let quoted = false;\n const pieces = terms.split(RUN); // split keeps captured runs at odd indices\n for (let i = 0; i < pieces.length; i++) {\n if (i % 2 === 0) {\n for (const ch of pieces[i]) if (ch === '\"') quoted = !quoted;\n out += pieces[i];\n continue;\n }\n if (quoted) {\n out += pieces[i]; // an author's phrase is matched as written\n continue;\n }\n const m = out.match(QUALIFIER);\n if (m) {\n out = `${out.slice(0, m.index)}${m[1]}${runQuery(pieces[i], `${m[2]}${m[3]}_seg:`)}`;\n } else {\n out += runQuery(pieces[i], SIDECAR_COLUMNS);\n }\n }\n return out;\n}\n"],"names":["segmentField","segmentMatch","SCRIPTS","RUN","RegExp","HAS_RUN","GRAPHEME_SEGMENTER","Intl","Segmenter","undefined","granularity","PUNCTUATION","BARRIER","graphemes","run","Array","from","segment","s","splitOnPunctuation","groups","g","test","push","length","filter","text","out","replace","body","map","join","trim","QUALIFIER","SIDECAR_COLUMNS","runQuery","columnPrefix","terms","quoted","pieces","split","i","ch","m","match","slice","index"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/sql-functions.ts"],"sourcesContent":["import posix from 'node:path/posix';\nimport type { DatabaseSync } from 'node:sqlite';\nimport { segmentMatch } from './segment.ts';\n\n// has(field, value): JSON-array field -> membership, string field -> substring, NULL -> false.\nexport function registerFunctions(db: DatabaseSync, segmenting: boolean): void {\n db.function('has', { deterministic: true, varargs: false }, (field: unknown, value: unknown): number => {\n if (field === null || field === undefined) return 0;\n\n const needle = String(value);\n\n if (typeof field === 'string') {\n if (field.startsWith('[')) {\n try {\n const parsed = JSON.parse(field);\n if (Array.isArray(parsed)) {\n return parsed.some((item) => String(item) === needle) ? 1 : 0;\n }\n } catch {}\n }\n return field.includes(needle) ? 1 : 0;\n }\n\n return String(field).includes(needle) ? 1 : 0;\n });\n\n // Unix basename(path, suffix?): the filename, minus suffix when it ends with one. SQLite\n // itself has no filename function, and the LIKE tricks that fake one also match folder names.\n db.function('basename', { deterministic: true, varargs: true }, (path: unknown, suffix?: unknown): string | null => {\n if (path === null || path === undefined) return null;\n const name = posix.basename(String(path));\n const tail = suffix === null || suffix === undefined ? '' : String(suffix);\n // POSIX: a suffix identical to the whole name is not removed (node's own basename strips it).\n return tail !== '' && tail !== name && name.endsWith(tail) ? name.slice(0, -tail.length) : name;\n });\n\n // Raw `content MATCH '<unspaced text>'` cannot be rewritten behind the author's back, and\n // matches nothing, so the same transform is available to hand-written SQL by name. `segmenting`\n // is the same config predicate commands.ts's search() gates on (contentTokenize(cfg) ===\n // undefined), passed in by open() rather than read back from persisted state.\n db.function('segment', { deterministic: true, varargs: false }, (terms: unknown): string => {\n const text = terms === null || terms === undefined ? '' : String(terms);\n return segmenting ? segmentMatch(text) : text;\n });\n}\n"],"names":["registerFunctions","db","segmenting","function","deterministic","varargs","field","value","undefined","needle","String","startsWith","parsed","JSON","parse","Array","isArray","some","item","includes","path","suffix","name","posix","basename","tail","endsWith","slice","length","terms","text","segmentMatch"],"mappings":";;;;+BAKgBA;;;eAAAA;;;4DALE;yBAEW;;;;;;AAGtB,SAASA,kBAAkBC,EAAgB,EAAEC,UAAmB;IACrED,GAAGE,QAAQ,CAAC,OAAO;QAAEC,eAAe;QAAMC,SAAS;IAAM,GAAG,SAACC,OAAgBC;QAC3E,IAAID,UAAU,QAAQA,UAAUE,WAAW,OAAO;QAElD,IAAMC,SAASC,OAAOH;QAEtB,IAAI,OAAOD,UAAU,UAAU;YAC7B,IAAIA,MAAMK,UAAU,CAAC,MAAM;gBACzB,IAAI;oBACF,IAAMC,SAASC,KAAKC,KAAK,CAACR;oBAC1B,IAAIS,MAAMC,OAAO,CAACJ,SAAS;wBACzB,OAAOA,OAAOK,IAAI,CAAC,SAACC;mCAASR,OAAOQ,UAAUT;6BAAU,IAAI;oBAC9D;gBACF,EAAE,eAAM,CAAC;YACX;YACA,OAAOH,MAAMa,QAAQ,CAACV,UAAU,IAAI;QACtC;QAEA,OAAOC,OAAOJ,OAAOa,QAAQ,CAACV,UAAU,IAAI;IAC9C;IAEA,yFAAyF;IACzF,8FAA8F;IAC9FR,GAAGE,QAAQ,CAAC,YAAY;QAAEC,eAAe;QAAMC,SAAS;IAAK,GAAG,SAACe,MAAeC;QAC9E,IAAID,SAAS,QAAQA,SAASZ,WAAW,OAAO;QAChD,IAAMc,OAAOC,cAAK,CAACC,QAAQ,CAACd,OAAOU;QACnC,IAAMK,OAAOJ,WAAW,QAAQA,WAAWb,YAAY,KAAKE,OAAOW;QACnE,8FAA8F;QAC9F,OAAOI,SAAS,MAAMA,SAASH,QAAQA,KAAKI,QAAQ,CAACD,QAAQH,KAAKK,KAAK,CAAC,GAAG,CAACF,KAAKG,MAAM,IAAIN;IAC7F;IAEA,0FAA0F;IAC1F,gGAAgG;IAChG,yFAAyF;IACzF,8EAA8E;IAC9ErB,GAAGE,QAAQ,CAAC,WAAW;QAAEC,eAAe;QAAMC,SAAS;IAAM,GAAG,SAACwB;QAC/D,IAAMC,OAAOD,UAAU,QAAQA,UAAUrB,YAAY,KAAKE,OAAOmB;QACjE,OAAO3B,aAAa6B,IAAAA,uBAAY,EAACD,QAAQA;IAC3C;AACF"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/traverse.ts"],"sourcesContent":["// Frontier-by-frontier BFS through a temp visited table, one indexed anti-join per ring: a\n// local question touches a neighborhood, never the whole edge list.\nimport type { DatabaseSync } from 'node:sqlite';\n\ntype Direction = 'forward' | 'reverse' | 'both';\n\ninterface FindPathOptions {\n directed?: boolean;\n maxDepth?: number;\n allowed?: Set<string>;\n}\n\nfunction resetVisited(db: DatabaseSync): void {\n db.exec('DROP TABLE IF EXISTS temp.visited');\n db.exec('CREATE TEMP TABLE visited (path TEXT PRIMARY KEY, depth INTEGER NOT NULL, pred TEXT)');\n}\n\n// Materializes the caller-resolved scope Set into a temp table so it joins like any other\n// indexed column. `extra`, when given, is always in scope -- findPath's `to` endpoint.\nfunction setupAllowed(db: DatabaseSync, allowed: Set<string>, extra?: string): void {\n db.exec('DROP TABLE IF EXISTS temp.allowed_nodes');\n db.exec('CREATE TEMP TABLE allowed_nodes (path TEXT PRIMARY KEY)');\n db.prepare('INSERT INTO allowed_nodes SELECT DISTINCT value FROM json_each(?1)').run(JSON.stringify([...allowed]));\n if (extra !== undefined) db.prepare('INSERT OR IGNORE INTO allowed_nodes VALUES (?)').run(extra);\n}\n\n// Only resolved links (dst IS NOT NULL) are followed, in either direction.\nfunction candidateSelect(direction: Direction): string {\n const forward = 'SELECT l.dst AS path, l.src AS pred FROM links l JOIN visited v ON v.path = l.src AND v.depth = ?1 WHERE l.dst IS NOT NULL';\n const reverse = 'SELECT l.src AS path, l.dst AS pred FROM links l JOIN visited v ON v.path = l.dst AND v.depth = ?1 WHERE l.dst IS NOT NULL';\n if (direction === 'forward') return forward;\n if (direction === 'reverse') return reverse;\n return `${forward} UNION ALL ${reverse}`;\n}\n\n// One ring: candidates adjacent to the previous ring's frontier (?1), anti-joined against\n// everything already visited, optionally filtered to the allowed set, capped (?3) and\n// inserted at the new depth (?2). RETURNING hands back exactly what this ring newly reached.\nfunction ringSql(direction: Direction, hasAllowed: boolean): string {\n return `\nINSERT INTO visited (path, depth, pred)\nSELECT cand.path, ?2, MIN(cand.pred)\nFROM (${candidateSelect(direction)}) cand\nWHERE NOT EXISTS (SELECT 1 FROM visited v2 WHERE v2.path = cand.path)\n${hasAllowed ? 'AND EXISTS (SELECT 1 FROM allowed_nodes a WHERE a.path = cand.path)' : ''}\nGROUP BY cand.path\nORDER BY cand.path\nLIMIT ?3\nRETURNING path`;\n}\n\nfunction reconstructPath(db: DatabaseSync, to: string): string[] {\n const lookup = db.prepare('SELECT pred FROM visited WHERE path = ?');\n const path: string[] = [];\n let cur: string | null = to;\n while (cur !== null) {\n path.push(cur);\n const row = lookup.get(cur) as { pred: string | null } | undefined;\n cur = row ? row.pred : null;\n }\n return path.reverse();\n}\n\n// One BFS from `from`, tracking a predecessor per node. Undirected by default, matching\n// personalizedRank; null when `to` is unreached within `maxDepth`.\nexport function findPath(db: DatabaseSync, from: string, to: string, opts: FindPathOptions = {}): string[] | null {\n if (from === to) return [from];\n\n const direction: Direction = opts.directed ? 'forward' : 'both';\n const maxDepth = opts.maxDepth ?? Infinity;\n if (maxDepth <= 0) return null;\n\n resetVisited(db);\n db.prepare('INSERT INTO visited (path, depth, pred) VALUES (?, 0, NULL)').run(from);\n if (opts.allowed) setupAllowed(db, opts.allowed, to);\n\n const stmt = db.prepare(ringSql(direction, !!opts.allowed));\n for (let ring = 1; ring <= maxDepth; ring++) {\n const rows = stmt.all(ring - 1, ring, -1) as Array<{ path: string }>;\n if (rows.length === 0) break;\n if (rows.some((row) => row.path === to)) return reconstructPath(db, to);\n }\n return null;\n}\n"],"names":["findPath","resetVisited","db","exec","setupAllowed","allowed","extra","prepare","run","JSON","stringify","undefined","candidateSelect","direction","forward","reverse","ringSql","hasAllowed","reconstructPath","to","lookup","path","cur","push","row","get","pred","from","opts","directed","maxDepth","Infinity","stmt","ring","rows","all","length","some"],"mappings":"AAAA,2FAA2F;AAC3F,oEAAoE;;;;;+BAgEpDA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AArDhB,SAASC,aAAaC,EAAgB;IACpCA,GAAGC,IAAI,CAAC;IACRD,GAAGC,IAAI,CAAC;AACV;AAEA,0FAA0F;AAC1F,uFAAuF;AACvF,SAASC,aAAaF,EAAgB,EAAEG,OAAoB,EAAEC,KAAc;IAC1EJ,GAAGC,IAAI,CAAC;IACRD,GAAGC,IAAI,CAAC;IACRD,GAAGK,OAAO,CAAC,sEAAsEC,GAAG,CAACC,KAAKC,SAAS,CAAE,qBAAGL;IACxG,IAAIC,UAAUK,WAAWT,GAAGK,OAAO,CAAC,kDAAkDC,GAAG,CAACF;AAC5F;AAEA,2EAA2E;AAC3E,SAASM,gBAAgBC,SAAoB;IAC3C,IAAMC,UAAU;IAChB,IAAMC,UAAU;IAChB,IAAIF,cAAc,WAAW,OAAOC;IACpC,IAAID,cAAc,WAAW,OAAOE;IACpC,OAAO,AAAC,GAAuBA,OAArBD,SAAQ,eAAqB,OAARC;AACjC;AAEA,0FAA0F;AAC1F,sFAAsF;AACtF,6FAA6F;AAC7F,SAASC,QAAQH,SAAoB,EAAEI,UAAmB;IACxD,OAAO,AAAC,0FAKRA,OAFML,gBAAgBC,YAAW,mFAEuD,OAAxFI,aAAa,wEAAwE,IAAG;AAK1F;AAEA,SAASC,gBAAgBhB,EAAgB,EAAEiB,EAAU;IACnD,IAAMC,SAASlB,GAAGK,OAAO,CAAC;IAC1B,IAAMc,OAAiB,EAAE;IACzB,IAAIC,MAAqBH;IACzB,MAAOG,QAAQ,KAAM;QACnBD,KAAKE,IAAI,CAACD;QACV,IAAME,MAAMJ,OAAOK,GAAG,CAACH;QACvBA,MAAME,MAAMA,IAAIE,IAAI,GAAG;IACzB;IACA,OAAOL,KAAKN,OAAO;AACrB;AAIO,SAASf,SAASE,EAAgB,EAAEyB,IAAY,EAAER,EAAU;QAAES,OAAAA,iEAAwB,CAAC;QAI3EA;IAHjB,IAAID,SAASR,IAAI,OAAO;QAACQ;KAAK;IAE9B,IAAMd,YAAuBe,KAAKC,QAAQ,GAAG,YAAY;IACzD,IAAMC,YAAWF,iBAAAA,KAAKE,QAAQ,cAAbF,4BAAAA,iBAAiBG;IAClC,IAAID,YAAY,GAAG,OAAO;IAE1B7B,aAAaC;IACbA,GAAGK,OAAO,CAAC,+DAA+DC,GAAG,CAACmB;IAC9E,IAAIC,KAAKvB,OAAO,EAAED,aAAaF,IAAI0B,KAAKvB,OAAO,EAAEc;IAEjD,IAAMa,OAAO9B,GAAGK,OAAO,CAACS,QAAQH,WAAW,CAAC,CAACe,KAAKvB,OAAO;IACzD,IAAK,IAAI4B,OAAO,GAAGA,QAAQH,UAAUG,OAAQ;QAC3C,IAAMC,OAAOF,KAAKG,GAAG,CAACF,OAAO,GAAGA,MAAM,CAAC;QACvC,IAAIC,KAAKE,MAAM,KAAK,GAAG;QACvB,IAAIF,KAAKG,IAAI,CAAC,SAACb;mBAAQA,IAAIH,IAAI,KAAKF;YAAK,OAAOD,gBAAgBhB,IAAIiB;IACtE;IACA,OAAO;AACT"}
@@ -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":["startsWithBoundary","name","prefix","length","startsWith","test","columnHint","db","err","match","exec","message","token","aliasStripped","replace","forms","Set","columns","prepare","all","map","c","candidates","form","add","size","quoted","split","join","Error"],"mappings":"AAEA,0FAA0F;AAC1F,4FAA4F;AAC5F,wFAAwF;AACxF,8EAA8E;AAE9E,SAASA,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;AAEA,OAAO,SAASG,WAAWC,EAAgB,EAAEC,GAAU;IACrD,MAAMC,QAAQ,wBAAwBC,IAAI,CAACF,IAAIG,OAAO;IACtD,IAAI,CAACF,OAAO,OAAOD;IACnB,MAAMI,QAAQH,KAAK,CAAC,EAAE;IACtB,uFAAuF;IACvF,wFAAwF;IACxF,8DAA8D;IAC9D,MAAMI,gBAAgBD,MAAME,OAAO,CAAC,mBAAmB;IACvD,MAAMC,QAAQ,IAAIC,IAAI;QAACJ;QAAOC;KAAc;IAC5C,MAAMI,UAAU,AAACV,GAAGW,OAAO,CAAC,kCAAkCC,GAAG,GAA+BC,GAAG,CAAC,CAACC,IAAMA,EAAEpB,IAAI;IACjH,MAAMqB,aAAa,IAAIN;IACvB,KAAK,MAAMf,QAAQgB,QAAS;QAC1B,KAAK,MAAMM,QAAQR,MAAO;YACxB,IAAId,SAASsB,QAAQvB,mBAAmBC,MAAMsB,OAAOD,WAAWE,GAAG,CAACvB;QACtE;IACF;IACA,IAAIqB,WAAWG,IAAI,KAAK,GAAG,OAAOjB;IAClC,MAAMkB,SAAS;WAAIJ;KAAW,CAACF,GAAG,CAAC,CAACnB,OAAS,CAAC,CAAC,EAAEA,KAAK0B,KAAK,CAAC,KAAKC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAEA,IAAI,CAAC;IACrF,OAAO,IAAIC,MAAM,GAAGrB,IAAIG,OAAO,CAAC,IAAI,EAAEe,OAAO,6GAA6G,CAAC;AAC7J"}
@@ -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":["BACKTICK_OPEN","TILDE_OPEN","fenceTracker","inFence","fenceChar","fenceLen","feed","line","bt","exec","includes","length","td","run","m","trim","commentTracker","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","maskRegions","body","test","fence","comment","inHtmlBlock","htmlBlockClose","split","map","isDelim","uncommented","stripped","replace","openMatch","tagName","toLowerCase","isClosingTag","has","maskCodeSpans","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","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","personalizedRank","seeds","undirected"],"mappings":"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"}