sensemaking 0.27.0 → 0.27.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 (285) hide show
  1. package/dist/cjs/chunk/extract.js.map +1 -1
  2. package/dist/cjs/chunk/group.js.map +1 -1
  3. package/dist/cjs/chunk/index.js.map +1 -1
  4. package/dist/cjs/chunk/parse.js.map +1 -1
  5. package/dist/cjs/chunk/parser.js.map +1 -1
  6. package/dist/cjs/chunk/tokens.js.map +1 -1
  7. package/dist/cjs/chunk/version.js.map +1 -1
  8. package/dist/cjs/cli/build.js.map +1 -1
  9. package/dist/cjs/cli/download.js.map +1 -1
  10. package/dist/cjs/cli/index.js.map +1 -1
  11. package/dist/cjs/cli/init.js.map +1 -1
  12. package/dist/cjs/cli/map.js.map +1 -1
  13. package/dist/cjs/cli/named.js.map +1 -1
  14. package/dist/cjs/cli/path.js.map +1 -1
  15. package/dist/cjs/cli/peek.js.map +1 -1
  16. package/dist/cjs/cli/related.js.map +1 -1
  17. package/dist/cjs/cli/search.js.map +1 -1
  18. package/dist/cjs/cli/shared.js.map +1 -1
  19. package/dist/cjs/cli/sql.js.map +1 -1
  20. package/dist/cjs/cli/status.js.map +1 -1
  21. package/dist/cjs/cli/watch.js.map +1 -1
  22. package/dist/cjs/cli.js.map +1 -1
  23. package/dist/cjs/commands/index.js.map +1 -1
  24. package/dist/cjs/commands/map.js.map +1 -1
  25. package/dist/cjs/commands/path.js.map +1 -1
  26. package/dist/cjs/commands/peek.js.map +1 -1
  27. package/dist/cjs/commands/related.js.map +1 -1
  28. package/dist/cjs/commands/scope.js.map +1 -1
  29. package/dist/cjs/commands/search.js.map +1 -1
  30. package/dist/cjs/commands/signals.js.map +1 -1
  31. package/dist/cjs/commands/snapshot.js.map +1 -1
  32. package/dist/cjs/commands/status.js.map +1 -1
  33. package/dist/cjs/config/access.js.map +1 -1
  34. package/dist/cjs/config/index.js.map +1 -1
  35. package/dist/cjs/config/load.js.map +1 -1
  36. package/dist/cjs/config/resolve.js.map +1 -1
  37. package/dist/cjs/config/signals.js.map +1 -1
  38. package/dist/cjs/config/types.js.map +1 -1
  39. package/dist/cjs/config/validate.js.map +1 -1
  40. package/dist/cjs/embed/cohere.js.map +1 -1
  41. package/dist/cjs/embed/distribution.js.map +1 -1
  42. package/dist/cjs/embed/endpoint.js.map +1 -1
  43. package/dist/cjs/embed/handoff.js.map +1 -1
  44. package/dist/cjs/embed/http.js.map +1 -1
  45. package/dist/cjs/embed/identity.js.map +1 -1
  46. package/dist/cjs/embed/langfit.js.map +1 -1
  47. package/dist/cjs/embed/languages.js.map +1 -1
  48. package/dist/cjs/embed/openai.js.map +1 -1
  49. package/dist/cjs/embed/query.js.map +1 -1
  50. package/dist/cjs/embed/registry.js.map +1 -1
  51. package/dist/cjs/embed/static.js.map +1 -1
  52. package/dist/cjs/embed/store.js.map +1 -1
  53. package/dist/cjs/embed/types.js.map +1 -1
  54. package/dist/cjs/errors.js.map +1 -1
  55. package/dist/cjs/features/embed.js.map +1 -1
  56. package/dist/cjs/features/fences.js.map +1 -1
  57. package/dist/cjs/features/index.js.map +1 -1
  58. package/dist/cjs/features/links.js.map +1 -1
  59. package/dist/cjs/features/rank.js.map +1 -1
  60. package/dist/cjs/features/sections.js.map +1 -1
  61. package/dist/cjs/features/tags.js.map +1 -1
  62. package/dist/cjs/graph/graph.js.map +1 -1
  63. package/dist/cjs/graph/traverse.js.map +1 -1
  64. package/dist/cjs/index.js.map +1 -1
  65. package/dist/cjs/lib/atomic-write.js.map +1 -1
  66. package/dist/cjs/lib/guarded-tick.js.map +1 -1
  67. package/dist/cjs/lib/serial-query.js.map +1 -1
  68. package/dist/cjs/lib/watch-notification.js.map +1 -1
  69. package/dist/cjs/lib/worker-file.js.map +1 -1
  70. package/dist/cjs/output/column-hint.js.map +1 -1
  71. package/dist/cjs/output/output.js.map +1 -1
  72. package/dist/cjs/output/progress.js.map +1 -1
  73. package/dist/cjs/output/search-error.js.map +1 -1
  74. package/dist/cjs/scan/frontmatter.js.map +1 -1
  75. package/dist/cjs/scan/index.js.map +1 -1
  76. package/dist/cjs/scan/list.js.map +1 -1
  77. package/dist/cjs/scan/pool.js.map +1 -1
  78. package/dist/cjs/scan/reparse.js.map +1 -1
  79. package/dist/cjs/scan/worker-error.js.map +1 -1
  80. package/dist/cjs/store/batch.js.map +1 -1
  81. package/dist/cjs/store/builder.js.map +1 -1
  82. package/dist/cjs/store/cache.js.map +1 -1
  83. package/dist/cjs/store/duckdb/batch.js.map +1 -1
  84. package/dist/cjs/store/duckdb/connection.js.map +1 -1
  85. package/dist/cjs/store/duckdb/fieldStats.js.map +1 -1
  86. package/dist/cjs/store/duckdb/lexical.d.cts +1 -6
  87. package/dist/cjs/store/duckdb/lexical.d.ts +1 -6
  88. package/dist/cjs/store/duckdb/lexical.js +28 -39
  89. package/dist/cjs/store/duckdb/lexical.js.map +1 -1
  90. package/dist/cjs/store/duckdb/native.d.cts +1 -2
  91. package/dist/cjs/store/duckdb/native.d.ts +1 -2
  92. package/dist/cjs/store/duckdb/native.js +1 -6
  93. package/dist/cjs/store/duckdb/native.js.map +1 -1
  94. package/dist/cjs/store/duckdb/open.js.map +1 -1
  95. package/dist/cjs/store/duckdb/ordered-bm25.d.cts +3 -16
  96. package/dist/cjs/store/duckdb/ordered-bm25.d.ts +3 -16
  97. package/dist/cjs/store/duckdb/ordered-bm25.js +27 -79
  98. package/dist/cjs/store/duckdb/ordered-bm25.js.map +1 -1
  99. package/dist/cjs/store/duckdb/reconcile.js.map +1 -1
  100. package/dist/cjs/store/duckdb/sql-functions.js.map +1 -1
  101. package/dist/cjs/store/duckdb/store.js.map +1 -1
  102. package/dist/cjs/store/duckdb/vectors.js.map +1 -1
  103. package/dist/cjs/store/embed-scope.js.map +1 -1
  104. package/dist/cjs/store/feature-scope.js.map +1 -1
  105. package/dist/cjs/store/index.js.map +1 -1
  106. package/dist/cjs/store/lock-wait.js.map +1 -1
  107. package/dist/cjs/store/native.js.map +1 -1
  108. package/dist/cjs/store/open.js.map +1 -1
  109. package/dist/cjs/store/preset-scope.js.map +1 -1
  110. package/dist/cjs/store/readiness.js.map +1 -1
  111. package/dist/cjs/store/reconcile.js.map +1 -1
  112. package/dist/cjs/store/shared.js.map +1 -1
  113. package/dist/cjs/store/signature.js.map +1 -1
  114. package/dist/cjs/store/sql-functions.js.map +1 -1
  115. package/dist/cjs/store/sqlite/connection.js.map +1 -1
  116. package/dist/cjs/store/sqlite/fieldStats.js.map +1 -1
  117. package/dist/cjs/store/sqlite/lexical.js.map +1 -1
  118. package/dist/cjs/store/sqlite/open.js.map +1 -1
  119. package/dist/cjs/store/sqlite/reconcile.js.map +1 -1
  120. package/dist/cjs/store/sqlite/sql-functions.js.map +1 -1
  121. package/dist/cjs/store/sqlite/store.js.map +1 -1
  122. package/dist/cjs/store/sqlite/vectors.js.map +1 -1
  123. package/dist/cjs/store/stages.js.map +1 -1
  124. package/dist/cjs/store/transaction.js.map +1 -1
  125. package/dist/cjs/store/turso/connection.js.map +1 -1
  126. package/dist/cjs/store/turso/fieldStats.js.map +1 -1
  127. package/dist/cjs/store/turso/lexical-text.js.map +1 -1
  128. package/dist/cjs/store/turso/lexical.js.map +1 -1
  129. package/dist/cjs/store/turso/native.js.map +1 -1
  130. package/dist/cjs/store/turso/open.js.map +1 -1
  131. package/dist/cjs/store/turso/reconcile.js.map +1 -1
  132. package/dist/cjs/store/turso/sql-functions.js.map +1 -1
  133. package/dist/cjs/store/turso/store.js.map +1 -1
  134. package/dist/cjs/store/turso/vectors.js.map +1 -1
  135. package/dist/cjs/store/types.js.map +1 -1
  136. package/dist/cjs/store/vectors.js.map +1 -1
  137. package/dist/cjs/text/segment.js.map +1 -1
  138. package/dist/cjs/text/strip.js.map +1 -1
  139. package/dist/cjs/watch-claim.js.map +1 -1
  140. package/dist/cjs/watch.js.map +1 -1
  141. package/dist/cjs/workers/parse.js.map +1 -1
  142. package/dist/cjs/workers/watch-heartbeat.js.map +1 -1
  143. package/dist/esm/chunk/extract.js.map +1 -1
  144. package/dist/esm/chunk/group.js.map +1 -1
  145. package/dist/esm/chunk/index.js.map +1 -1
  146. package/dist/esm/chunk/parse.js.map +1 -1
  147. package/dist/esm/chunk/parser.js.map +1 -1
  148. package/dist/esm/chunk/tokens.js.map +1 -1
  149. package/dist/esm/chunk/types.js.map +1 -1
  150. package/dist/esm/chunk/version.js.map +1 -1
  151. package/dist/esm/cli/build.js.map +1 -1
  152. package/dist/esm/cli/download.js.map +1 -1
  153. package/dist/esm/cli/index.js.map +1 -1
  154. package/dist/esm/cli/init.js.map +1 -1
  155. package/dist/esm/cli/map.js.map +1 -1
  156. package/dist/esm/cli/named.js.map +1 -1
  157. package/dist/esm/cli/path.js.map +1 -1
  158. package/dist/esm/cli/peek.js.map +1 -1
  159. package/dist/esm/cli/related.js.map +1 -1
  160. package/dist/esm/cli/search.js.map +1 -1
  161. package/dist/esm/cli/shared.js.map +1 -1
  162. package/dist/esm/cli/sql.js.map +1 -1
  163. package/dist/esm/cli/status.js.map +1 -1
  164. package/dist/esm/cli/types.js.map +1 -1
  165. package/dist/esm/cli/watch.js.map +1 -1
  166. package/dist/esm/cli.js.map +1 -1
  167. package/dist/esm/commands/index.js.map +1 -1
  168. package/dist/esm/commands/map.js.map +1 -1
  169. package/dist/esm/commands/path.js.map +1 -1
  170. package/dist/esm/commands/peek.js.map +1 -1
  171. package/dist/esm/commands/related.js.map +1 -1
  172. package/dist/esm/commands/scope.js.map +1 -1
  173. package/dist/esm/commands/search.js.map +1 -1
  174. package/dist/esm/commands/signals.js.map +1 -1
  175. package/dist/esm/commands/snapshot.js.map +1 -1
  176. package/dist/esm/commands/status.js.map +1 -1
  177. package/dist/esm/config/access.js.map +1 -1
  178. package/dist/esm/config/index.js.map +1 -1
  179. package/dist/esm/config/load.js.map +1 -1
  180. package/dist/esm/config/resolve.js.map +1 -1
  181. package/dist/esm/config/signals.js.map +1 -1
  182. package/dist/esm/config/types.js.map +1 -1
  183. package/dist/esm/config/validate.js.map +1 -1
  184. package/dist/esm/embed/cohere.js.map +1 -1
  185. package/dist/esm/embed/distribution.js.map +1 -1
  186. package/dist/esm/embed/endpoint.js.map +1 -1
  187. package/dist/esm/embed/handoff.js.map +1 -1
  188. package/dist/esm/embed/http.js.map +1 -1
  189. package/dist/esm/embed/identity.js.map +1 -1
  190. package/dist/esm/embed/langfit.js.map +1 -1
  191. package/dist/esm/embed/languages.js.map +1 -1
  192. package/dist/esm/embed/openai.js.map +1 -1
  193. package/dist/esm/embed/query.js.map +1 -1
  194. package/dist/esm/embed/registry.js.map +1 -1
  195. package/dist/esm/embed/static.js.map +1 -1
  196. package/dist/esm/embed/store.js.map +1 -1
  197. package/dist/esm/embed/types.js.map +1 -1
  198. package/dist/esm/errors.js.map +1 -1
  199. package/dist/esm/features/embed.js.map +1 -1
  200. package/dist/esm/features/fences.js.map +1 -1
  201. package/dist/esm/features/index.js.map +1 -1
  202. package/dist/esm/features/links.js.map +1 -1
  203. package/dist/esm/features/rank.js.map +1 -1
  204. package/dist/esm/features/sections.js.map +1 -1
  205. package/dist/esm/features/tags.js.map +1 -1
  206. package/dist/esm/features/types.js.map +1 -1
  207. package/dist/esm/graph/graph.js.map +1 -1
  208. package/dist/esm/graph/traverse.js.map +1 -1
  209. package/dist/esm/index.js.map +1 -1
  210. package/dist/esm/lib/atomic-write.js.map +1 -1
  211. package/dist/esm/lib/guarded-tick.js.map +1 -1
  212. package/dist/esm/lib/serial-query.js.map +1 -1
  213. package/dist/esm/lib/watch-notification.js.map +1 -1
  214. package/dist/esm/lib/worker-file.js.map +1 -1
  215. package/dist/esm/output/column-hint.js.map +1 -1
  216. package/dist/esm/output/output.js.map +1 -1
  217. package/dist/esm/output/progress.js.map +1 -1
  218. package/dist/esm/output/search-error.js.map +1 -1
  219. package/dist/esm/scan/frontmatter.js.map +1 -1
  220. package/dist/esm/scan/index.js.map +1 -1
  221. package/dist/esm/scan/list.js.map +1 -1
  222. package/dist/esm/scan/pool.js.map +1 -1
  223. package/dist/esm/scan/reparse.js.map +1 -1
  224. package/dist/esm/scan/worker-error.js.map +1 -1
  225. package/dist/esm/store/batch.js.map +1 -1
  226. package/dist/esm/store/builder.js.map +1 -1
  227. package/dist/esm/store/cache.js.map +1 -1
  228. package/dist/esm/store/duckdb/batch.js.map +1 -1
  229. package/dist/esm/store/duckdb/connection.js.map +1 -1
  230. package/dist/esm/store/duckdb/fieldStats.js.map +1 -1
  231. package/dist/esm/store/duckdb/lexical.d.ts +1 -6
  232. package/dist/esm/store/duckdb/lexical.js +13 -17
  233. package/dist/esm/store/duckdb/lexical.js.map +1 -1
  234. package/dist/esm/store/duckdb/native.d.ts +1 -2
  235. package/dist/esm/store/duckdb/native.js +1 -3
  236. package/dist/esm/store/duckdb/native.js.map +1 -1
  237. package/dist/esm/store/duckdb/open.js.map +1 -1
  238. package/dist/esm/store/duckdb/ordered-bm25.d.ts +3 -16
  239. package/dist/esm/store/duckdb/ordered-bm25.js +18 -54
  240. package/dist/esm/store/duckdb/ordered-bm25.js.map +1 -1
  241. package/dist/esm/store/duckdb/reconcile.js.map +1 -1
  242. package/dist/esm/store/duckdb/sql-functions.js.map +1 -1
  243. package/dist/esm/store/duckdb/store.js.map +1 -1
  244. package/dist/esm/store/duckdb/vectors.js.map +1 -1
  245. package/dist/esm/store/embed-scope.js.map +1 -1
  246. package/dist/esm/store/feature-scope.js.map +1 -1
  247. package/dist/esm/store/index.js.map +1 -1
  248. package/dist/esm/store/lock-wait.js.map +1 -1
  249. package/dist/esm/store/native.js.map +1 -1
  250. package/dist/esm/store/open.js.map +1 -1
  251. package/dist/esm/store/preset-scope.js.map +1 -1
  252. package/dist/esm/store/readiness.js.map +1 -1
  253. package/dist/esm/store/reconcile.js.map +1 -1
  254. package/dist/esm/store/shared.js.map +1 -1
  255. package/dist/esm/store/signature.js.map +1 -1
  256. package/dist/esm/store/sql-functions.js.map +1 -1
  257. package/dist/esm/store/sqlite/connection.js.map +1 -1
  258. package/dist/esm/store/sqlite/fieldStats.js.map +1 -1
  259. package/dist/esm/store/sqlite/lexical.js.map +1 -1
  260. package/dist/esm/store/sqlite/open.js.map +1 -1
  261. package/dist/esm/store/sqlite/reconcile.js.map +1 -1
  262. package/dist/esm/store/sqlite/sql-functions.js.map +1 -1
  263. package/dist/esm/store/sqlite/store.js.map +1 -1
  264. package/dist/esm/store/sqlite/vectors.js.map +1 -1
  265. package/dist/esm/store/stages.js.map +1 -1
  266. package/dist/esm/store/transaction.js.map +1 -1
  267. package/dist/esm/store/turso/connection.js.map +1 -1
  268. package/dist/esm/store/turso/fieldStats.js.map +1 -1
  269. package/dist/esm/store/turso/lexical-text.js.map +1 -1
  270. package/dist/esm/store/turso/lexical.js.map +1 -1
  271. package/dist/esm/store/turso/native.js.map +1 -1
  272. package/dist/esm/store/turso/open.js.map +1 -1
  273. package/dist/esm/store/turso/reconcile.js.map +1 -1
  274. package/dist/esm/store/turso/sql-functions.js.map +1 -1
  275. package/dist/esm/store/turso/store.js.map +1 -1
  276. package/dist/esm/store/turso/vectors.js.map +1 -1
  277. package/dist/esm/store/types.js.map +1 -1
  278. package/dist/esm/store/vectors.js.map +1 -1
  279. package/dist/esm/text/segment.js.map +1 -1
  280. package/dist/esm/text/strip.js.map +1 -1
  281. package/dist/esm/watch-claim.js.map +1 -1
  282. package/dist/esm/watch.js.map +1 -1
  283. package/dist/esm/workers/parse.js.map +1 -1
  284. package/dist/esm/workers/watch-heartbeat.js.map +1 -1
  285. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/graph/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.\n\nimport { serialQuery } from '../lib/serial-query.ts';\nimport type { Store } from '../store/types.ts';\n\ntype Direction = 'forward' | 'reverse' | 'both';\n\nexport interface FindPathOptions {\n directed?: boolean;\n maxDepth?: number;\n allowed?: Set<string>;\n}\n\nasync function resetVisited(store: Store): Promise<void> {\n await store.exec('DROP TABLE IF EXISTS temp.visited');\n await store.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.\nasync function setupAllowed(store: Store, allowed: Set<string>, extra?: string): Promise<void> {\n const all = new Set(allowed);\n if (extra !== undefined) all.add(extra);\n await store.exec('DROP TABLE IF EXISTS temp.allowed_nodes');\n await store.exec('CREATE TEMP TABLE allowed_nodes (path TEXT PRIMARY KEY)');\n await store.runBatch(\n 'INSERT INTO allowed_nodes (path) VALUES (?)',\n [...all].map((p) => [p])\n );\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, inserted at the new depth (?2); RETURNING gives 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\nRETURNING path`;\n}\n\nasync function reconstructPath(store: Store, to: string): Promise<string[]> {\n const lookup = await store.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 = (await 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(store: Store, from: string, to: string, opts: FindPathOptions = {}): Promise<string[] | null> {\n return serialQuery(store, () => store.transaction(() => findPathInSnapshot(store, from, to, opts)));\n}\n\n// Internal entry for the scoped command wrapper, whose transaction also owns endpoint resolution\n// and scope reads. Direct graph callers use findPath() above and receive the same snapshot rule.\nexport async function findPathInSnapshot(store: Store, from: string, to: string, opts: FindPathOptions): Promise<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 await resetVisited(store);\n const insertStart = await store.prepare('INSERT INTO visited (path, depth, pred) VALUES (?, 0, NULL)');\n await insertStart.run(from);\n if (opts.allowed) await setupAllowed(store, opts.allowed, to);\n\n const stmt = await store.prepare(ringSql(direction, !!opts.allowed));\n for (let ring = 1; ring <= maxDepth; ring++) {\n const rows = (await stmt.all(ring - 1, ring)) as Array<{ path: string }>;\n if (rows.length === 0) break;\n if (rows.some((row) => row.path === to)) return reconstructPath(store, to);\n }\n return null;\n}\n"],"names":["findPath","findPathInSnapshot","resetVisited","store","exec","setupAllowed","allowed","extra","all","Set","undefined","add","runBatch","map","p","candidateSelect","direction","forward","reverse","ringSql","hasAllowed","reconstructPath","to","lookup","path","cur","row","prepare","push","get","pred","from","opts","serialQuery","transaction","maxDepth","insertStart","stmt","ring","rows","directed","Infinity","run","length","some"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/graph/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.\n\nimport { serialQuery } from '../lib/serial-query.ts';\nimport type { Store } from '../store/types.ts';\n\ntype Direction = 'forward' | 'reverse' | 'both';\n\nexport interface FindPathOptions {\n directed?: boolean;\n maxDepth?: number;\n allowed?: Set<string>;\n}\n\nasync function resetVisited(store: Store): Promise<void> {\n await store.exec('DROP TABLE IF EXISTS temp.visited');\n await store.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.\nasync function setupAllowed(store: Store, allowed: Set<string>, extra?: string): Promise<void> {\n const all = new Set(allowed);\n if (extra !== undefined) all.add(extra);\n await store.exec('DROP TABLE IF EXISTS temp.allowed_nodes');\n await store.exec('CREATE TEMP TABLE allowed_nodes (path TEXT PRIMARY KEY)');\n await store.runBatch(\n 'INSERT INTO allowed_nodes (path) VALUES (?)',\n [...all].map((p) => [p])\n );\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, inserted at the new depth (?2); RETURNING gives 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\nRETURNING path`;\n}\n\nasync function reconstructPath(store: Store, to: string): Promise<string[]> {\n const lookup = await store.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 = (await 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(store: Store, from: string, to: string, opts: FindPathOptions = {}): Promise<string[] | null> {\n return serialQuery(store, () => store.transaction(() => findPathInSnapshot(store, from, to, opts)));\n}\n\n// Internal entry for the scoped command wrapper, whose transaction also owns endpoint resolution\n// and scope reads. Direct graph callers use findPath() above and receive the same snapshot rule.\nexport async function findPathInSnapshot(store: Store, from: string, to: string, opts: FindPathOptions): Promise<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 await resetVisited(store);\n const insertStart = await store.prepare('INSERT INTO visited (path, depth, pred) VALUES (?, 0, NULL)');\n await insertStart.run(from);\n if (opts.allowed) await setupAllowed(store, opts.allowed, to);\n\n const stmt = await store.prepare(ringSql(direction, !!opts.allowed));\n for (let ring = 1; ring <= maxDepth; ring++) {\n const rows = (await stmt.all(ring - 1, ring)) as Array<{ path: string }>;\n if (rows.length === 0) break;\n if (rows.some((row) => row.path === to)) return reconstructPath(store, to);\n }\n return null;\n}\n"],"names":["findPath","findPathInSnapshot","resetVisited","store","exec","setupAllowed","allowed","extra","all","Set","undefined","add","runBatch","map","p","candidateSelect","direction","forward","reverse","ringSql","hasAllowed","reconstructPath","to","lookup","path","cur","row","prepare","push","get","pred","from","opts","serialQuery","transaction","maxDepth","insertStart","stmt","ring","rows","directed","Infinity","run","length","some"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/index.ts"],"sourcesContent":["// Public library API. Deliberately small: every export is a stability promise;\n// internals (feature registry, graph, scan, meta) stay module-private.\n\nexport type { PathOptions, Peek, PeekOptions, PeekSection, PresetCoverage, RelatedOptions, RelatedResult, SearchOptions, SearchResult, SearchResultVia, SearchSignalContribution, TreeMap, TreeMapField, TreeMapHub, TreeMapRecent } from './commands/index.ts';\nexport { findPath, mapTree, peek, presetCoverage, relatedNotes, search } from './commands/index.ts';\nexport type { Config, EmbedConfig, FeatureName, InitOverrides, LoadConfigOptions, Preset, ResolvedConfig, SavedQuery, SavedSearch, SearchOverrides, SignalName, SignalWeights, StoreName } from './config/index.ts';\nexport { CONFIG_FILENAME, initConfig, loadConfig, migrateConfig, SIGNAL_NAMES, STATE_DIR, STORE_NAMES, SUPPORTED_CONFIG_VERSION } from './config/index.ts';\nexport type { SenseErrorCode } from './errors.ts';\nexport { SenseError } from './errors.ts';\nexport type { Format, Row, RowFormat } from './output/output.ts';\nexport { printRows } from './output/output.ts';\nexport type { BuildOptions, BuildResult, OpenOptions, OpenResult, Stages } from './store/index.ts';\nexport { buildIndex as build, CAPABILITY_NAMES, clearCache, openStore as open } from './store/index.ts';\nexport type { Capability, DocumentStore, FieldStat, LexicalHit, LexicalIndex, LexicalQueryOptions, RawStatement, RunResult, SqlSession, Statement, Store, VectorCandidate, VectorSimilar, VectorStore, VectorWriteRow } from './store/types.ts';\n\nexport type { WatchEvent, WatchOptions } from './watch.ts';\nexport { runWatch } from './watch.ts';\n"],"names":["CAPABILITY_NAMES","CONFIG_FILENAME","SIGNAL_NAMES","STATE_DIR","STORE_NAMES","SUPPORTED_CONFIG_VERSION","SenseError","build","buildIndex","clearCache","findPath","initConfig","loadConfig","mapTree","migrateConfig","open","openStore","peek","presetCoverage","printRows","relatedNotes","runWatch","search"],"mappings":"AAAA,+EAA+E;AAC/E,uEAAuE;;;;;;;;;;;;QAWzCA;eAAAA,0BAAgB;;QANrCC;eAAAA,yBAAe;;QAAyCC;eAAAA,sBAAY;;QAAEC;eAAAA,mBAAS;;QAAEC;eAAAA,qBAAW;;QAAEC;eAAAA,kCAAwB;;QAEtHC;eAAAA,oBAAU;;QAIIC;eAAdC,oBAAU;;QAA6BC;eAAAA,oBAAU;;QARjDC;eAAAA,iBAAQ;;QAESC;eAAAA,oBAAU;;QAAEC;eAAAA,oBAAU;;QAF7BC;eAAAA,gBAAO;;QAEwBC;eAAAA,uBAAa;;QAMUC;eAAbC,mBAAS;;QARzCC;eAAAA,aAAI;;QAAEC;eAAAA,uBAAc;;QAMvCC;eAAAA,mBAAS;;QANgCC;eAAAA,qBAAY;;QAYrDC;eAAAA,iBAAQ;;QAZ+CC;eAAAA,eAAM;;;uBAAQ;wBAEyD;wBAE5G;wBAED;wBAE2D;uBAI5D"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/index.ts"],"sourcesContent":["// Public library API. Deliberately small: every export is a stability promise;\n// internals (feature registry, graph, scan, meta) stay module-private.\n\nexport type { PathOptions, Peek, PeekOptions, PeekSection, PresetCoverage, RelatedOptions, RelatedResult, SearchOptions, SearchResult, SearchResultVia, SearchSignalContribution, TreeMap, TreeMapField, TreeMapHub, TreeMapRecent } from './commands/index.ts';\nexport { findPath, mapTree, peek, presetCoverage, relatedNotes, search } from './commands/index.ts';\nexport type { Config, EmbedConfig, FeatureName, InitOverrides, LoadConfigOptions, Preset, ResolvedConfig, SavedQuery, SavedSearch, SearchOverrides, SignalName, SignalWeights, StoreName } from './config/index.ts';\nexport { CONFIG_FILENAME, initConfig, loadConfig, migrateConfig, SIGNAL_NAMES, STATE_DIR, STORE_NAMES, SUPPORTED_CONFIG_VERSION } from './config/index.ts';\nexport type { SenseErrorCode } from './errors.ts';\nexport { SenseError } from './errors.ts';\nexport type { Format, Row, RowFormat } from './output/output.ts';\nexport { printRows } from './output/output.ts';\nexport type { BuildOptions, BuildResult, OpenOptions, OpenResult, Stages } from './store/index.ts';\nexport { buildIndex as build, CAPABILITY_NAMES, clearCache, openStore as open } from './store/index.ts';\nexport type { Capability, DocumentStore, FieldStat, LexicalHit, LexicalIndex, LexicalQueryOptions, RawStatement, RunResult, SqlSession, Statement, Store, VectorCandidate, VectorSimilar, VectorStore, VectorWriteRow } from './store/types.ts';\n\nexport type { WatchEvent, WatchOptions } from './watch.ts';\nexport { runWatch } from './watch.ts';\n"],"names":["CAPABILITY_NAMES","CONFIG_FILENAME","SIGNAL_NAMES","STATE_DIR","STORE_NAMES","SUPPORTED_CONFIG_VERSION","SenseError","build","buildIndex","clearCache","findPath","initConfig","loadConfig","mapTree","migrateConfig","open","openStore","peek","presetCoverage","printRows","relatedNotes","runWatch","search"],"mappings":"AAAA,+EAA+E;AAC/E,uEAAuE;;;;;;;;;;;;QAWzCA;eAAAA,0BAAgB;;QANrCC;eAAAA,yBAAe;;QAAyCC;eAAAA,sBAAY;;QAAEC;eAAAA,mBAAS;;QAAEC;eAAAA,qBAAW;;QAAEC;eAAAA,kCAAwB;;QAEtHC;eAAAA,oBAAU;;QAIIC;eAAdC,oBAAU;;QAA6BC;eAAAA,oBAAU;;QARjDC;eAAAA,iBAAQ;;QAESC;eAAAA,oBAAU;;QAAEC;eAAAA,oBAAU;;QAF7BC;eAAAA,gBAAO;;QAEwBC;eAAAA,uBAAa;;QAMUC;eAAbC,mBAAS;;QARzCC;eAAAA,aAAI;;QAAEC;eAAAA,uBAAc;;QAMvCC;eAAAA,mBAAS;;QANgCC;eAAAA,qBAAY;;QAYrDC;eAAAA,iBAAQ;;QAZ+CC;eAAAA,eAAM;;;uBAAQ;wBAEyD;wBAE5G;wBAED;wBAE2D;uBAI5D"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/lib/atomic-write.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { renameSync, unlinkSync, writeFileSync } from 'node:fs';\n\n// Stage-then-swap: write beside the target, then rename over it. A crash or full disk mid-write\n// leaves the target untouched instead of truncated. Matches embed/store.ts's model-download idiom.\nexport function writeFileAtomic(path: string, data: string | Buffer): void {\n const tmp = `${path}.${randomUUID()}.part`;\n let staged = false;\n try {\n writeFileSync(tmp, data, { flag: 'wx' });\n staged = true;\n renameSync(tmp, path);\n } catch (err) {\n // An exclusive-create collision belongs to another writer; never remove its staging file.\n if (staged || !(err instanceof Error && 'code' in err && err.code === 'EEXIST')) {\n try {\n unlinkSync(tmp);\n } catch {\n // best-effort cleanup; the original error below is what matters\n }\n }\n throw err;\n }\n}\n"],"names":["writeFileAtomic","path","data","tmp","randomUUID","staged","writeFileSync","flag","renameSync","err","Error","code","unlinkSync"],"mappings":";;;;+BAKgBA;;;eAAAA;;;0BALW;sBAC2B;;;;;;;AAI/C,SAASA,gBAAgBC,IAAY,EAAEC,IAAqB;IACjE,IAAMC,MAAM,AAAC,GAAUC,OAARH,MAAK,KAAgB,OAAbG,IAAAA,sBAAU,KAAG;IACpC,IAAIC,SAAS;IACb,IAAI;QACFC,IAAAA,qBAAa,EAACH,KAAKD,MAAM;YAAEK,MAAM;QAAK;QACtCF,SAAS;QACTG,IAAAA,kBAAU,EAACL,KAAKF;IAClB,EAAE,OAAOQ,KAAK;QACZ,0FAA0F;QAC1F,IAAIJ,UAAU,CAAEI,CAAAA,AAAG,YAAHA,KAAeC,UAAS,UAAUD,OAAOA,IAAIE,IAAI,KAAK,QAAO,GAAI;YAC/E,IAAI;gBACFC,IAAAA,kBAAU,EAACT;YACb,EAAE,eAAM;YACN,gEAAgE;YAClE;QACF;QACA,MAAMM;IACR;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/lib/atomic-write.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport { renameSync, unlinkSync, writeFileSync } from 'node:fs';\n\n// Stage-then-swap: write beside the target, then rename over it. A crash or full disk mid-write\n// leaves the target untouched instead of truncated. Matches embed/store.ts's model-download idiom.\nexport function writeFileAtomic(path: string, data: string | Buffer): void {\n const tmp = `${path}.${randomUUID()}.part`;\n let staged = false;\n try {\n writeFileSync(tmp, data, { flag: 'wx' });\n staged = true;\n renameSync(tmp, path);\n } catch (err) {\n // An exclusive-create collision belongs to another writer; never remove its staging file.\n if (staged || !(err instanceof Error && 'code' in err && err.code === 'EEXIST')) {\n try {\n unlinkSync(tmp);\n } catch {\n // best-effort cleanup; the original error below is what matters\n }\n }\n throw err;\n }\n}\n"],"names":["writeFileAtomic","path","data","tmp","randomUUID","staged","writeFileSync","flag","renameSync","err","Error","code","unlinkSync"],"mappings":";;;;+BAKgBA;;;eAAAA;;;0BALW;sBAC2B;;;;;;;AAI/C,SAASA,gBAAgBC,IAAY,EAAEC,IAAqB;IACjE,IAAMC,MAAM,AAAC,GAAUC,OAARH,MAAK,KAAgB,OAAbG,IAAAA,sBAAU,KAAG;IACpC,IAAIC,SAAS;IACb,IAAI;QACFC,IAAAA,qBAAa,EAACH,KAAKD,MAAM;YAAEK,MAAM;QAAK;QACtCF,SAAS;QACTG,IAAAA,kBAAU,EAACL,KAAKF;IAClB,EAAE,OAAOQ,KAAK;QACZ,0FAA0F;QAC1F,IAAIJ,UAAU,CAAEI,CAAAA,AAAG,YAAHA,KAAeC,UAAS,UAAUD,OAAOA,IAAIE,IAAI,KAAK,QAAO,GAAI;YAC/E,IAAI;gBACFC,IAAAA,kBAAU,EAACT;YACb,EAAE,eAAM;YACN,gEAAgE;YAClE;QACF;QACA,MAAMM;IACR;AACF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/lib/guarded-tick.ts"],"sourcesContent":["// Wraps an async interval tick so a rejection (e.g. a store closed mid-await) never\n// escapes as an unhandled rejection, and so a skip() guard can suppress the call entirely.\nexport function guardedTick(fn: () => Promise<void>, skip: () => boolean): () => void {\n return () => {\n if (skip()) return;\n fn().catch(() => {});\n };\n}\n"],"names":["guardedTick","fn","skip","catch"],"mappings":"AAAA,oFAAoF;AACpF,2FAA2F;;;;;+BAC3EA;;;eAAAA;;;AAAT,SAASA,YAAYC,EAAuB,EAAEC,IAAmB;IACtE,OAAO;QACL,IAAIA,QAAQ;QACZD,KAAKE,KAAK,CAAC,YAAO;IACpB;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/lib/guarded-tick.ts"],"sourcesContent":["// Wraps an async interval tick so a rejection (e.g. a store closed mid-await) never\n// escapes as an unhandled rejection, and so a skip() guard can suppress the call entirely.\nexport function guardedTick(fn: () => Promise<void>, skip: () => boolean): () => void {\n return () => {\n if (skip()) return;\n fn().catch(() => {});\n };\n}\n"],"names":["guardedTick","fn","skip","catch"],"mappings":"AAAA,oFAAoF;AACpF,2FAA2F;;;;;+BAC3EA;;;eAAAA;;;AAAT,SAASA,YAAYC,EAAuB,EAAEC,IAAmB;IACtE,OAAO;QACL,IAAIA,QAAQ;QACZD,KAAKE,KAAK,CAAC,YAAO;IACpB;AACF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/lib/serial-query.ts"],"sourcesContent":["const pending = new WeakMap<object, Promise<void>>();\n\n// High-level queries share temporary tables and transaction state on a handle.\n// Raw SQL and handle closure remain caller-owned and must await these queries.\nexport function serialQuery<T>(handle: object, query: () => Promise<T>): Promise<T> {\n const result = (pending.get(handle) ?? Promise.resolve()).then(query);\n const settled = result.then(\n () => {},\n () => {}\n );\n pending.set(handle, settled);\n void settled.then(() => {\n if (pending.get(handle) === settled) pending.delete(handle);\n });\n return result;\n}\n"],"names":["serialQuery","pending","WeakMap","handle","query","result","get","Promise","resolve","then","settled","set","delete"],"mappings":";;;;+BAIgBA;;;eAAAA;;;AAJhB,IAAMC,UAAU,IAAIC;AAIb,SAASF,YAAeG,MAAc,EAAEC,KAAuB;QACpDH;IAAhB,IAAMI,SAAS,EAACJ,eAAAA,QAAQK,GAAG,CAACH,qBAAZF,0BAAAA,eAAuBM,QAAQC,OAAO,IAAIC,IAAI,CAACL;IAC/D,IAAMM,UAAUL,OAAOI,IAAI,CACzB,YAAO,GACP,YAAO;IAETR,QAAQU,GAAG,CAACR,QAAQO;IACpB,KAAKA,QAAQD,IAAI,CAAC;QAChB,IAAIR,QAAQK,GAAG,CAACH,YAAYO,SAAST,QAAQW,MAAM,CAACT;IACtD;IACA,OAAOE;AACT"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/lib/serial-query.ts"],"sourcesContent":["const pending = new WeakMap<object, Promise<void>>();\n\n// High-level queries share temporary tables and transaction state on a handle.\n// Raw SQL and handle closure remain caller-owned and must await these queries.\nexport function serialQuery<T>(handle: object, query: () => Promise<T>): Promise<T> {\n const result = (pending.get(handle) ?? Promise.resolve()).then(query);\n const settled = result.then(\n () => {},\n () => {}\n );\n pending.set(handle, settled);\n void settled.then(() => {\n if (pending.get(handle) === settled) pending.delete(handle);\n });\n return result;\n}\n"],"names":["serialQuery","pending","WeakMap","handle","query","result","get","Promise","resolve","then","settled","set","delete"],"mappings":";;;;+BAIgBA;;;eAAAA;;;AAJhB,IAAMC,UAAU,IAAIC;AAIb,SAASF,YAAeG,MAAc,EAAEC,KAAuB;QACpDH;IAAhB,IAAMI,SAAS,EAACJ,eAAAA,QAAQK,GAAG,CAACH,qBAAZF,0BAAAA,eAAuBM,QAAQC,OAAO,IAAIC,IAAI,CAACL;IAC/D,IAAMM,UAAUL,OAAOI,IAAI,CACzB,YAAO,GACP,YAAO;IAETR,QAAQU,GAAG,CAACR,QAAQO;IACpB,KAAKA,QAAQD,IAAI,CAAC;QAChB,IAAIR,QAAQK,GAAG,CAACH,YAAYO,SAAST,QAAQW,MAAM,CAACT;IACtD;IACA,OAAOE;AACT"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/lib/watch-notification.ts"],"sourcesContent":["import { STATE_DIR } from '../config/types.ts';\n\nexport function shouldReconcileWatchNotification(filename: string | Buffer | null): boolean {\n return typeof filename !== 'string' || !filename.startsWith(STATE_DIR);\n}\n"],"names":["shouldReconcileWatchNotification","filename","startsWith","STATE_DIR"],"mappings":";;;;+BAEgBA;;;eAAAA;;;uBAFU;AAEnB,SAASA,iCAAiCC,QAAgC;IAC/E,OAAO,OAAOA,aAAa,YAAY,CAACA,SAASC,UAAU,CAACC,kBAAS;AACvE"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/lib/watch-notification.ts"],"sourcesContent":["import { STATE_DIR } from '../config/types.ts';\n\nexport function shouldReconcileWatchNotification(filename: string | Buffer | null): boolean {\n return typeof filename !== 'string' || !filename.startsWith(STATE_DIR);\n}\n"],"names":["shouldReconcileWatchNotification","filename","startsWith","STATE_DIR"],"mappings":";;;;+BAEgBA;;;eAAAA;;;uBAFU;AAEnB,SAASA,iCAAiCC,QAAgC;IAC/E,OAAO,OAAOA,aAAa,YAAY,CAACA,SAASC,UAAU,CAACC,kBAAS;AACvE"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/lib/worker-file.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\n\nlet packageRoot: string | undefined;\n\n// Workers load emitted CommonJS because a fresh worker thread does not inherit the source TS loader.\n// Resolve the package lazily so callers that never spawn a worker do no filesystem work here.\nexport function resolveWorkerFile(name: string): string {\n if (!packageRoot) {\n const load = createRequire(import.meta.url);\n for (const rel of ['..', '../..', '../../..']) {\n try {\n if ((load(`${rel}/package.json`) as { name?: string }).name === 'sensemaking') {\n packageRoot = dirname(load.resolve(`${rel}/package.json`));\n break;\n }\n } catch {}\n }\n }\n if (!packageRoot) throw new Error(`cannot locate the sensemaking package root, so the ${name} worker cannot be found; run npm run build`);\n return join(packageRoot, 'dist', 'cjs', 'workers', `${name}.js`);\n}\n"],"names":["resolveWorkerFile","packageRoot","name","load","createRequire","rel","dirname","resolve","Error","join"],"mappings":";;;;+BAOgBA;;;eAAAA;;;0BAPc;wBACA;AAE9B,IAAIC;AAIG,SAASD,kBAAkBE,IAAY;IAC5C,IAAI,CAACD,aAAa;QAChB,IAAME,OAAOC,IAAAA,yBAAa,EAAC;QAC3B,gBAAkB,QAAA;YAAC;YAAM;YAAS;SAAW,OAA3B,mBAA6B;gBAApCC,MAAO;YAChB,IAAI;gBACF,IAAI,AAACF,KAAK,AAAC,GAAM,OAAJE,KAAI,kBAAsCH,IAAI,KAAK,eAAe;oBAC7ED,cAAcK,IAAAA,iBAAO,EAACH,KAAKI,OAAO,CAAC,AAAC,GAAM,OAAJF,KAAI;oBAC1C;gBACF;YACF,EAAE,eAAM,CAAC;QACX;IACF;IACA,IAAI,CAACJ,aAAa,MAAM,IAAIO,MAAM,AAAC,sDAA0D,OAALN,MAAK;IAC7F,OAAOO,IAAAA,cAAI,EAACR,aAAa,QAAQ,OAAO,WAAW,AAAC,GAAO,OAALC,MAAK;AAC7D"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/lib/worker-file.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\n\nlet packageRoot: string | undefined;\n\n// Workers load emitted CommonJS because a fresh worker thread does not inherit the source TS loader.\n// Resolve the package lazily so callers that never spawn a worker do no filesystem work here.\nexport function resolveWorkerFile(name: string): string {\n if (!packageRoot) {\n const load = createRequire(import.meta.url);\n for (const rel of ['..', '../..', '../../..']) {\n try {\n if ((load(`${rel}/package.json`) as { name?: string }).name === 'sensemaking') {\n packageRoot = dirname(load.resolve(`${rel}/package.json`));\n break;\n }\n } catch {}\n }\n }\n if (!packageRoot) throw new Error(`cannot locate the sensemaking package root, so the ${name} worker cannot be found; run npm run build`);\n return join(packageRoot, 'dist', 'cjs', 'workers', `${name}.js`);\n}\n"],"names":["resolveWorkerFile","packageRoot","name","load","createRequire","rel","dirname","resolve","Error","join"],"mappings":";;;;+BAOgBA;;;eAAAA;;;0BAPc;wBACA;AAE9B,IAAIC;AAIG,SAASD,kBAAkBE,IAAY;IAC5C,IAAI,CAACD,aAAa;QAChB,IAAME,OAAOC,IAAAA,yBAAa,EAAC;QAC3B,gBAAkB,QAAA;YAAC;YAAM;YAAS;SAAW,OAA3B,mBAA6B;gBAApCC,MAAO;YAChB,IAAI;gBACF,IAAI,AAACF,KAAK,AAAC,GAAM,OAAJE,KAAI,kBAAsCH,IAAI,KAAK,eAAe;oBAC7ED,cAAcK,IAAAA,iBAAO,EAACH,KAAKI,OAAO,CAAC,AAAC,GAAM,OAAJF,KAAI;oBAC1C;gBACF;YACF,EAAE,eAAM,CAAC;QACX;IACF;IACA,IAAI,CAACJ,aAAa,MAAM,IAAIO,MAAM,AAAC,sDAA0D,OAALN,MAAK;IAC7F,OAAOO,IAAAA,cAAI,EAACR,aAAa,QAAQ,OAAO,WAAW,AAAC,GAAO,OAALC,MAAK;AAC7D"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/output/column-hint.ts"],"sourcesContent":["// A frontmatter key with punctuation (`plugin-id`, `a.b`) is a real column, but unquoted in SQL\n// it parses as an expression; this maps SQLite's/DuckDB's fragment error back to the real column.\n\nfunction startsWithBoundary(name: string, prefix: string): boolean {\n return name.length > prefix.length && name.startsWith(prefix) && /\\W/.test(name[prefix.length]);\n}\n\n// columns: the tree's frontmatter columns (store.docs.columns()), read by the caller so this\n// stays a pure function rather than a store dependency.\nexport function columnHint(columns: string[], err: Error): Error {\n const match = /no such column: (\\S+)|Referenced column \"([^\"]+)\" not found in FROM clause|Referenced table \"([^\"]+)\" not found/.exec(err.message);\n if (!match) return err;\n const token = match[1] ?? match[2] ?? match[3];\n // `f.plugin` -> `plugin`; left as-is when there's no leading alias segment, so a column\n // literally named `a.b` still matches via the full-token check below.\n const aliasStripped = token.replace(/^[A-Za-z_]\\w*\\./, '');\n const forms = new Set([token, aliasStripped]);\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, the engine parses the punctuation as an operator or a qualifier, not part of a column name.`);\n}\n"],"names":["columnHint","startsWithBoundary","name","prefix","length","startsWith","test","columns","err","match","exec","message","token","aliasStripped","replace","forms","Set","candidates","form","add","size","quoted","map","split","join","Error"],"mappings":";;;;+BASgBA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAThB,gGAAgG;AAChG,kGAAkG;AAElG,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;AAIO,SAASJ,WAAWO,OAAiB,EAAEC,GAAU;QAGxCC,MAAAA;IAFd,IAAMA,QAAQ,kHAAkHC,IAAI,CAACF,IAAIG,OAAO;IAChJ,IAAI,CAACF,OAAO,OAAOD;IACnB,IAAMI,SAAQH,QAAAA,UAAAA,KAAK,CAAC,EAAE,cAARA,qBAAAA,UAAYA,KAAK,CAAC,EAAE,cAApBA,kBAAAA,OAAwBA,KAAK,CAAC,EAAE;IAC9C,wFAAwF;IACxF,sEAAsE;IACtE,IAAMI,gBAAgBD,MAAME,OAAO,CAAC,mBAAmB;IACvD,IAAMC,QAAQ,IAAIC,IAAI;QAACJ;QAAOC;KAAc;IAC5C,IAAMI,aAAa,IAAID;QAClB,kCAAA,2BAAA;;QAAL,QAAK,YAAcT,4BAAd,SAAA,6BAAA,QAAA,yBAAA,iCAAuB;YAAvB,IAAML,OAAN;gBACE,mCAAA,4BAAA;;gBAAL,QAAK,aAAca,0BAAd,UAAA,8BAAA,SAAA,0BAAA,kCAAqB;oBAArB,IAAMG,OAAN;oBACH,IAAIhB,SAASgB,QAAQjB,mBAAmBC,MAAMgB,OAAOD,WAAWE,GAAG,CAACjB;gBACtE;;gBAFK;gBAAA;;;yBAAA,8BAAA;wBAAA;;;wBAAA;8BAAA;;;;QAGP;;QAJK;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAKL,IAAIe,WAAWG,IAAI,KAAK,GAAG,OAAOZ;IAClC,IAAMa,SAAS,AAAC,qBAAGJ,YAAYK,GAAG,CAAC,SAACpB;eAAS,AAAC,IAA8B,OAA3BA,KAAKqB,KAAK,CAAC,KAAKC,IAAI,CAAC,OAAM;OAAIA,IAAI,CAAC;IACrF,OAAO,IAAIC,MAAM,AAAC,GAAoBJ,OAAlBb,IAAIG,OAAO,EAAC,QAAa,OAAPU,QAAO;AAC/C"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/output/column-hint.ts"],"sourcesContent":["// A frontmatter key with punctuation (`plugin-id`, `a.b`) is a real column, but unquoted in SQL\n// it parses as an expression; this maps SQLite's/DuckDB's fragment error back to the real column.\n\nfunction startsWithBoundary(name: string, prefix: string): boolean {\n return name.length > prefix.length && name.startsWith(prefix) && /\\W/.test(name[prefix.length]);\n}\n\n// columns: the tree's frontmatter columns (store.docs.columns()), read by the caller so this\n// stays a pure function rather than a store dependency.\nexport function columnHint(columns: string[], err: Error): Error {\n const match = /no such column: (\\S+)|Referenced column \"([^\"]+)\" not found in FROM clause|Referenced table \"([^\"]+)\" not found/.exec(err.message);\n if (!match) return err;\n const token = match[1] ?? match[2] ?? match[3];\n // `f.plugin` -> `plugin`; left as-is when there's no leading alias segment, so a column\n // literally named `a.b` still matches via the full-token check below.\n const aliasStripped = token.replace(/^[A-Za-z_]\\w*\\./, '');\n const forms = new Set([token, aliasStripped]);\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, the engine parses the punctuation as an operator or a qualifier, not part of a column name.`);\n}\n"],"names":["columnHint","startsWithBoundary","name","prefix","length","startsWith","test","columns","err","match","exec","message","token","aliasStripped","replace","forms","Set","candidates","form","add","size","quoted","map","split","join","Error"],"mappings":";;;;+BASgBA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAThB,gGAAgG;AAChG,kGAAkG;AAElG,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;AAIO,SAASJ,WAAWO,OAAiB,EAAEC,GAAU;QAGxCC,MAAAA;IAFd,IAAMA,QAAQ,kHAAkHC,IAAI,CAACF,IAAIG,OAAO;IAChJ,IAAI,CAACF,OAAO,OAAOD;IACnB,IAAMI,SAAQH,QAAAA,UAAAA,KAAK,CAAC,EAAE,cAARA,qBAAAA,UAAYA,KAAK,CAAC,EAAE,cAApBA,kBAAAA,OAAwBA,KAAK,CAAC,EAAE;IAC9C,wFAAwF;IACxF,sEAAsE;IACtE,IAAMI,gBAAgBD,MAAME,OAAO,CAAC,mBAAmB;IACvD,IAAMC,QAAQ,IAAIC,IAAI;QAACJ;QAAOC;KAAc;IAC5C,IAAMI,aAAa,IAAID;QAClB,kCAAA,2BAAA;;QAAL,QAAK,YAAcT,4BAAd,SAAA,6BAAA,QAAA,yBAAA,iCAAuB;YAAvB,IAAML,OAAN;gBACE,mCAAA,4BAAA;;gBAAL,QAAK,aAAca,0BAAd,UAAA,8BAAA,SAAA,0BAAA,kCAAqB;oBAArB,IAAMG,OAAN;oBACH,IAAIhB,SAASgB,QAAQjB,mBAAmBC,MAAMgB,OAAOD,WAAWE,GAAG,CAACjB;gBACtE;;gBAFK;gBAAA;;;yBAAA,8BAAA;wBAAA;;;wBAAA;8BAAA;;;;QAGP;;QAJK;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAKL,IAAIe,WAAWG,IAAI,KAAK,GAAG,OAAOZ;IAClC,IAAMa,SAAS,AAAC,qBAAGJ,YAAYK,GAAG,CAAC,SAACpB;eAAS,AAAC,IAA8B,OAA3BA,KAAKqB,KAAK,CAAC,KAAKC,IAAI,CAAC,OAAM;OAAIA,IAAI,CAAC;IACrF,OAAO,IAAIC,MAAM,AAAC,GAAoBJ,OAAlBb,IAAIG,OAAO,EAAC,QAAa,OAAPU,QAAO;AAC/C"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/output/output.ts"],"sourcesContent":["import type { TreeMap } from '../commands/map.ts';\nimport type { Peek } from '../commands/peek.ts';\n\n// 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 keeps them as-is.\nfunction cell(value: unknown): string {\n return String(value ?? '').replace(/\\s*\\n\\s*/g, ' ');\n}\n\n// RFC 4180, deliberately not cell(): csv is the redirect-to-file format, so it keeps every\n// character, newlines included; what it cannot carry (NULL vs empty, types) is what json is for.\n// An array (e.g. snippets) joins with the one delimiter our content provably cannot contain,\n// inside the quoted field newlines already trigger (DESIGN.md \"Rendering a list of snippets\").\nfunction csvField(value: unknown): string {\n const text = value === null || value === undefined ? '' : Array.isArray(value) ? value.join('\\n') : 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// JSON.stringify throws on BigInt, and stores return int64 as BigInt (DuckDB does): a value\n// that fits a safe integer stays a number, a larger one becomes its decimal string.\nconst MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);\nconst bigintSafe = (_key: string, value: unknown): unknown => (typeof value === 'bigint' ? (value >= -MAX_SAFE && value <= MAX_SAFE ? Number(value) : value.toString()) : value);\n\nexport function stringifyJson(value: unknown, indent?: number): string {\n return JSON.stringify(value, bigintSafe, indent);\n}\n\nexport function printRows(rows: Row[], format: RowFormat, columns?: string[]): void {\n if (format === 'csv') {\n // Names from a row wherever there is one: the statement's column list keeps duplicates the\n // row collapsed. Nothing at all with no row and no columns -- a bare newline is an empty record.\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`: the result is never held as\n// rows and again as a rendered string. Table buffers (column width depends on the last row); json/csv write row by row.\nexport async function printRowStream(rows: AsyncIterable<Row>, format: RowFormat, columns: string[]): Promise<void> {\n const iterator = rows[Symbol.asyncIterator]();\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 = await iterator.next();\n const rest: AsyncIterable<Row> = { [Symbol.asyncIterator]: () => iterator };\n\n if (format === 'table') {\n const collected: Row[] = first.done ? [] : [first.value];\n for await (const row of rest) collected.push(row);\n printRows(collected, 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 const indent = (row: Row) =>\n stringifyJson(row, 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 await (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 await (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\n// An array cell (snippets) becomes one physical line per element; every other value stays the\n// single line cell() already produced. No cell in any other command holds one today, so a row\n// with no array-valued cell yields exactly one physical line, unchanged from before this existed.\nfunction cellLines(value: unknown): string[] {\n if (Array.isArray(value)) return value.length === 0 ? [''] : value.map((v) => cell(v));\n return [cell(value)];\n}\n\nfunction renderRows(rows: object[], format: Format, width = process.stdout.columns): string {\n if (format === 'json') return stringifyJson(rows, 2);\n if (rows.length === 0) return '(0 rows)';\n\n const columns = Object.keys(rows[0]);\n const linesByCell = rows.map((row) => columns.map((col) => cellLines(Reflect.get(row, col))));\n const heights = linesByCell.map((cellsInRow) => Math.max(1, ...cellsInRow.map((lines) => lines.length)));\n const natural = columns.map((col, i) => Math.max(col.length, ...linesByCell.flatMap((cellsInRow) => cellsInRow[i]).map((line) => line.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 // A row becomes as many physical lines as its tallest cell; other columns blank-pad on\n // continuation lines (DESIGN.md \"Rendering a list of snippets\").\n const body: string[] = [];\n for (let r = 0; r < rows.length; r++) {\n for (let li = 0; li < heights[r]; li++) body.push(formatRow(columns.map((_, c) => linesByCell[r][c][li] ?? '')));\n }\n\n return [formatRow(columns), widths.map((w) => '-'.repeat(w)).join(' '), ...body].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: TreeMap): 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: Peek): 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)} ${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","stringifyJson","OVERSIZE_BYTES","cell","value","String","replace","csvField","text","undefined","Array","isArray","join","test","csvLine","values","map","warnOversize","bytes","rowCount","console","warn","Math","round","MAX_SAFE","BigInt","Number","MAX_SAFE_INTEGER","bigintSafe","_key","toString","indent","JSON","stringify","rows","format","columns","names","length","Object","keys","Set","rendered","row","name","log","Buffer","byteLength","renderRows","iterator","first","rest","collected","write","Symbol","asyncIterator","next","done","push","process","stdout","split","line","MIN_COLUMN","TRUNCATED","fitWidths","widths","limit","gaps","fitted","total","reduce","a","b","widest","indexOf","max","cellLines","v","body","formatRow","_","c","linesByCell","r","li","heights","width","col","Reflect","get","cellsInRow","lines","natural","i","flatMap","clip","w","padEnd","slice","trimEnd","repeat","features","off","on","signalLabels","signals","entries","weight","presets","p","files","embedded","vectors","result","parts","docs","count","fields","fieldsTotal","hubs","includes","recentCaveat","recent","path","tokens","parseError","frontmatter","key","sections","s","level","heading","start_line","end_line","sectionsTotal","linkLine","label","shown","outboundTotal","unresolvedTotal","backlinksTotal","outbound","unresolved","backlinks"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/output/output.ts"],"sourcesContent":["import type { TreeMap } from '../commands/map.ts';\nimport type { Peek } from '../commands/peek.ts';\n\n// 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 keeps them as-is.\nfunction cell(value: unknown): string {\n return String(value ?? '').replace(/\\s*\\n\\s*/g, ' ');\n}\n\n// RFC 4180, deliberately not cell(): csv is the redirect-to-file format, so it keeps every\n// character, newlines included; what it cannot carry (NULL vs empty, types) is what json is for.\n// An array (e.g. snippets) joins with the one delimiter our content provably cannot contain,\n// inside the quoted field newlines already trigger (DESIGN.md \"Rendering a list of snippets\").\nfunction csvField(value: unknown): string {\n const text = value === null || value === undefined ? '' : Array.isArray(value) ? value.join('\\n') : 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// JSON.stringify throws on BigInt, and stores return int64 as BigInt (DuckDB does): a value\n// that fits a safe integer stays a number, a larger one becomes its decimal string.\nconst MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);\nconst bigintSafe = (_key: string, value: unknown): unknown => (typeof value === 'bigint' ? (value >= -MAX_SAFE && value <= MAX_SAFE ? Number(value) : value.toString()) : value);\n\nexport function stringifyJson(value: unknown, indent?: number): string {\n return JSON.stringify(value, bigintSafe, indent);\n}\n\nexport function printRows(rows: Row[], format: RowFormat, columns?: string[]): void {\n if (format === 'csv') {\n // Names from a row wherever there is one: the statement's column list keeps duplicates the\n // row collapsed. Nothing at all with no row and no columns -- a bare newline is an empty record.\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`: the result is never held as\n// rows and again as a rendered string. Table buffers (column width depends on the last row); json/csv write row by row.\nexport async function printRowStream(rows: AsyncIterable<Row>, format: RowFormat, columns: string[]): Promise<void> {\n const iterator = rows[Symbol.asyncIterator]();\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 = await iterator.next();\n const rest: AsyncIterable<Row> = { [Symbol.asyncIterator]: () => iterator };\n\n if (format === 'table') {\n const collected: Row[] = first.done ? [] : [first.value];\n for await (const row of rest) collected.push(row);\n printRows(collected, 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 const indent = (row: Row) =>\n stringifyJson(row, 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 await (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 await (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\n// An array cell (snippets) becomes one physical line per element; every other value stays the\n// single line cell() already produced. No cell in any other command holds one today, so a row\n// with no array-valued cell yields exactly one physical line, unchanged from before this existed.\nfunction cellLines(value: unknown): string[] {\n if (Array.isArray(value)) return value.length === 0 ? [''] : value.map((v) => cell(v));\n return [cell(value)];\n}\n\nfunction renderRows(rows: object[], format: Format, width = process.stdout.columns): string {\n if (format === 'json') return stringifyJson(rows, 2);\n if (rows.length === 0) return '(0 rows)';\n\n const columns = Object.keys(rows[0]);\n const linesByCell = rows.map((row) => columns.map((col) => cellLines(Reflect.get(row, col))));\n const heights = linesByCell.map((cellsInRow) => Math.max(1, ...cellsInRow.map((lines) => lines.length)));\n const natural = columns.map((col, i) => Math.max(col.length, ...linesByCell.flatMap((cellsInRow) => cellsInRow[i]).map((line) => line.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 // A row becomes as many physical lines as its tallest cell; other columns blank-pad on\n // continuation lines (DESIGN.md \"Rendering a list of snippets\").\n const body: string[] = [];\n for (let r = 0; r < rows.length; r++) {\n for (let li = 0; li < heights[r]; li++) body.push(formatRow(columns.map((_, c) => linesByCell[r][c][li] ?? '')));\n }\n\n return [formatRow(columns), widths.map((w) => '-'.repeat(w)).join(' '), ...body].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: TreeMap): 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: Peek): 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)} ${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","stringifyJson","OVERSIZE_BYTES","cell","value","String","replace","csvField","text","undefined","Array","isArray","join","test","csvLine","values","map","warnOversize","bytes","rowCount","console","warn","Math","round","MAX_SAFE","BigInt","Number","MAX_SAFE_INTEGER","bigintSafe","_key","toString","indent","JSON","stringify","rows","format","columns","names","length","Object","keys","Set","rendered","row","name","log","Buffer","byteLength","renderRows","iterator","first","rest","collected","write","Symbol","asyncIterator","next","done","push","process","stdout","split","line","MIN_COLUMN","TRUNCATED","fitWidths","widths","limit","gaps","fitted","total","reduce","a","b","widest","indexOf","max","cellLines","v","body","formatRow","_","c","linesByCell","r","li","heights","width","col","Reflect","get","cellsInRow","lines","natural","i","flatMap","clip","w","padEnd","slice","trimEnd","repeat","features","off","on","signalLabels","signals","entries","weight","presets","p","files","embedded","vectors","result","parts","docs","count","fields","fieldsTotal","hubs","includes","recentCaveat","recent","path","tokens","parseError","frontmatter","key","sections","s","level","heading","start_line","end_line","sectionsTotal","linkLine","label","shown","outboundTotal","unresolvedTotal","backlinksTotal","outbound","unresolved","backlinks"],"mappings":";;;;;;;;;;;QAqLgBA;eAAAA;;QAIAC;eAAAA;;QAYAC;eAAAA;;QAnIMC;eAAAA;;QAnBNC;eAAAA;;QA4JAC;eAAAA;;QAWAC;eAAAA;;QA3KAC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA/BhB,yFAAyF;AACzF,IAAMC,iBAAiB;AAEvB,sGAAsG;AACtG,SAASC,KAAKC,KAAc;IAC1B,OAAOC,OAAOD,kBAAAA,mBAAAA,QAAS,IAAIE,OAAO,CAAC,aAAa;AAClD;AAEA,2FAA2F;AAC3F,iGAAiG;AACjG,6FAA6F;AAC7F,+FAA+F;AAC/F,SAASC,SAASH,KAAc;IAC9B,IAAMI,OAAOJ,UAAU,QAAQA,UAAUK,YAAY,KAAKC,MAAMC,OAAO,CAACP,SAASA,MAAMQ,IAAI,CAAC,QAAQP,OAAOD;IAC3G,OAAO,WAAWS,IAAI,CAACL,QAAQ,AAAC,IAA4B,OAAzBA,KAAKF,OAAO,CAAC,MAAM,OAAM,OAAKE;AACnE;AAEA,SAASM,QAAQC,MAAiB;IAChC,OAAOA,OAAOC,GAAG,CAACT,UAAUK,IAAI,CAAC;AACnC;AAEA,SAASK,aAAaC,KAAa,EAAEC,QAAgB;IACnD,IAAID,SAAShB,gBAAgB;IAC7BkB,QAAQC,IAAI,CAAC,AAAC,sBAA2DF,OAAtCG,KAAKC,KAAK,CAACL,QAAQ,OAAM,eAAsB,OAATC,UAAS;AACpF;AAEA,4FAA4F;AAC5F,oFAAoF;AACpF,IAAMK,WAAWC,OAAOC,OAAOC,gBAAgB;AAC/C,IAAMC,aAAa,oBAACC,MAAczB;WAA6B,CAAA,OAAOA,sCAAP,SAAOA,MAAI,MAAM,WAAYA,SAAS,CAACoB,YAAYpB,SAASoB,WAAWE,OAAOtB,SAASA,MAAM0B,QAAQ,KAAM1B;;AAEnK,SAASH,cAAcG,KAAc,EAAE2B,MAAe;IAC3D,OAAOC,KAAKC,SAAS,CAAC7B,OAAOwB,YAAYG;AAC3C;AAEO,SAASjC,UAAUoC,IAAW,EAAEC,MAAiB,EAAEC,OAAkB;IAC1E,IAAID,WAAW,OAAO;QACpB,2FAA2F;QAC3F,iGAAiG;QACjG,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;YAAC5B,QAAQuB;SAAsE,CAA/E,OAAiB,qBAAGH,KAAKlB,GAAG,CAAC,SAAC2B;mBAAQ7B,QAAQuB,MAAMrB,GAAG,CAAC,SAAC4B;uBAASD,GAAG,CAACC,KAAK;;aAAKhC,IAAI,CAAC;QACtGQ,QAAQyB,GAAG,CAACH;QACZ,yDAAyD;QACzDzB,aAAa6B,OAAOC,UAAU,CAACL,WAAWR,KAAKI,MAAM;QACrD;IACF;IACA,IAAMI,YAAWM,WAAWd,MAAMC;IAClCf,QAAQyB,GAAG,CAACH;IACZzB,aAAa6B,OAAOC,UAAU,CAACL,YAAWR,KAAKI,MAAM;AACvD;AAIO,SAAezC,eAAeqC,IAAwB,EAAEC,MAAiB,EAAEC,OAAiB;;YAC3Fa,UAGAC,OACAC,MAGEC,mGACWT,UAKfzB,OACAC,UACEkC,OASEtB,sGAWaY,YAQbN,OAGAA;;;;oBA9CFY,WAAWf,IAAI,CAACoB,OAAOC,aAAa,CAAC;oBAG7B;;wBAAMN,SAASO,IAAI;;;oBAA3BN,QAAQ;oBACRC,OAA6B,qBAACG,OAAOC,aAAa,EAAG;+BAAMN;;yBAE7Dd,CAAAA,WAAW,OAAM,GAAjBA;;;;oBACIiB,YAAmBF,MAAMO,IAAI;wBAASP,MAAM9C,KAAK;;;;;;;;;;;gDAC/B+C;;;;;;;;;;;;;oBAAPR;oBAAaS,UAAUM,IAAI,CAACf;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAC7C7C,UAAUsD,WAAWjB,QAAQC;oBAC7B;;;;oBAGElB,QAAQ;oBACRC,WAAW;oBACTkC,QAAQ,eAAC7C;wBACb,yDAAyD;wBACzDU,SAAS4B,OAAOC,UAAU,CAACvC;wBAC3BmD,QAAQC,MAAM,CAACP,KAAK,CAAC7C;oBACvB;yBAEI2B,CAAAA,WAAW,MAAK,GAAhBA;;;;oBACF,sFAAsF;oBACtF,+DAA+D;oBACzDJ,SAAS,gBAACY;+BACd1C,cAAc0C,KAAK,GAChBkB,KAAK,CAAC,MACN7C,GAAG,CAAC,SAAC8C;mCAAS,AAAC,KAAS,OAALA;2BACnBlD,IAAI,CAAC;;yBACNsC,MAAMO,IAAI,EAAVP;;;;oBACFG,MAAM;;;;;;oBAENA,MAAM;oBACNA,MAAMtB,OAAOmB,MAAM9C,KAAK;oBACxBe,WAAW;;;;;;;;;;iDACagC;;;;;;;;;;;;;oBAAPR;oBACfU,MAAM;oBACNA,MAAMtB,OAAOY;oBACbxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAEFkC,MAAM;;;;;;;;yBAECH,MAAMO,IAAI,EAAVP;;;;oBACHb,QAAS,qBAAG,IAAII,IAAIL;oBAC1B,IAAIC,MAAMC,MAAM,GAAG,GAAGe,MAAM,AAAC,GAAiB,OAAfvC,QAAQuB,QAAO;;;;;;oBAExCA,SAAQE,OAAOC,IAAI,CAACU,MAAM9C,KAAK;oBACrCiD,MAAM,AAAC,GAAiB,OAAfvC,QAAQuB,SAAO;oBACxBgB,MAAM,AAAC,GAAkD,OAAhDvC,QAAQuB,OAAMrB,GAAG,CAAC,SAAC4B;+BAASM,MAAM9C,KAAK,CAACwC,KAAK;yBAAG;oBACzDzB,WAAW;;;;;;;;;;;;4BACMwB;wBACfU,MAAM,AAAC,GAA0C,OAAxCvC,QAAQuB,OAAMrB,GAAG,CAAC,SAAC4B;mCAASD,GAAG,CAACC,KAAK;6BAAG;wBACjDzB;oBACF;iDAHwBgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oBAK1BlC,aAAaC,OAAOC;;;;;;IACtB;;AAEA,6FAA6F;AAC7F,0EAA0E;AAC1E,IAAM4C,aAAa;AACnB,IAAMC,YAAY;AAElB,SAASC,UAAUC,MAAgB,EAAEC,KAAa;IAChD,IAAMC,OAAO,AAACF,CAAAA,OAAO5B,MAAM,GAAG,CAAA,IAAK;IACnC,IAAM+B,SAAU,qBAAGH;IACnB,OAAS;YAGuB5C;QAF9B,IAAMgD,QAAQD,OAAOE,MAAM,CAAC,SAACC,GAAGC;mBAAMD,IAAIC;WAAG,KAAKL;QAClD,IAAIE,SAASH,OAAO,OAAOE;QAC3B,IAAMK,SAASL,OAAOM,OAAO,CAACrD,CAAAA,QAAAA,MAAKsD,GAAG,OAARtD,OAAS,qBAAG+C;QAC1C,IAAIA,MAAM,CAACK,OAAO,IAAIX,YAAY,OAAOM;QACzCA,MAAM,CAACK,OAAO,GAAGpD,KAAKsD,GAAG,CAACb,YAAYM,MAAM,CAACK,OAAO,GAAGpD,KAAKsD,GAAG,CAAC,GAAGN,QAAQH;IAC7E;AACF;AAEA,8FAA8F;AAC9F,8FAA8F;AAC9F,kGAAkG;AAClG,SAASU,UAAUzE,KAAc;IAC/B,IAAIM,MAAMC,OAAO,CAACP,QAAQ,OAAOA,MAAMkC,MAAM,KAAK,IAAI;QAAC;KAAG,GAAGlC,MAAMY,GAAG,CAAC,SAAC8D;eAAM3E,KAAK2E;;IACnF,OAAO;QAAC3E,KAAKC;KAAO;AACtB;AAEA,SAAS4C,WAAWd,IAAc,EAAEC,MAAc;;;YAqBN4C,KAAKrB,IAAI,CAACsB,UAAU5C,QAAQpB,GAAG,CAAC,SAACiE,GAAGC;oBAAMC;wBAAAA,sBAAAA,WAAW,CAACC,EAAE,CAACF,EAAE,CAACG,GAAG,cAArBF,iCAAAA,sBAAyB;;;QAA3G,IAAK,IAAIE,KAAK,GAAGA,KAAKC,OAAO,CAACF,EAAE,EAAEC;IACpC;QAtBkDE,QAAAA,iEAAQ5B,QAAQC,MAAM,CAACxB,OAAO;QAMhCd,OACRA;IANxC,IAAIa,WAAW,QAAQ,OAAOlC,cAAciC,MAAM;IAClD,IAAIA,KAAKI,MAAM,KAAK,GAAG,OAAO;IAE9B,IAAMF,UAAUG,OAAOC,IAAI,CAACN,IAAI,CAAC,EAAE;IACnC,IAAMiD,cAAcjD,KAAKlB,GAAG,CAAC,SAAC2B;eAAQP,QAAQpB,GAAG,CAAC,SAACwE;mBAAQX,UAAUY,QAAQC,GAAG,CAAC/C,KAAK6C;;;IACtF,IAAMF,UAAUH,YAAYnE,GAAG,CAAC,SAAC2E;eAAerE,CAAAA,QAAAA,MAAKsD,GAAG,OAARtD,OAAAA;YAAS;SAA8C,CAAvDA,OAAY,qBAAGqE,WAAW3E,GAAG,CAAC,SAAC4E;mBAAUA,MAAMtD,MAAM;;;IACrG,IAAMuD,UAAUzD,QAAQpB,GAAG,CAAC,SAACwE,KAAKM;eAAMxE,CAAAA,SAAAA,MAAKsD,GAAG,OAARtD,QAAAA;YAASkE,IAAIlD,MAAM;SAAmF,CAAtGhB,OAAqB,qBAAG6D,YAAYY,OAAO,CAAC,SAACJ;mBAAeA,UAAU,CAACG,EAAE;WAAE9E,GAAG,CAAC,SAAC8C;mBAASA,KAAKxB,MAAM;;;IAC5I,IAAM4B,SAASqB,SAASA,QAAQxB,aAAaE,UAAU4B,SAASN,SAASM;IAEzE,IAAMG,OAAO,cAAC5F,OAAe6F;eAAe7F,MAAMkC,MAAM,IAAI2D,IAAI7F,MAAM8F,MAAM,CAACD,KAAK,AAAC,GAA0BjC,OAAxB5D,MAAM+F,KAAK,CAAC,GAAGF,IAAI,IAAe,OAAVjC;;IAC7G,IAAMgB,YAAY,mBAACjE;eACjBA,OACGC,GAAG,CAAC,SAACZ,OAAO0F;mBAAME,KAAK5F,OAAO8D,MAAM,CAAC4B,EAAE;WACvClF,IAAI,CAAC,MACLwF,OAAO;;IAEZ,uFAAuF;IACvF,iEAAiE;IACjE,IAAMrB,OAAiB,EAAE;IACzB,IAAK,IAAIK,IAAI,GAAGA,IAAIlD,KAAKI,MAAM,EAAE8C;IAIjC,OAAO;QAACJ,UAAU5C;QAAU8B,OAAOlD,GAAG,CAAC,SAACiF;mBAAM,IAAII,MAAM,CAACJ;WAAIrF,IAAI,CAAC;KAAe,CAA1E,OAAkE,qBAAGmE,OAAMnE,IAAI,CAAC;AACzF;AAMO,SAASlB,eAAekD,IAAY;IACzC,OAAO,AAAC,YAAgB,OAALA;AACrB;AAEO,SAASjD,aAAa2G,QAAyC;IACpE,IAAMC,MAAMD,SAASC,GAAG,CAACjE,MAAM,GAAG,IAAI,AAAC,cAAqF,OAA3EgE,SAASC,GAAG,CAACvF,GAAG,CAAC,SAAC4B;eAAS,AAAC,GAAWlD,OAATkD,MAAK,MAAyB,OAArBlD,eAAekD,OAAM;OAAIhC,IAAI,CAAC,SAAU;IAChI,OAAO,AAAC,aAAqC2F,OAAzBD,SAASE,EAAE,CAAC5F,IAAI,CAAC,OAAY,OAAJ2F;AAC/C;AAEA,6DAA6D;AAC7D,SAASE,aAAaC,OAA+B;IACnD,OAAOnE,OAAOoE,OAAO,CAACD,SACnB1F,GAAG,CAAC;iDAAE4B,kBAAMgE;eAAaA,WAAW,IAAIhE,OAAO,AAAC,GAAUgE,OAARhE,MAAK,KAAU,OAAPgE;OAC1DhG,IAAI,CAAC;AACV;AAEO,SAAShB,aAAaiH,OAAkG;IAC7H,6FAA6F;IAC7F,8EAA8E;IAC9E,OAAO;QAAC;KAA+K,CAAhL,OAAa,qBAAGA,QAAQ7F,GAAG,CAAC,SAAC8F;eAAM,AAAC,KAAeA,OAAXA,EAAElE,IAAI,EAAC,MAAwBkE,OAApBA,EAAEC,KAAK,EAAC,cAAkCD,OAAtBA,EAAEE,QAAQ,EAAC,aAA2F,OAAhFF,EAAEJ,OAAO,CAACO,OAAO,KAAKxG,YAAY,KAAK,AAAC,cAAqC,OAAxBgG,aAAaK,EAAEJ,OAAO,GAAE;;AACnL;AAEO,SAAS3G,UAAUmH,MAAe;IACvC,IAAMC,QAAQ;QAAE,SAA8B7F,OAAtB4F,OAAOE,IAAI,CAACC,KAAK,EAAC,MAAyC,OAArC/F,KAAKC,KAAK,CAAC2F,OAAOE,IAAI,CAAClG,KAAK,GAAG,OAAM;QAAOvB,aAAauH,OAAOZ,QAAQ;QAAG;KAA4E,CAAvL,OAA+G,qBAAG1G,aAAasH,OAAOL,OAAO,IAA7I;QAAgJ;QAAI7D,WAAWkE,OAAOI,MAAM,EAAE;KAAS;IACrM,IAAIJ,OAAOK,WAAW,GAAGL,OAAOI,MAAM,CAAChF,MAAM,EAAE6E,MAAMzD,IAAI,CAAC,AAAC,KAA8C,OAA1CwD,OAAOK,WAAW,GAAGL,OAAOI,MAAM,CAAChF,MAAM,EAAC;IACzG,IAAI4E,OAAOM,IAAI,CAAClF,MAAM,GAAG,GAAG6E,MAAMzD,IAAI,CAAC,0BAA0BV,WAAWkE,OAAOM,IAAI,EAAE;SACpF,IAAIN,OAAOZ,QAAQ,CAACC,GAAG,CAACkB,QAAQ,CAAC,SAASN,MAAMzD,IAAI,CAAC,AAAC,gBAAsC,OAAvBhE,eAAe,SAAQ;IACjGyH,MAAMzD,IAAI,CAAC;IACX,IAAIwD,OAAOQ,YAAY,EAAEP,MAAMzD,IAAI,CAACwD,OAAOQ,YAAY;IACvDP,MAAMzD,IAAI,CAACV,WAAWkE,OAAOS,MAAM,EAAE;IACrC,OAAOR,MAAMvG,IAAI,CAAC;AACpB;AAEO,SAASZ,WAAWkH,MAAY;IACrC,IAAMtB,QAAQ;QAAE,GAAoBsB,OAAlBA,OAAOU,IAAI,EAAC,QAAoB,OAAdV,OAAOW,MAAM,EAAC;KAAU;IAC5D,4FAA4F;IAC5F,iEAAiE;IACjE,IAAIX,OAAOY,UAAU,EAAElC,MAAMlC,IAAI,CAAC,AAAC,2DAA4E,OAAlBwD,OAAOY,UAAU,EAAC;QAC1G,kCAAA,2BAAA;;QAAL,QAAK,YAAsBvF,OAAOoE,OAAO,CAACO,OAAOa,WAAW,sBAAvD,SAAA,6BAAA,QAAA,yBAAA;YAAA,mCAAA,iBAAOC,sBAAK5H;YAA8CwF,MAAMlC,IAAI,CAAC,AAAC,KAAYtD,OAAR4H,KAAI,MAAU,OAAN5H;;;QAAlF;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IACL,IAAI8G,OAAOe,QAAQ,CAAC3F,MAAM,GAAG,GAAG;QAC9BsD,MAAMlC,IAAI,CAAC,IAAI;YACV,mCAAA,4BAAA;;YAAL,QAAK,aAAWwD,OAAOe,QAAQ,qBAA1B,UAAA,8BAAA,SAAA,0BAAA;gBAAA,IAAMC,IAAN;gBAA4BtC,MAAMlC,IAAI,CAAC,AAAC,KAA2BwE,OAAvB,IAAI7B,MAAM,CAAC6B,EAAEC,KAAK,GAAE,KAAmBD,OAAhBA,EAAEE,OAAO,EAAC,QAAsBF,OAAhBA,EAAEG,UAAU,EAAC,KAAmBH,OAAhBA,EAAEI,QAAQ,EAAC,OAAc,OAATJ,EAAEL,MAAM,EAAC;;;YAA5H;YAAA;;;qBAAA,8BAAA;oBAAA;;;oBAAA;0BAAA;;;;QACL,IAAIX,OAAOqB,aAAa,GAAGrB,OAAOe,QAAQ,CAAC3F,MAAM,EAAEsD,MAAMlC,IAAI,CAAC,AAAC,OAAoD,OAA9CwD,OAAOqB,aAAa,GAAGrB,OAAOe,QAAQ,CAAC3F,MAAM,EAAC;IACrH,OAAO,IAAI4E,OAAOX,GAAG,CAACkB,QAAQ,CAAC,aAAa7B,MAAMlC,IAAI,CAAC,IAAI;IAC3D,IAAIwD,OAAOX,GAAG,CAACkB,QAAQ,CAAC,UAAU;QAChC7B,MAAMlC,IAAI,CAAC,IAAI;IACjB,OAAO;QACL,IAAM8E,WAAW,kBAACC,OAAeC,OAAiBpE;YAChD,IAAIA,QAAQ,GAAGsB,MAAMlC,IAAI,CAAC,AAAC,GAAYY,OAAVmE,OAAM,MAAeC,OAAXpE,OAAM,OAAwBA,OAAnBoE,MAAM9H,IAAI,CAAC,OAAsE,OAA9D0D,QAAQoE,MAAMpG,MAAM,GAAG,AAAC,MAA0B,OAArBgC,QAAQoE,MAAMpG,MAAM,EAAC,WAAS;QAClI;QACA,IAAI4E,OAAOyB,aAAa,GAAGzB,OAAO0B,eAAe,GAAG1B,OAAO2B,cAAc,GAAG,GAAGjD,MAAMlC,IAAI,CAAC;QAC1F8E,SAAS,aAAatB,OAAO4B,QAAQ,EAAE5B,OAAOyB,aAAa;QAC3DH,SAAS,cAActB,OAAO6B,UAAU,EAAE7B,OAAO0B,eAAe;QAChEJ,SAAS,aAAatB,OAAO8B,SAAS,EAAE9B,OAAO2B,cAAc;IAC/D;IACA,OAAOjD,MAAMhF,IAAI,CAAC;AACpB"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/output/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
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/output/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 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/output/search-error.ts"],"sourcesContent":["import { SenseError } from '../errors.ts';\nimport { hasUnspacedRun } from '../text/segment.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.\nconst FTS5_PUNCTUATION = /[^\\p{L}\\p{M}\\p{N}_\\s]/u;\n\nfunction hasBalancedGrouping(text: string): boolean {\n let depth = 0;\n let grouped = false;\n for (const char of text) {\n if (char === '(') {\n depth++;\n grouped = true;\n } else if (char === ')') {\n depth--;\n if (depth < 0) return false;\n }\n }\n return grouped && depth === 0;\n}\n\n// Detects routing intent only. SQLite parses the complete expression, while other stores name\n// the unsupported operator; neither path silently interprets its punctuation as literal text.\nfunction hasExplicitFts5Syntax(terms: string): boolean {\n const text = terms.replace(/\"[^\"]*\"/g, 'phrase');\n return /[\\p{L}\\p{N}_]+\\*(?=\\s|$)/u.test(text) || /(?:^|[\\s(])(?:AND|OR|NOT)(?=\\s|\\)|$)/u.test(text) || /(?:^|[\\s(])NEAR\\b/u.test(text) || /(?:^|[\\s(])\\^\\S+/u.test(text) || /(?:^|[\\s(])[\\p{L}_]\\w*\\s*:/u.test(text) || hasBalancedGrouping(text);\n}\n\n// SQLite treats punctuation in an unquoted spaced-script token as MATCH syntax. Validate that\n// boundary before dispatch so DuckDB and Tantivy do not silently interpret the same input as text.\nexport function bareTermSyntaxError(terms: string): Error | null {\n if (hasExplicitFts5Syntax(terms)) return null;\n const outsideQuotes = terms.replace(/\"[^\"]*\"/g, ' ');\n const suspects = (outsideQuotes.match(/\\S+/g) ?? []).filter((token) => {\n if (!FTS5_PUNCTUATION.test(token) || hasUnspacedRun(token)) return false;\n if (/^[\\p{L}_]\\w*\\s*:/u.test(token)) return false;\n if (/^[\\p{L}\\p{N}_]+\\*(?:\\s|$)/u.test(token)) return false;\n if (/^(?:AND|OR|NOT)$/u.test(token)) return false;\n return true;\n });\n if (suspects.length === 0) return null;\n return new SenseError('SEARCH_SYNTAX', `the punctuation in ${suspects.map((term) => `\\`${term}\\``).join(', ')} is FTS5 syntax, not literal text; search for it literally by double-quoting: '\"${suspects[0]}\"'. Searchable columns are title, summary, text.`);\n}\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 can raise \"no such column\" through this same statement.\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":["bareTermSyntaxError","searchError","FTS5_PUNCTUATION","hasBalancedGrouping","text","depth","grouped","char","hasExplicitFts5Syntax","terms","replace","test","outsideQuotes","suspects","match","filter","token","hasUnspacedRun","length","SenseError","map","term","join","err","scope","message","t","startsWith","col","exec","fromTerms","undefined","some","split","includes"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/output/search-error.ts"],"sourcesContent":["import { SenseError } from '../errors.ts';\nimport { hasUnspacedRun } from '../text/segment.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.\nconst FTS5_PUNCTUATION = /[^\\p{L}\\p{M}\\p{N}_\\s]/u;\n\nfunction hasBalancedGrouping(text: string): boolean {\n let depth = 0;\n let grouped = false;\n for (const char of text) {\n if (char === '(') {\n depth++;\n grouped = true;\n } else if (char === ')') {\n depth--;\n if (depth < 0) return false;\n }\n }\n return grouped && depth === 0;\n}\n\n// Detects routing intent only. SQLite parses the complete expression, while other stores name\n// the unsupported operator; neither path silently interprets its punctuation as literal text.\nfunction hasExplicitFts5Syntax(terms: string): boolean {\n const text = terms.replace(/\"[^\"]*\"/g, 'phrase');\n return /[\\p{L}\\p{N}_]+\\*(?=\\s|$)/u.test(text) || /(?:^|[\\s(])(?:AND|OR|NOT)(?=\\s|\\)|$)/u.test(text) || /(?:^|[\\s(])NEAR\\b/u.test(text) || /(?:^|[\\s(])\\^\\S+/u.test(text) || /(?:^|[\\s(])[\\p{L}_]\\w*\\s*:/u.test(text) || hasBalancedGrouping(text);\n}\n\n// SQLite treats punctuation in an unquoted spaced-script token as MATCH syntax. Validate that\n// boundary before dispatch so DuckDB and Tantivy do not silently interpret the same input as text.\nexport function bareTermSyntaxError(terms: string): Error | null {\n if (hasExplicitFts5Syntax(terms)) return null;\n const outsideQuotes = terms.replace(/\"[^\"]*\"/g, ' ');\n const suspects = (outsideQuotes.match(/\\S+/g) ?? []).filter((token) => {\n if (!FTS5_PUNCTUATION.test(token) || hasUnspacedRun(token)) return false;\n if (/^[\\p{L}_]\\w*\\s*:/u.test(token)) return false;\n if (/^[\\p{L}\\p{N}_]+\\*(?:\\s|$)/u.test(token)) return false;\n if (/^(?:AND|OR|NOT)$/u.test(token)) return false;\n return true;\n });\n if (suspects.length === 0) return null;\n return new SenseError('SEARCH_SYNTAX', `the punctuation in ${suspects.map((term) => `\\`${term}\\``).join(', ')} is FTS5 syntax, not literal text; search for it literally by double-quoting: '\"${suspects[0]}\"'. Searchable columns are title, summary, text.`);\n}\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 can raise \"no such column\" through this same statement.\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":["bareTermSyntaxError","searchError","FTS5_PUNCTUATION","hasBalancedGrouping","text","depth","grouped","char","hasExplicitFts5Syntax","terms","replace","test","outsideQuotes","suspects","match","filter","token","hasUnspacedRun","length","SenseError","map","term","join","err","scope","message","t","startsWith","col","exec","fromTerms","undefined","some","split","includes"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/scan/frontmatter.ts"],"sourcesContent":["import { isCollection, parseDocument, visit } from 'yaml';\n\n// Frontmatter keys that would collide with table columns. Exported so reconcile.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// Only BAD_SCALAR_START qualifies: YAML 1.2 reserves `@` and `` ` `` at the start of a plain scalar, so `aliases: [@handle]` can only mean [\"@handle\"].\n// Every other code has a second reading (a swallowed key, a dropped URL, a silently overwritten duplicate) that would write values nobody wrote.\nconst ACCEPTED_YAML_CODES = new Set(['BAD_SCALAR_START']);\n\nexport function normalizeText(value: unknown): string {\n if (value === null || value === undefined) return '';\n return String(value).replace(/\\s+/g, ' ').trim();\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.\nexport function 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// Exactly `s.split('\\n').length` without allocating the array: callers that need only the count\n// run it per file per feature on the parse hot path.\nexport function countLines(s: string): number {\n let n = 1;\n for (let i = 0; i < s.length; i++) if (s.charCodeAt(i) === 10) n++;\n return n;\n}\n\n// The delimiter split is all this package used gray-matter for.\nexport function 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 hold a value nobody meant: `created: {{date}}` is valid YAML for a flow map used as a mapping key, so it raises no error and stores {\"{ date }\": null}.\n// No error code catches that; yaml's own warning lacks a path and fires once per document, so this reports it here instead, with the path.\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// Anything past ACCEPTED_YAML_CODES is quarantined: no frontmatter columns, `_parse_error` carries the reason. Recovering it would write values nobody wrote, worse than absence since no query can see it; content, links and sections never touch frontmatter, so a broken note stays searchable.\n// yaml's message continues onto a source snippet, so the first line is the sentence, minus the colon that introduced the part being dropped.\nfunction firstLine(message: string): string {\n return message.split('\\n')[0].replace(/:\\s*$/, '');\n}\n\nexport function 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"],"names":["RESERVED_COLUMNS","countLines","looksLikeDatetime","mapValue","normalizeDate","normalizeText","parseFrontmatter","splitFrontmatter","Set","ACCEPTED_YAML_CODES","value","undefined","String","replace","trim","ISO_DATETIME","MEANT_AS_DATETIME","test","m","exec","date","time","zone","digits","offset","length","slice","normalized","Number","isNaN","Date","parse","BigInt","isSafeInteger","JSON","stringify","s","n","i","charCodeAt","raw","open","match","fm","body","rest","close","index","warnStringifiedKeys","relPath","doc","warnings","found","visit","Pair","_key","pair","isCollection","key","BREAK","push","firstLine","message","split","parseDocument","logLevel","refused","errors","filter","err","has","code","detail","parseError","data","toJS","Array","isArray"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/scan/frontmatter.ts"],"sourcesContent":["import { isCollection, parseDocument, visit } from 'yaml';\n\n// Frontmatter keys that would collide with table columns. Exported so reconcile.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// Only BAD_SCALAR_START qualifies: YAML 1.2 reserves `@` and `` ` `` at the start of a plain scalar, so `aliases: [@handle]` can only mean [\"@handle\"].\n// Every other code has a second reading (a swallowed key, a dropped URL, a silently overwritten duplicate) that would write values nobody wrote.\nconst ACCEPTED_YAML_CODES = new Set(['BAD_SCALAR_START']);\n\nexport function normalizeText(value: unknown): string {\n if (value === null || value === undefined) return '';\n return String(value).replace(/\\s+/g, ' ').trim();\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.\nexport function 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// Exactly `s.split('\\n').length` without allocating the array: callers that need only the count\n// run it per file per feature on the parse hot path.\nexport function countLines(s: string): number {\n let n = 1;\n for (let i = 0; i < s.length; i++) if (s.charCodeAt(i) === 10) n++;\n return n;\n}\n\n// The delimiter split is all this package used gray-matter for.\nexport function 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 hold a value nobody meant: `created: {{date}}` is valid YAML for a flow map used as a mapping key, so it raises no error and stores {\"{ date }\": null}.\n// No error code catches that; yaml's own warning lacks a path and fires once per document, so this reports it here instead, with the path.\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// Anything past ACCEPTED_YAML_CODES is quarantined: no frontmatter columns, `_parse_error` carries the reason. Recovering it would write values nobody wrote, worse than absence since no query can see it; content, links and sections never touch frontmatter, so a broken note stays searchable.\n// yaml's message continues onto a source snippet, so the first line is the sentence, minus the colon that introduced the part being dropped.\nfunction firstLine(message: string): string {\n return message.split('\\n')[0].replace(/:\\s*$/, '');\n}\n\nexport function 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"],"names":["RESERVED_COLUMNS","countLines","looksLikeDatetime","mapValue","normalizeDate","normalizeText","parseFrontmatter","splitFrontmatter","Set","ACCEPTED_YAML_CODES","value","undefined","String","replace","trim","ISO_DATETIME","MEANT_AS_DATETIME","test","m","exec","date","time","zone","digits","offset","length","slice","normalized","Number","isNaN","Date","parse","BigInt","isSafeInteger","JSON","stringify","s","n","i","charCodeAt","raw","open","match","fm","body","rest","close","index","warnStringifiedKeys","relPath","doc","warnings","found","visit","Pair","_key","pair","isCollection","key","BREAK","push","firstLine","message","split","parseDocument","logLevel","refused","errors","filter","err","has","code","detail","parseError","data","toJS","Array","isArray"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/scan/index.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { parse } from '../chunk/index.ts';\nimport type { Config } from '../config/index.ts';\nimport type { Feature } from '../features/types.ts';\nimport { textFromBlocks } from '../text/strip.ts';\nimport { looksLikeDatetime, mapValue, normalizeText, parseFrontmatter, RESERVED_COLUMNS, splitFrontmatter } from './frontmatter.ts';\nimport type { FileStat } from './list.ts';\n\n// Filesystem -> rows. Pure data in, data + warnings out; store/sqlite/reconcile.ts does the SQL.\n\nexport { looksLikeDatetime, normalizeDate, RESERVED_COLUMNS } from './frontmatter.ts';\nexport type { FileStat } from './list.ts';\nexport { listFiles, toPosixPath } from './list.ts';\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 // Exact decoded source bytes read for this parse generation. Stored outside the FTS table so\n // snippets and delayed embedding never consult a newer filesystem generation.\n source: string;\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\nexport function parseSource(file: FileStat, raw: string, extractors: Feature[] = [], cfg?: Config): { doc: ParsedDoc; warnings: string[] } {\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 // Parsed once and shared: the FTS text path (textFromBlocks, ~ strip.ts) and any feature\n // that needs a parse tree (embed's chunker) both read this same block list.\n const blocks = parse(content);\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: textFromBlocks(blocks) };\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 source: raw,\n search,\n extracted: Object.fromEntries(extractors.filter((f) => f.extract).map((f) => [f.name, f.extract?.(raw, content, search, data, cfg, blocks)])),\n },\n warnings,\n };\n}\n\nexport function parseFile(file: FileStat, extractors: Feature[] = [], cfg?: Config): { doc: ParsedDoc; warnings: string[] } {\n // Preserve the authored bytes: feature extractors, indexed snippets, and section offsets use\n // the same decoded string from this one read.\n return parseSource(file, readFileSync(file.absPath, 'utf8'), extractors, cfg);\n}\n"],"names":["RESERVED_COLUMNS","listFiles","looksLikeDatetime","normalizeDate","parseFile","parseSource","toPosixPath","file","raw","extractors","cfg","warnings","splitFrontmatter","fm","body","content","data","parseError","parseFrontmatter","relPath","mapped","Object","keys","key","has","push","value","mapValue","Number","isNaN","Date","parse","blocks","search","title","normalizeText","summary","text","textFromBlocks","doc","mtimeMs","ctimeMs","size","presets","source","extracted","fromEntries","filter","f","extract","map","name","readFileSync","absPath"],"mappings":";;;;;;;;;;;QAU2CA;eAAAA,+BAAgB;;QAElDC;eAAAA,iBAAS;;QAFTC;eAAAA,gCAAiB;;QAAEC;eAAAA,4BAAa;;QAmEzBC;eAAAA;;QA5CAC;eAAAA;;QArBIC;eAAAA,mBAAW;;;sBAZF;uBACP;uBAGS;6BACkF;sBAO1E;AAqBhC,SAASD,YAAYE,IAAc,EAAEC,GAAW;QAAEC,aAAAA,iEAAwB,EAAE,EAAEC;IACnF,IAAMC,WAAqB,EAAE;IAE7B,IAA8BC,oBAAAA,IAAAA,+BAAgB,EAACJ,MAAvCK,KAAsBD,kBAAtBC,IAAIC,AAAMC,UAAYH,kBAAlBE;IACZ,IAA6BD,OAAAA,OAAO,OAAO;QAAEG,MAAM,CAAC;QAA8BC,YAAY;IAAK,IAAIC,IAAAA,+BAAgB,EAACX,KAAKY,OAAO,EAAEN,IAAIF,WAAlIK,OAAqBH,KAArBG,MAAMC,aAAeJ,KAAfI;IACd,IAAMG,SAA0D,CAAC;QAE5D,kCAAA,2BAAA;;QAAL,QAAK,YAAaC,OAAOC,IAAI,CAACN,0BAAzB,SAAA,6BAAA,QAAA,yBAAA,iCAAgC;YAAhC,IAAMO,MAAN;YACH,IAAIvB,+BAAgB,CAACwB,GAAG,CAACD,MAAM;gBAC7BZ,SAASc,IAAI,CAAC,AAAC,YAAwDF,OAA7ChB,KAAKY,OAAO,EAAC,kCAAoC,OAAJI,KAAI;gBAC3E;YACF;YACA,IAAMG,QAAQC,IAAAA,uBAAQ,EAACX,IAAI,CAACO,IAAI;YAChC,IAAI,OAAOG,UAAU,YAAYxB,IAAAA,gCAAiB,EAACwB,UAAUE,OAAOC,KAAK,CAACC,KAAKC,KAAK,CAACL,SAAS;gBAC5Ff,SAASc,IAAI,CAAC,AAAC,YAA4BF,OAAjBhB,KAAKY,OAAO,EAAC,MAAgCO,OAA5BH,KAAI,0BAA8B,OAANG,OAAM;YAC/E;YACAN,MAAM,CAACG,IAAI,GAAGG;QAChB;;QAVK;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAYL,yFAAyF;IACzF,4EAA4E;IAC5E,IAAMM,SAASD,IAAAA,cAAK,EAAChB;IAErB,oEAAoE;IACpE,0CAA0C;IAC1C,IAAMkB,SAAS;QAAEC,OAAOC,IAAAA,4BAAa,EAACnB,KAAKkB,KAAK;QAAGE,SAASD,IAAAA,4BAAa,EAACnB,KAAKoB,OAAO;QAAGC,MAAMC,IAAAA,uBAAc,EAACN;IAAQ;IAEtH,OAAO;QACLO,KAAK;YACHpB,SAASZ,KAAKY,OAAO;YACrBqB,SAASjC,KAAKiC,OAAO;YACrBC,SAASlC,KAAKkC,OAAO;YACrBC,MAAMnC,KAAKmC,IAAI;YACfC,SAASpC,KAAKoC,OAAO;YACrB3B,MAAMI;YACNH,YAAAA;YACA2B,QAAQpC;YACRyB,QAAAA;YACAY,WAAWxB,OAAOyB,WAAW,CAACrC,WAAWsC,MAAM,CAAC,SAACC;uBAAMA,EAAEC,OAAO;eAAEC,GAAG,CAAC,SAACF;oBAAeA;uBAAT;oBAACA,EAAEG,IAAI;qBAAEH,aAAAA,EAAEC,OAAO,cAATD,iCAAAA,gBAAAA,GAAYxC,KAAKO,SAASkB,QAAQjB,MAAMN,KAAKsB;iBAAQ;;QAC7I;QACArB,UAAAA;IACF;AACF;AAEO,SAASP,UAAUG,IAAc;QAAEE,aAAAA,iEAAwB,EAAE,EAAEC;IACpE,6FAA6F;IAC7F,8CAA8C;IAC9C,OAAOL,YAAYE,MAAM6C,IAAAA,oBAAY,EAAC7C,KAAK8C,OAAO,EAAE,SAAS5C,YAAYC;AAC3E"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/scan/index.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { parse } from '../chunk/index.ts';\nimport type { Config } from '../config/index.ts';\nimport type { Feature } from '../features/types.ts';\nimport { textFromBlocks } from '../text/strip.ts';\nimport { looksLikeDatetime, mapValue, normalizeText, parseFrontmatter, RESERVED_COLUMNS, splitFrontmatter } from './frontmatter.ts';\nimport type { FileStat } from './list.ts';\n\n// Filesystem -> rows. Pure data in, data + warnings out; store/sqlite/reconcile.ts does the SQL.\n\nexport { looksLikeDatetime, normalizeDate, RESERVED_COLUMNS } from './frontmatter.ts';\nexport type { FileStat } from './list.ts';\nexport { listFiles, toPosixPath } from './list.ts';\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 // Exact decoded source bytes read for this parse generation. Stored outside the FTS table so\n // snippets and delayed embedding never consult a newer filesystem generation.\n source: string;\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\nexport function parseSource(file: FileStat, raw: string, extractors: Feature[] = [], cfg?: Config): { doc: ParsedDoc; warnings: string[] } {\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 // Parsed once and shared: the FTS text path (textFromBlocks, ~ strip.ts) and any feature\n // that needs a parse tree (embed's chunker) both read this same block list.\n const blocks = parse(content);\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: textFromBlocks(blocks) };\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 source: raw,\n search,\n extracted: Object.fromEntries(extractors.filter((f) => f.extract).map((f) => [f.name, f.extract?.(raw, content, search, data, cfg, blocks)])),\n },\n warnings,\n };\n}\n\nexport function parseFile(file: FileStat, extractors: Feature[] = [], cfg?: Config): { doc: ParsedDoc; warnings: string[] } {\n // Preserve the authored bytes: feature extractors, indexed snippets, and section offsets use\n // the same decoded string from this one read.\n return parseSource(file, readFileSync(file.absPath, 'utf8'), extractors, cfg);\n}\n"],"names":["RESERVED_COLUMNS","listFiles","looksLikeDatetime","normalizeDate","parseFile","parseSource","toPosixPath","file","raw","extractors","cfg","warnings","splitFrontmatter","fm","body","content","data","parseError","parseFrontmatter","relPath","mapped","Object","keys","key","has","push","value","mapValue","Number","isNaN","Date","parse","blocks","search","title","normalizeText","summary","text","textFromBlocks","doc","mtimeMs","ctimeMs","size","presets","source","extracted","fromEntries","filter","f","extract","map","name","readFileSync","absPath"],"mappings":";;;;;;;;;;;QAU2CA;eAAAA,+BAAgB;;QAElDC;eAAAA,iBAAS;;QAFTC;eAAAA,gCAAiB;;QAAEC;eAAAA,4BAAa;;QAmEzBC;eAAAA;;QA5CAC;eAAAA;;QArBIC;eAAAA,mBAAW;;;sBAZF;uBACP;uBAGS;6BACkF;sBAO1E;AAqBhC,SAASD,YAAYE,IAAc,EAAEC,GAAW;QAAEC,aAAAA,iEAAwB,EAAE,EAAEC;IACnF,IAAMC,WAAqB,EAAE;IAE7B,IAA8BC,oBAAAA,IAAAA,+BAAgB,EAACJ,MAAvCK,KAAsBD,kBAAtBC,IAAIC,AAAMC,UAAYH,kBAAlBE;IACZ,IAA6BD,OAAAA,OAAO,OAAO;QAAEG,MAAM,CAAC;QAA8BC,YAAY;IAAK,IAAIC,IAAAA,+BAAgB,EAACX,KAAKY,OAAO,EAAEN,IAAIF,WAAlIK,OAAqBH,KAArBG,MAAMC,aAAeJ,KAAfI;IACd,IAAMG,SAA0D,CAAC;QAE5D,kCAAA,2BAAA;;QAAL,QAAK,YAAaC,OAAOC,IAAI,CAACN,0BAAzB,SAAA,6BAAA,QAAA,yBAAA,iCAAgC;YAAhC,IAAMO,MAAN;YACH,IAAIvB,+BAAgB,CAACwB,GAAG,CAACD,MAAM;gBAC7BZ,SAASc,IAAI,CAAC,AAAC,YAAwDF,OAA7ChB,KAAKY,OAAO,EAAC,kCAAoC,OAAJI,KAAI;gBAC3E;YACF;YACA,IAAMG,QAAQC,IAAAA,uBAAQ,EAACX,IAAI,CAACO,IAAI;YAChC,IAAI,OAAOG,UAAU,YAAYxB,IAAAA,gCAAiB,EAACwB,UAAUE,OAAOC,KAAK,CAACC,KAAKC,KAAK,CAACL,SAAS;gBAC5Ff,SAASc,IAAI,CAAC,AAAC,YAA4BF,OAAjBhB,KAAKY,OAAO,EAAC,MAAgCO,OAA5BH,KAAI,0BAA8B,OAANG,OAAM;YAC/E;YACAN,MAAM,CAACG,IAAI,GAAGG;QAChB;;QAVK;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAYL,yFAAyF;IACzF,4EAA4E;IAC5E,IAAMM,SAASD,IAAAA,cAAK,EAAChB;IAErB,oEAAoE;IACpE,0CAA0C;IAC1C,IAAMkB,SAAS;QAAEC,OAAOC,IAAAA,4BAAa,EAACnB,KAAKkB,KAAK;QAAGE,SAASD,IAAAA,4BAAa,EAACnB,KAAKoB,OAAO;QAAGC,MAAMC,IAAAA,uBAAc,EAACN;IAAQ;IAEtH,OAAO;QACLO,KAAK;YACHpB,SAASZ,KAAKY,OAAO;YACrBqB,SAASjC,KAAKiC,OAAO;YACrBC,SAASlC,KAAKkC,OAAO;YACrBC,MAAMnC,KAAKmC,IAAI;YACfC,SAASpC,KAAKoC,OAAO;YACrB3B,MAAMI;YACNH,YAAAA;YACA2B,QAAQpC;YACRyB,QAAAA;YACAY,WAAWxB,OAAOyB,WAAW,CAACrC,WAAWsC,MAAM,CAAC,SAACC;uBAAMA,EAAEC,OAAO;eAAEC,GAAG,CAAC,SAACF;oBAAeA;uBAAT;oBAACA,EAAEG,IAAI;qBAAEH,aAAAA,EAAEC,OAAO,cAATD,iCAAAA,gBAAAA,GAAYxC,KAAKO,SAASkB,QAAQjB,MAAMN,KAAKsB;iBAAQ;;QAC7I;QACArB,UAAAA;IACF;AACF;AAEO,SAASP,UAAUG,IAAc;QAAEE,aAAAA,iEAAwB,EAAE,EAAEC;IACpE,6FAA6F;IAC7F,8CAA8C;IAC9C,OAAOL,YAAYE,MAAM6C,IAAAA,oBAAY,EAAC7C,KAAK8C,OAAO,EAAE,SAAS5C,YAAYC;AAC3E"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/scan/list.ts"],"sourcesContent":["import { globSync, statSync } from 'node:fs';\nimport { join, sep } from 'node:path';\nimport type { Config } from '../config/index.ts';\nimport { embedEnabled, presetHasSignal, presetNames } from '../config/index.ts';\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 per-file work here is the hottest path in the package.\n// Everything derivable from the config 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"],"names":["listFiles","toPosixPath","relPath","separator","sep","split","join","NO_THROW","throwIfNoEntry","cfg","baseDir","coverage","Map","posixNeeded","presetNames","name","preset","presets","globSync","include","cwd","exclude","matched","set","get","Set","add","embedding","embedEnabled","vectorPresets","filter","presetHasSignal","files","keys","sort","absPath","st","statSync","isFile","embed","some","has","push","mtimeMs","ctimeMs","birthtimeMs","size"],"mappings":";;;;;;;;;;;QAyBgBA;eAAAA;;QARAC;eAAAA;;;sBAjBmB;wBACT;uBAEiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcpD,SAASA,YAAYC,OAAe;QAAEC,YAAAA,iEAAoBC,aAAG;IAClE,OAAOD,cAAc,OAAOD,QAAQG,KAAK,CAACF,WAAWG,IAAI,CAAC,OAAOJ;AACnE;AAEA,kJAAkJ;AAClJ,+EAA+E;AAC/E,IAAMK,WAAW;IAAEC,gBAAgB;AAAM;AAElC,SAASR,UAAUS,GAAW,EAAEC,OAAe;IACpD,IAAMC,WAAW,IAAIC;IACrB,IAAMC,cAAcT,aAAG,KAAK;QACvB,kCAAA,2BAAA;;QAAL,QAAK,YAAcU,IAAAA,oBAAW,EAACL,yBAA1B,SAAA,6BAAA,QAAA,yBAAA,iCAAgC;YAAhC,IAAMM,OAAN;YACH,IAAMC,SAASP,IAAIQ,OAAO,CAACF,KAAK;gBAC3B,mCAAA,4BAAA;;gBAAL,QAAK,aAAiBG,IAAAA,gBAAQ,EAACF,OAAOG,OAAO,EAAE;oBAAEC,KAAKV;oBAASW,SAASL,OAAOK,OAAO;gBAAC,uBAAlF,UAAA,8BAAA,SAAA,0BAAA,kCAAsF;oBAAtF,IAAMC,UAAN;wBAESX;oBADZ,IAAMT,UAAUW,cAAcZ,YAAYqB,WAAWA;oBACrD,IAAMC,OAAMZ,gBAAAA,SAASa,GAAG,CAACtB,sBAAbS,2BAAAA,gBAAyB,IAAIc;oBACzCF,IAAIG,GAAG,CAACX;oBACRJ,SAASY,GAAG,CAACrB,SAASqB;gBACxB;;gBALK;gBAAA;;;yBAAA,8BAAA;wBAAA;;;wBAAA;8BAAA;;;;QAMP;;QARK;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAUL,2EAA2E;IAC3E,IAAMI,YAAYC,IAAAA,qBAAY,EAACnB;IAC/B,IAAMoB,gBAAgBF,YAAY,IAAIF,IAAIX,IAAAA,oBAAW,EAACL,KAAKqB,MAAM,CAAC,SAACf;eAASgB,IAAAA,wBAAe,EAACtB,KAAKM,MAAM;UAAe;IAEtH,IAAMiB,QAAoB,EAAE;QACvB,mCAAA,4BAAA;;QAAL,QAAK,aAAiB,AAAC,qBAAGrB,SAASsB,IAAI,IAAIC,IAAI,uBAA1C,UAAA,8BAAA,SAAA,0BAAA,kCAA8C;YAA9C,IAAMhC,WAAN;YACH,IAAMiC,UAAU7B,IAAAA,cAAI,EAACI,SAASR,WAAU,sDAAsD;YAC9F,yFAAyF;YACzF,uFAAuF;YACvF,IAAMkC,KAAKC,IAAAA,gBAAQ,EAACF,SAAS5B;YAC7B,IAAI,EAAC6B,eAAAA,yBAAAA,GAAIE,MAAM,KAAI;YACnB,IAAMrB,UAAU,AAAC,qBAAIN,SAASa,GAAG,CAACtB,WAA0BgC,IAAI;YAChE,IAAMK,QAAQV,kBAAkB,QAAQZ,QAAQuB,IAAI,CAAC,SAACzB;uBAASc,cAAcY,GAAG,CAAC1B;;YACjFiB,MAAMU,IAAI,CAAC;gBAAExC,SAAAA;gBAASiC,SAAAA;gBAASQ,SAASP,GAAGO,OAAO;gBAAEC,SAASR,GAAGS,WAAW;gBAAEC,MAAMV,GAAGU,IAAI;gBAAE7B,SAAAA;gBAASsB,OAAAA;YAAM;QAC7G;;QATK;QAAA;;;iBAAA,8BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAUL,OAAOP;AACT"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/scan/list.ts"],"sourcesContent":["import { globSync, statSync } from 'node:fs';\nimport { join, sep } from 'node:path';\nimport type { Config } from '../config/index.ts';\nimport { embedEnabled, presetHasSignal, presetNames } from '../config/index.ts';\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 per-file work here is the hottest path in the package.\n// Everything derivable from the config 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"],"names":["listFiles","toPosixPath","relPath","separator","sep","split","join","NO_THROW","throwIfNoEntry","cfg","baseDir","coverage","Map","posixNeeded","presetNames","name","preset","presets","globSync","include","cwd","exclude","matched","set","get","Set","add","embedding","embedEnabled","vectorPresets","filter","presetHasSignal","files","keys","sort","absPath","st","statSync","isFile","embed","some","has","push","mtimeMs","ctimeMs","birthtimeMs","size"],"mappings":";;;;;;;;;;;QAyBgBA;eAAAA;;QARAC;eAAAA;;;sBAjBmB;wBACT;uBAEiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcpD,SAASA,YAAYC,OAAe;QAAEC,YAAAA,iEAAoBC,aAAG;IAClE,OAAOD,cAAc,OAAOD,QAAQG,KAAK,CAACF,WAAWG,IAAI,CAAC,OAAOJ;AACnE;AAEA,kJAAkJ;AAClJ,+EAA+E;AAC/E,IAAMK,WAAW;IAAEC,gBAAgB;AAAM;AAElC,SAASR,UAAUS,GAAW,EAAEC,OAAe;IACpD,IAAMC,WAAW,IAAIC;IACrB,IAAMC,cAAcT,aAAG,KAAK;QACvB,kCAAA,2BAAA;;QAAL,QAAK,YAAcU,IAAAA,oBAAW,EAACL,yBAA1B,SAAA,6BAAA,QAAA,yBAAA,iCAAgC;YAAhC,IAAMM,OAAN;YACH,IAAMC,SAASP,IAAIQ,OAAO,CAACF,KAAK;gBAC3B,mCAAA,4BAAA;;gBAAL,QAAK,aAAiBG,IAAAA,gBAAQ,EAACF,OAAOG,OAAO,EAAE;oBAAEC,KAAKV;oBAASW,SAASL,OAAOK,OAAO;gBAAC,uBAAlF,UAAA,8BAAA,SAAA,0BAAA,kCAAsF;oBAAtF,IAAMC,UAAN;wBAESX;oBADZ,IAAMT,UAAUW,cAAcZ,YAAYqB,WAAWA;oBACrD,IAAMC,OAAMZ,gBAAAA,SAASa,GAAG,CAACtB,sBAAbS,2BAAAA,gBAAyB,IAAIc;oBACzCF,IAAIG,GAAG,CAACX;oBACRJ,SAASY,GAAG,CAACrB,SAASqB;gBACxB;;gBALK;gBAAA;;;yBAAA,8BAAA;wBAAA;;;wBAAA;8BAAA;;;;QAMP;;QARK;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAUL,2EAA2E;IAC3E,IAAMI,YAAYC,IAAAA,qBAAY,EAACnB;IAC/B,IAAMoB,gBAAgBF,YAAY,IAAIF,IAAIX,IAAAA,oBAAW,EAACL,KAAKqB,MAAM,CAAC,SAACf;eAASgB,IAAAA,wBAAe,EAACtB,KAAKM,MAAM;UAAe;IAEtH,IAAMiB,QAAoB,EAAE;QACvB,mCAAA,4BAAA;;QAAL,QAAK,aAAiB,AAAC,qBAAGrB,SAASsB,IAAI,IAAIC,IAAI,uBAA1C,UAAA,8BAAA,SAAA,0BAAA,kCAA8C;YAA9C,IAAMhC,WAAN;YACH,IAAMiC,UAAU7B,IAAAA,cAAI,EAACI,SAASR,WAAU,sDAAsD;YAC9F,yFAAyF;YACzF,uFAAuF;YACvF,IAAMkC,KAAKC,IAAAA,gBAAQ,EAACF,SAAS5B;YAC7B,IAAI,EAAC6B,eAAAA,yBAAAA,GAAIE,MAAM,KAAI;YACnB,IAAMrB,UAAU,AAAC,qBAAIN,SAASa,GAAG,CAACtB,WAA0BgC,IAAI;YAChE,IAAMK,QAAQV,kBAAkB,QAAQZ,QAAQuB,IAAI,CAAC,SAACzB;uBAASc,cAAcY,GAAG,CAAC1B;;YACjFiB,MAAMU,IAAI,CAAC;gBAAExC,SAAAA;gBAASiC,SAAAA;gBAASQ,SAASP,GAAGO,OAAO;gBAAEC,SAASR,GAAGS,WAAW;gBAAEC,MAAMV,GAAGU,IAAI;gBAAE7B,SAAAA;gBAASsB,OAAAA;YAAM;QAC7G;;QATK;QAAA;;;iBAAA,8BAAA;gBAAA;;;gBAAA;sBAAA;;;;IAUL,OAAOP;AACT"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/scan/pool.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { isDeepStrictEqual } from 'node:util';\n// Type-only: erased at build, but keeps depcheck's usage check satisfied for the tier-2\n// `_require` below (see coding-standards' deferral tiers).\nimport type * as TinypoolNS from 'tinypool';\nimport type { Config } from '../config/index.ts';\nimport type { Feature } from '../features/types.ts';\nimport { resolveWorkerFile } from '../lib/worker-file.ts';\nimport type { ParsedDoc } from '../scan/index.ts';\nimport type { ParseTaskResult, ParseWorkerData } from '../workers/parse.ts';\nimport type { FileStat } from './list.ts';\nimport { reviveError } from './worker-error.ts';\n\n// Tinypool is ESM-only; our floor (>=22.20) has native require(esm), so the tier-2 house deferral reaches it.\nconst _require = typeof require === 'undefined' ? createRequire(import.meta.url) : require;\n// Candidate queue depth gives uneven files more than one scheduling turn per worker.\n// The bounded parser comparison decides whether this value ships.\nconst BATCHES_PER_WORKER = 4;\n\n// parseMs is worker-side only (see workers/parse.ts); absent on the serial path.\nexport type FileResult = { doc: ParsedDoc; warnings: string[]; parseMs?: number };\n\n// Created lazily and reused while dispatch context stays equivalent. A builder owns one instance\n// for its lifetime instead of paying pool startup for unchanged reconciles.\nexport class ParsePool {\n private pool: TinypoolNS.Tinypool | undefined;\n private workerData: ParseWorkerData | undefined;\n private workerCount: number | undefined;\n private operation: Promise<void> = Promise.resolve();\n // Tinypools this instance has constructed. Repeated equivalent dispatches leave this unchanged;\n // a context/count change or close followed by run constructs another pool.\n poolsCreated = 0;\n\n private enqueue<T>(operation: () => Promise<T>): Promise<T> {\n const result = this.operation.then(operation);\n this.operation = result.then(\n () => undefined,\n () => undefined\n );\n return result;\n }\n\n private async ensure(workerData: ParseWorkerData, workerCount: number): Promise<TinypoolNS.Tinypool> {\n if (this.pool && (!isDeepStrictEqual(this.workerData, workerData) || this.workerCount !== workerCount)) await this.destroy();\n if (!this.pool) {\n const { Tinypool } = _require('tinypool') as typeof TinypoolNS;\n this.pool = new Tinypool({ filename: resolveWorkerFile('parse'), minThreads: workerCount, maxThreads: workerCount, workerData });\n this.workerData = workerData;\n this.workerCount = workerCount;\n this.poolsCreated++;\n }\n return this.pool;\n }\n\n // Never the tree: a worker task carries a bounded FileStat batch and returns only what\n // parseFile returns for each file, never the token tree.\n run(files: FileStat[], features: Feature[], cfg: Config, onParsed: ((done: number) => void) | undefined, requestedWorkers: number): Promise<FileResult[]> {\n if (files.length === 0) return Promise.resolve([]);\n // Snapshot at invocation so caller mutation cannot change queued work or its reuse baseline.\n const workerData: ParseWorkerData = { cfg: structuredClone(cfg), featureNames: [...new Set(features.map((feature) => feature.name))].sort() };\n const workerCount = Math.max(1, Math.min(requestedWorkers, files.length));\n return this.enqueue(() => this.dispatch(files, workerData, onParsed, workerCount));\n }\n\n private async dispatch(files: FileStat[], workerData: ParseWorkerData, onParsed: ((done: number) => void) | undefined, workerCount: number): Promise<FileResult[]> {\n const pool = await this.ensure(workerData, workerCount);\n const batches = batchFiles(files, Math.min(files.length, workerCount * BATCHES_PER_WORKER));\n let done = 0;\n const settled = await Promise.all(\n batches.map(async (batch): Promise<{ results: FileResult[]; failures: unknown[] }> => {\n let taskResults: ParseTaskResult;\n try {\n taskResults = (await pool.run(batch)) as ParseTaskResult;\n } catch (err) {\n return { results: [], failures: [err] };\n }\n\n const results: FileResult[] = [];\n const failures: unknown[] = [];\n for (const result of taskResults) {\n if (!result.ok) {\n failures.push(reviveError(result.error));\n continue;\n }\n results.push({ doc: result.doc, warnings: result.warnings, parseMs: result.parseMs });\n try {\n onParsed?.(++done);\n } catch (err) {\n failures.push(err);\n }\n }\n return { results, failures };\n })\n );\n const results: FileResult[] = [];\n const failures: unknown[] = [];\n for (const batch of settled) {\n results.push(...batch.results);\n failures.push(...batch.failures);\n }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1) throw new AggregateError(failures, `${failures.length} parse tasks failed`);\n // Promise.all and contiguous batches preserve the input order that first-seen columns use.\n return results;\n }\n\n private async destroy(): Promise<void> {\n if (!this.pool) return;\n const pool = this.pool;\n await pool.destroy();\n this.pool = undefined;\n this.workerData = undefined;\n this.workerCount = undefined;\n }\n\n // A pool never created costs nothing to destroy. Queuing lets active dispatches drain first.\n close(): Promise<void> {\n return this.enqueue(() => this.destroy());\n }\n}\n\nfunction batchFiles(files: FileStat[], batchCount: number): FileStat[][] {\n const batches: FileStat[][] = [];\n let start = 0;\n let remainingBytes = files.reduce((sum, file) => sum + file.size, 0);\n\n for (let batchIndex = 0; batchIndex < batchCount; batchIndex++) {\n const remainingBatches = batchCount - batchIndex;\n if (remainingBatches === 1) {\n batches.push(files.slice(start));\n break;\n }\n\n const targetBytes = remainingBytes / remainingBatches;\n const lastEnd = files.length - (remainingBatches - 1);\n let end = start;\n let bytes = 0;\n while (end < lastEnd && (end === start || bytes < targetBytes)) {\n bytes += files[end].size;\n end++;\n }\n batches.push(files.slice(start, end));\n start = end;\n remainingBytes -= bytes;\n }\n return batches;\n}\n"],"names":["ParsePool","_require","require","createRequire","BATCHES_PER_WORKER","operation","Promise","resolve","poolsCreated","enqueue","result","then","undefined","ensure","workerData","workerCount","Tinypool","pool","isDeepStrictEqual","destroy","filename","resolveWorkerFile","minThreads","maxThreads","run","files","features","cfg","onParsed","requestedWorkers","length","structuredClone","featureNames","Set","map","feature","name","sort","Math","max","min","dispatch","batches","done","settled","results","failures","batch","batchFiles","all","taskResults","err","ok","push","reviveError","error","doc","warnings","parseMs","AggregateError","close","batchCount","start","remainingBytes","reduce","sum","file","size","batchIndex","remainingBatches","slice","targetBytes","lastEnd","end","bytes"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/scan/pool.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { isDeepStrictEqual } from 'node:util';\n// Type-only: erased at build, but keeps depcheck's usage check satisfied for the tier-2\n// `_require` below (see coding-standards' deferral tiers).\nimport type * as TinypoolNS from 'tinypool';\nimport type { Config } from '../config/index.ts';\nimport type { Feature } from '../features/types.ts';\nimport { resolveWorkerFile } from '../lib/worker-file.ts';\nimport type { ParsedDoc } from '../scan/index.ts';\nimport type { ParseTaskResult, ParseWorkerData } from '../workers/parse.ts';\nimport type { FileStat } from './list.ts';\nimport { reviveError } from './worker-error.ts';\n\n// Tinypool is ESM-only; our floor (>=22.20) has native require(esm), so the tier-2 house deferral reaches it.\nconst _require = typeof require === 'undefined' ? createRequire(import.meta.url) : require;\n// Candidate queue depth gives uneven files more than one scheduling turn per worker.\n// The bounded parser comparison decides whether this value ships.\nconst BATCHES_PER_WORKER = 4;\n\n// parseMs is worker-side only (see workers/parse.ts); absent on the serial path.\nexport type FileResult = { doc: ParsedDoc; warnings: string[]; parseMs?: number };\n\n// Created lazily and reused while dispatch context stays equivalent. A builder owns one instance\n// for its lifetime instead of paying pool startup for unchanged reconciles.\nexport class ParsePool {\n private pool: TinypoolNS.Tinypool | undefined;\n private workerData: ParseWorkerData | undefined;\n private workerCount: number | undefined;\n private operation: Promise<void> = Promise.resolve();\n // Tinypools this instance has constructed. Repeated equivalent dispatches leave this unchanged;\n // a context/count change or close followed by run constructs another pool.\n poolsCreated = 0;\n\n private enqueue<T>(operation: () => Promise<T>): Promise<T> {\n const result = this.operation.then(operation);\n this.operation = result.then(\n () => undefined,\n () => undefined\n );\n return result;\n }\n\n private async ensure(workerData: ParseWorkerData, workerCount: number): Promise<TinypoolNS.Tinypool> {\n if (this.pool && (!isDeepStrictEqual(this.workerData, workerData) || this.workerCount !== workerCount)) await this.destroy();\n if (!this.pool) {\n const { Tinypool } = _require('tinypool') as typeof TinypoolNS;\n this.pool = new Tinypool({ filename: resolveWorkerFile('parse'), minThreads: workerCount, maxThreads: workerCount, workerData });\n this.workerData = workerData;\n this.workerCount = workerCount;\n this.poolsCreated++;\n }\n return this.pool;\n }\n\n // Never the tree: a worker task carries a bounded FileStat batch and returns only what\n // parseFile returns for each file, never the token tree.\n run(files: FileStat[], features: Feature[], cfg: Config, onParsed: ((done: number) => void) | undefined, requestedWorkers: number): Promise<FileResult[]> {\n if (files.length === 0) return Promise.resolve([]);\n // Snapshot at invocation so caller mutation cannot change queued work or its reuse baseline.\n const workerData: ParseWorkerData = { cfg: structuredClone(cfg), featureNames: [...new Set(features.map((feature) => feature.name))].sort() };\n const workerCount = Math.max(1, Math.min(requestedWorkers, files.length));\n return this.enqueue(() => this.dispatch(files, workerData, onParsed, workerCount));\n }\n\n private async dispatch(files: FileStat[], workerData: ParseWorkerData, onParsed: ((done: number) => void) | undefined, workerCount: number): Promise<FileResult[]> {\n const pool = await this.ensure(workerData, workerCount);\n const batches = batchFiles(files, Math.min(files.length, workerCount * BATCHES_PER_WORKER));\n let done = 0;\n const settled = await Promise.all(\n batches.map(async (batch): Promise<{ results: FileResult[]; failures: unknown[] }> => {\n let taskResults: ParseTaskResult;\n try {\n taskResults = (await pool.run(batch)) as ParseTaskResult;\n } catch (err) {\n return { results: [], failures: [err] };\n }\n\n const results: FileResult[] = [];\n const failures: unknown[] = [];\n for (const result of taskResults) {\n if (!result.ok) {\n failures.push(reviveError(result.error));\n continue;\n }\n results.push({ doc: result.doc, warnings: result.warnings, parseMs: result.parseMs });\n try {\n onParsed?.(++done);\n } catch (err) {\n failures.push(err);\n }\n }\n return { results, failures };\n })\n );\n const results: FileResult[] = [];\n const failures: unknown[] = [];\n for (const batch of settled) {\n results.push(...batch.results);\n failures.push(...batch.failures);\n }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1) throw new AggregateError(failures, `${failures.length} parse tasks failed`);\n // Promise.all and contiguous batches preserve the input order that first-seen columns use.\n return results;\n }\n\n private async destroy(): Promise<void> {\n if (!this.pool) return;\n const pool = this.pool;\n await pool.destroy();\n this.pool = undefined;\n this.workerData = undefined;\n this.workerCount = undefined;\n }\n\n // A pool never created costs nothing to destroy. Queuing lets active dispatches drain first.\n close(): Promise<void> {\n return this.enqueue(() => this.destroy());\n }\n}\n\nfunction batchFiles(files: FileStat[], batchCount: number): FileStat[][] {\n const batches: FileStat[][] = [];\n let start = 0;\n let remainingBytes = files.reduce((sum, file) => sum + file.size, 0);\n\n for (let batchIndex = 0; batchIndex < batchCount; batchIndex++) {\n const remainingBatches = batchCount - batchIndex;\n if (remainingBatches === 1) {\n batches.push(files.slice(start));\n break;\n }\n\n const targetBytes = remainingBytes / remainingBatches;\n const lastEnd = files.length - (remainingBatches - 1);\n let end = start;\n let bytes = 0;\n while (end < lastEnd && (end === start || bytes < targetBytes)) {\n bytes += files[end].size;\n end++;\n }\n batches.push(files.slice(start, end));\n start = end;\n remainingBytes -= bytes;\n }\n return batches;\n}\n"],"names":["ParsePool","_require","require","createRequire","BATCHES_PER_WORKER","operation","Promise","resolve","poolsCreated","enqueue","result","then","undefined","ensure","workerData","workerCount","Tinypool","pool","isDeepStrictEqual","destroy","filename","resolveWorkerFile","minThreads","maxThreads","run","files","features","cfg","onParsed","requestedWorkers","length","structuredClone","featureNames","Set","map","feature","name","sort","Math","max","min","dispatch","batches","done","settled","results","failures","batch","batchFiles","all","taskResults","err","ok","push","reviveError","error","doc","warnings","parseMs","AggregateError","close","batchCount","start","remainingBytes","reduce","sum","file","size","batchIndex","remainingBatches","slice","targetBytes","lastEnd","end","bytes"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/scan/reparse.ts"],"sourcesContent":["import { availableParallelism } from 'node:os';\nimport type { Config } from '../config/index.ts';\nimport type { Feature } from '../features/types.ts';\nimport type { ParsedDoc } from './index.ts';\nimport { parseFile } from './index.ts';\nimport type { FileStat } from './list.ts';\nimport type { FileResult } from './pool.ts';\nimport { ParsePool } from './pool.ts';\n\n// Store-agnostic per-file parse pass shared by every store's reconcile(). Index-preserving:\n// one pass over `files`, pushed in order.\nexport interface ReparseResult {\n docs: ParsedDoc[];\n warnings: string[];\n // Frontmatter keys not in `knownColumns`, first-seen order -- the order callers ALTER TABLE ADD COLUMN in.\n newColumns: string[];\n // Sum of worker-side parseFile time (workers/parse.ts) across files; 0 on the serial path.\n workerParseMs: number;\n}\n\nexport interface ReparseOptions {\n // Overrides PARSE_BYTES_PER_WORKER below. Zero forces worker dispatch in tests.\n // Internal: no caller in src/ passes it.\n threshold?: number;\n // Overrides DEFAULT_MAX_WORKERS below.\n maxWorkers?: number;\n // A builder-owned pool to dispatch through instead of creating and destroying one for this\n // call alone (see store/builder.ts). Absent, reparseFiles manages its own ephemeral pool.\n pool?: ParsePool;\n}\n\n// The 2026-09-26 comparison kept ~326 KiB updates serial and 5.86 MiB work pooled.\n// Companion byte shares prevent one dominant file from selecting workers for a tiny remainder.\nexport const PARSE_BYTES_PER_WORKER = 512 * 1024;\nconst DEFAULT_MAX_WORKERS = 8;\n\n// Per-file feature filtering, shared by the serial loop (reads `features` from the caller) and\n// the worker path (can only pass `cfg` across the thread boundary, so derives `features` itself).\nexport function featuresForFile(features: Feature[], cfg: Config, file: FileStat): Feature[] {\n return features.filter((feature) => !feature.enabledForFile || feature.enabledForFile(cfg, file));\n}\n\nfunction reparseSerial(files: FileStat[], features: Feature[], cfg: Config, onParsed?: (done: number) => void): FileResult[] {\n const results: FileResult[] = [];\n let done = 0;\n for (const file of files) {\n const fileFeatures = featuresForFile(features, cfg, file);\n results.push(parseFile(file, fileFeatures, cfg));\n onParsed?.(++done);\n }\n return results;\n}\n\n// Dispatches through `pool` when the caller owns one (a builder, kept alive across calls); with\n// none given, opens an ephemeral ParsePool for this call alone and always closes it.\nasync function reparsePooled(files: FileStat[], features: Feature[], cfg: Config, onParsed: ((done: number) => void) | undefined, maxWorkers: number, pool: ParsePool | undefined): Promise<FileResult[]> {\n if (pool) return pool.run(files, features, cfg, onParsed, maxWorkers);\n const ephemeral = new ParsePool();\n let results: FileResult[] | undefined;\n let dispatchError: unknown;\n let dispatchFailed = false;\n try {\n results = await ephemeral.run(files, features, cfg, onParsed, maxWorkers);\n } catch (err) {\n dispatchFailed = true;\n dispatchError = err;\n }\n try {\n await ephemeral.close();\n } catch (closeError) {\n if (dispatchFailed) throw new AggregateError([dispatchError, closeError], 'parse dispatch and pool close failed');\n throw closeError;\n }\n if (dispatchFailed) throw dispatchError;\n if (results === undefined) throw new Error('parse dispatch finished without results');\n return results;\n}\n\nfunction parseWorkerCount(files: FileStat[], bytesPerWorker: number, maxWorkers: number): number {\n if (files.length === 0) return 0;\n const available = Math.max(1, Math.min(maxWorkers, files.length));\n if (bytesPerWorker === 0) return available;\n let totalBytes = 0;\n let largestBytes = 0;\n for (const file of files) {\n totalBytes += file.size;\n largestBytes = Math.max(largestBytes, file.size);\n }\n const aggregateWorkers = Math.floor(totalBytes / bytesPerWorker);\n // The largest file is indivisible, so extra workers need full shares among the remainder.\n const companionWorkers = 1 + Math.floor((totalBytes - largestBytes) / bytesPerWorker);\n return Math.min(available, aggregateWorkers, companionWorkers);\n}\n\n// `onParsed` receives the running count (1-based) after each file, mirroring a Progress.tick\n// call; pass one in to keep progress reporting working without this module owning a reporter.\nexport async function reparseFiles(files: FileStat[], features: Feature[], cfg: Config, knownColumns: ReadonlySet<string>, onParsed?: (done: number) => void, options: ReparseOptions = {}): Promise<ReparseResult> {\n const threshold = options.threshold ?? PARSE_BYTES_PER_WORKER;\n const maxWorkers = options.maxWorkers ?? Math.min(DEFAULT_MAX_WORKERS, availableParallelism());\n const workerCount = parseWorkerCount(files, threshold, maxWorkers);\n const pooled = files.length > 0 && (threshold === 0 || workerCount >= 2);\n const results = pooled ? await reparsePooled(files, features, cfg, onParsed, workerCount, options.pool) : reparseSerial(files, features, cfg, onParsed);\n\n const docs: ParsedDoc[] = [];\n const warnings: string[] = [];\n const newColumns: string[] = [];\n const seen = new Set(knownColumns);\n let workerParseMs = 0;\n for (const { doc, warnings: fileWarnings, parseMs } of results) {\n warnings.push(...fileWarnings);\n workerParseMs += parseMs ?? 0;\n for (const key of Object.keys(doc.data)) {\n if (!seen.has(key)) {\n seen.add(key);\n newColumns.push(key);\n }\n }\n docs.push(doc);\n }\n\n return { docs, warnings, newColumns, workerParseMs };\n}\n"],"names":["PARSE_BYTES_PER_WORKER","featuresForFile","reparseFiles","DEFAULT_MAX_WORKERS","features","cfg","file","filter","feature","enabledForFile","reparseSerial","files","onParsed","results","done","fileFeatures","push","parseFile","reparsePooled","maxWorkers","pool","ephemeral","dispatchError","dispatchFailed","err","closeError","run","ParsePool","close","AggregateError","undefined","Error","parseWorkerCount","bytesPerWorker","length","available","Math","max","min","totalBytes","largestBytes","size","aggregateWorkers","floor","companionWorkers","knownColumns","options","threshold","workerCount","pooled","docs","warnings","newColumns","seen","workerParseMs","doc","fileWarnings","parseMs","key","availableParallelism","Set","Object","keys","data","has","add"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/scan/reparse.ts"],"sourcesContent":["import { availableParallelism } from 'node:os';\nimport type { Config } from '../config/index.ts';\nimport type { Feature } from '../features/types.ts';\nimport type { ParsedDoc } from './index.ts';\nimport { parseFile } from './index.ts';\nimport type { FileStat } from './list.ts';\nimport type { FileResult } from './pool.ts';\nimport { ParsePool } from './pool.ts';\n\n// Store-agnostic per-file parse pass shared by every store's reconcile(). Index-preserving:\n// one pass over `files`, pushed in order.\nexport interface ReparseResult {\n docs: ParsedDoc[];\n warnings: string[];\n // Frontmatter keys not in `knownColumns`, first-seen order -- the order callers ALTER TABLE ADD COLUMN in.\n newColumns: string[];\n // Sum of worker-side parseFile time (workers/parse.ts) across files; 0 on the serial path.\n workerParseMs: number;\n}\n\nexport interface ReparseOptions {\n // Overrides PARSE_BYTES_PER_WORKER below. Zero forces worker dispatch in tests.\n // Internal: no caller in src/ passes it.\n threshold?: number;\n // Overrides DEFAULT_MAX_WORKERS below.\n maxWorkers?: number;\n // A builder-owned pool to dispatch through instead of creating and destroying one for this\n // call alone (see store/builder.ts). Absent, reparseFiles manages its own ephemeral pool.\n pool?: ParsePool;\n}\n\n// The 2026-09-26 comparison kept ~326 KiB updates serial and 5.86 MiB work pooled.\n// Companion byte shares prevent one dominant file from selecting workers for a tiny remainder.\nexport const PARSE_BYTES_PER_WORKER = 512 * 1024;\nconst DEFAULT_MAX_WORKERS = 8;\n\n// Per-file feature filtering, shared by the serial loop (reads `features` from the caller) and\n// the worker path (can only pass `cfg` across the thread boundary, so derives `features` itself).\nexport function featuresForFile(features: Feature[], cfg: Config, file: FileStat): Feature[] {\n return features.filter((feature) => !feature.enabledForFile || feature.enabledForFile(cfg, file));\n}\n\nfunction reparseSerial(files: FileStat[], features: Feature[], cfg: Config, onParsed?: (done: number) => void): FileResult[] {\n const results: FileResult[] = [];\n let done = 0;\n for (const file of files) {\n const fileFeatures = featuresForFile(features, cfg, file);\n results.push(parseFile(file, fileFeatures, cfg));\n onParsed?.(++done);\n }\n return results;\n}\n\n// Dispatches through `pool` when the caller owns one (a builder, kept alive across calls); with\n// none given, opens an ephemeral ParsePool for this call alone and always closes it.\nasync function reparsePooled(files: FileStat[], features: Feature[], cfg: Config, onParsed: ((done: number) => void) | undefined, maxWorkers: number, pool: ParsePool | undefined): Promise<FileResult[]> {\n if (pool) return pool.run(files, features, cfg, onParsed, maxWorkers);\n const ephemeral = new ParsePool();\n let results: FileResult[] | undefined;\n let dispatchError: unknown;\n let dispatchFailed = false;\n try {\n results = await ephemeral.run(files, features, cfg, onParsed, maxWorkers);\n } catch (err) {\n dispatchFailed = true;\n dispatchError = err;\n }\n try {\n await ephemeral.close();\n } catch (closeError) {\n if (dispatchFailed) throw new AggregateError([dispatchError, closeError], 'parse dispatch and pool close failed');\n throw closeError;\n }\n if (dispatchFailed) throw dispatchError;\n if (results === undefined) throw new Error('parse dispatch finished without results');\n return results;\n}\n\nfunction parseWorkerCount(files: FileStat[], bytesPerWorker: number, maxWorkers: number): number {\n if (files.length === 0) return 0;\n const available = Math.max(1, Math.min(maxWorkers, files.length));\n if (bytesPerWorker === 0) return available;\n let totalBytes = 0;\n let largestBytes = 0;\n for (const file of files) {\n totalBytes += file.size;\n largestBytes = Math.max(largestBytes, file.size);\n }\n const aggregateWorkers = Math.floor(totalBytes / bytesPerWorker);\n // The largest file is indivisible, so extra workers need full shares among the remainder.\n const companionWorkers = 1 + Math.floor((totalBytes - largestBytes) / bytesPerWorker);\n return Math.min(available, aggregateWorkers, companionWorkers);\n}\n\n// `onParsed` receives the running count (1-based) after each file, mirroring a Progress.tick\n// call; pass one in to keep progress reporting working without this module owning a reporter.\nexport async function reparseFiles(files: FileStat[], features: Feature[], cfg: Config, knownColumns: ReadonlySet<string>, onParsed?: (done: number) => void, options: ReparseOptions = {}): Promise<ReparseResult> {\n const threshold = options.threshold ?? PARSE_BYTES_PER_WORKER;\n const maxWorkers = options.maxWorkers ?? Math.min(DEFAULT_MAX_WORKERS, availableParallelism());\n const workerCount = parseWorkerCount(files, threshold, maxWorkers);\n const pooled = files.length > 0 && (threshold === 0 || workerCount >= 2);\n const results = pooled ? await reparsePooled(files, features, cfg, onParsed, workerCount, options.pool) : reparseSerial(files, features, cfg, onParsed);\n\n const docs: ParsedDoc[] = [];\n const warnings: string[] = [];\n const newColumns: string[] = [];\n const seen = new Set(knownColumns);\n let workerParseMs = 0;\n for (const { doc, warnings: fileWarnings, parseMs } of results) {\n warnings.push(...fileWarnings);\n workerParseMs += parseMs ?? 0;\n for (const key of Object.keys(doc.data)) {\n if (!seen.has(key)) {\n seen.add(key);\n newColumns.push(key);\n }\n }\n docs.push(doc);\n }\n\n return { docs, warnings, newColumns, workerParseMs };\n}\n"],"names":["PARSE_BYTES_PER_WORKER","featuresForFile","reparseFiles","DEFAULT_MAX_WORKERS","features","cfg","file","filter","feature","enabledForFile","reparseSerial","files","onParsed","results","done","fileFeatures","push","parseFile","reparsePooled","maxWorkers","pool","ephemeral","dispatchError","dispatchFailed","err","closeError","run","ParsePool","close","AggregateError","undefined","Error","parseWorkerCount","bytesPerWorker","length","available","Math","max","min","totalBytes","largestBytes","size","aggregateWorkers","floor","companionWorkers","knownColumns","options","threshold","workerCount","pooled","docs","warnings","newColumns","seen","workerParseMs","doc","fileWarnings","parseMs","key","availableParallelism","Set","Object","keys","data","has","add"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/scan/worker-error.ts"],"sourcesContent":["import { SenseError, type SenseErrorCode } from '../errors.ts';\n\n// Structured clone across a worker_threads boundary drops a subclass and its custom properties, so\n// a SenseError arrives as a plain Error with `code` undefined (and `code` drives caller behavior): the worker serializes explicitly and the main thread rebuilds by hand.\nexport interface WorkerErrorPayload {\n name: string;\n code?: SenseErrorCode;\n message: string;\n stack?: string;\n}\n\nexport function serializeError(err: unknown): WorkerErrorPayload {\n if (err instanceof Error) return { name: err.name, code: err instanceof SenseError ? err.code : undefined, message: err.message, stack: err.stack };\n return { name: 'Error', message: String(err) };\n}\n\nexport function reviveError(payload: WorkerErrorPayload): Error {\n const err = payload.code ? new SenseError(payload.code, payload.message) : new Error(payload.message);\n err.name = payload.name;\n if (payload.stack) err.stack = payload.stack;\n return err;\n}\n"],"names":["reviveError","serializeError","err","Error","name","code","SenseError","undefined","message","stack","String","payload"],"mappings":";;;;;;;;;;;QAgBgBA;eAAAA;;QALAC;eAAAA;;;wBAXgC;;;;;;;AAWzC,SAASA,eAAeC,GAAY;IACzC,IAAIA,AAAG,YAAHA,KAAeC,QAAO,OAAO;QAAEC,MAAMF,IAAIE,IAAI;QAAEC,MAAMH,AAAG,YAAHA,KAAeI,oBAAU,IAAGJ,IAAIG,IAAI,GAAGE;QAAWC,SAASN,IAAIM,OAAO;QAAEC,OAAOP,IAAIO,KAAK;IAAC;IAClJ,OAAO;QAAEL,MAAM;QAASI,SAASE,OAAOR;IAAK;AAC/C;AAEO,SAASF,YAAYW,OAA2B;IACrD,IAAMT,MAAMS,QAAQN,IAAI,GAAG,IAAIC,oBAAU,CAACK,QAAQN,IAAI,EAAEM,QAAQH,OAAO,IAAI,IAAIL,MAAMQ,QAAQH,OAAO;IACpGN,IAAIE,IAAI,GAAGO,QAAQP,IAAI;IACvB,IAAIO,QAAQF,KAAK,EAAEP,IAAIO,KAAK,GAAGE,QAAQF,KAAK;IAC5C,OAAOP;AACT"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/scan/worker-error.ts"],"sourcesContent":["import { SenseError, type SenseErrorCode } from '../errors.ts';\n\n// Structured clone across a worker_threads boundary drops a subclass and its custom properties, so\n// a SenseError arrives as a plain Error with `code` undefined (and `code` drives caller behavior): the worker serializes explicitly and the main thread rebuilds by hand.\nexport interface WorkerErrorPayload {\n name: string;\n code?: SenseErrorCode;\n message: string;\n stack?: string;\n}\n\nexport function serializeError(err: unknown): WorkerErrorPayload {\n if (err instanceof Error) return { name: err.name, code: err instanceof SenseError ? err.code : undefined, message: err.message, stack: err.stack };\n return { name: 'Error', message: String(err) };\n}\n\nexport function reviveError(payload: WorkerErrorPayload): Error {\n const err = payload.code ? new SenseError(payload.code, payload.message) : new Error(payload.message);\n err.name = payload.name;\n if (payload.stack) err.stack = payload.stack;\n return err;\n}\n"],"names":["reviveError","serializeError","err","Error","name","code","SenseError","undefined","message","stack","String","payload"],"mappings":";;;;;;;;;;;QAgBgBA;eAAAA;;QALAC;eAAAA;;;wBAXgC;;;;;;;AAWzC,SAASA,eAAeC,GAAY;IACzC,IAAIA,AAAG,YAAHA,KAAeC,QAAO,OAAO;QAAEC,MAAMF,IAAIE,IAAI;QAAEC,MAAMH,AAAG,YAAHA,KAAeI,oBAAU,IAAGJ,IAAIG,IAAI,GAAGE;QAAWC,SAASN,IAAIM,OAAO;QAAEC,OAAOP,IAAIO,KAAK;IAAC;IAClJ,OAAO;QAAEL,MAAM;QAASI,SAASE,OAAOR;IAAK;AAC/C;AAEO,SAASF,YAAYW,OAA2B;IACrD,IAAMT,MAAMS,QAAQN,IAAI,GAAG,IAAIC,oBAAU,CAACK,QAAQN,IAAI,EAAEM,QAAQH,OAAO,IAAI,IAAIL,MAAMQ,QAAQH,OAAO;IACpGN,IAAIE,IAAI,GAAGO,QAAQP,IAAI;IACvB,IAAIO,QAAQF,KAAK,EAAEP,IAAIO,KAAK,GAAGE,QAAQF,KAAK;IAC5C,OAAOP;AACT"}