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/store/reconcile.ts"],"sourcesContent":["import type { Config } from '../config/index.ts';\nimport { activeFeatures } from '../features/index.ts';\nimport type { ExtractedDoc, ReconcileDelta } from '../features/types.ts';\nimport { progress } from '../output/progress.ts';\nimport { listFiles, RESERVED_COLUMNS } from '../scan/index.ts';\nimport type { ParsePool } from '../scan/pool.ts';\nimport { reparseFiles } from '../scan/reparse.ts';\nimport { recordLockWaitMs } from './lock-wait.ts';\nimport { appendRows, getColumns, quoteIdent } from './shared.ts';\nimport { featureStage, type StageRecorder, type Stages, stageRecorder } from './stages.ts';\nimport { withTransaction } from './transaction.ts';\nimport type { Connection, ReconcileDialect } from './types.ts';\n\n// One reconcile algorithm shared by every store, parameterised by a per-engine ReconcileDialect\n// (types.ts). Ordering is universal, not a dialect concern: ALTER, then the frontmatter upsert,\n// then reconcileContent, then preset_files, then the vanished-frontmatter delete, then feature hooks\n// -- a vanished path's content delete (inside reconcileContent) must precede its frontmatter\n// delete, since sqlite's delete SQL resolves the row via its frontmatter rowid.\n\n// Feature-owned columns (`_rank`) must stay out of the upsert: a reparse would null the last\n// computed value on every touch, not just the reconciles that recompute it.\nexport const CORE_FRONTMATTER_COLUMNS = new Set(['path', '_mtime', '_ctime', '_size', '_parse_error']);\n\nexport interface ReconcilePaths {\n rootDir: string;\n configDir: string;\n}\n\nexport interface ReconcileSnapshot {\n existingRows: Array<{ path: string; _mtime: number; _size: number }>;\n seenColumns: Set<string>;\n}\n\nexport interface ReconcilePlan {\n mutated: boolean;\n parsed: number;\n warnings: string[];\n apply(conn: Connection): Promise<void>;\n finish(txMs: number): Stages;\n record(conn: Connection, txMs: number): Promise<void>;\n}\n\nexport interface ReconcileTiming {\n stages: StageRecorder;\n elapsed(): number;\n workerParseMs: number;\n txMs: number;\n}\n\nexport function createReconcileTiming(cfg: Config): ReconcileTiming {\n const start = process.hrtime.bigint();\n return {\n stages: stageRecorder(activeFeatures(cfg).map((feature) => feature.name)),\n elapsed: () => Number(process.hrtime.bigint() - start) / 1e6,\n workerParseMs: 0,\n txMs: 0,\n };\n}\n\n// Called inside the builder's short planning snapshot, alongside its metadata baseline. Parsing\n// happens only after that transaction closes; publication later rejects this state if generation\n// or configuration moved in the meantime.\nexport async function readReconcileSnapshot(conn: Connection, timing: ReconcileTiming): Promise<ReconcileSnapshot> {\n const existingRows = await timing.stages.time('existing', async () => {\n const existingStmt = await conn.prepare('SELECT \"path\", \"_mtime\", \"_size\" FROM frontmatter');\n return (await existingStmt.all()) as ReconcileSnapshot['existingRows'];\n });\n return { existingRows, seenColumns: await getColumns(conn) };\n}\n\nexport async function prepareReconcile(snapshot: ReconcileSnapshot, cfg: Config, paths: ReconcilePaths, dialect: ReconcileDialect, timing: ReconcileTiming, pool?: ParsePool, forcedPaths?: ReadonlySet<string>): Promise<ReconcilePlan> {\n const { rootDir, configDir } = paths;\n const features = activeFeatures(cfg);\n const { stages, elapsed } = timing;\n const files = await stages.time('list', () => listFiles(cfg, rootDir));\n const currentSet = new Set(files.map((f) => f.relPath));\n const existingRows = snapshot.existingRows;\n const existing = new Map(existingRows.map((r) => [r.path, r]));\n // A path whose coverage moved between presets (forcedPaths) but is no longer covered at all is\n // already caught below by !currentSet.has, since it can only be forced by having existed under\n // an old preset's match, which means it was reconciled into `existing` already.\n const vanished = existingRows.filter((r) => !currentSet.has(r.path)).map((r) => r.path);\n\n // forcedPaths treats an unchanged file as touched because its preset coverage moved, not its\n // stamp -- reconcile still owns add/update/remove and every cross-feature cascade for it.\n const toReparse = files.filter((f) => {\n const row = existing.get(f.relPath);\n return !row || row._mtime !== f.mtimeMs || row._size !== f.size || (forcedPaths?.has(f.relPath) ?? false);\n });\n\n if (vanished.length === 0 && toReparse.length === 0) {\n return {\n mutated: false,\n parsed: 0,\n warnings: [],\n apply: async () => {},\n finish: (txMs) => stages.take(elapsed(), txMs, timing.workerParseMs),\n record: async () => {},\n };\n }\n\n const seenColumns = new Set(snapshot.seenColumns);\n\n // Bulk reparses (a sync, a cold build) are the long silences a query can hit; short\n // reconciles stay silent (progress() has a threshold).\n const report = progress('reparsing files', toReparse.length);\n // Pool wall time, dispatch to drain, so this stage shares a clock with every other one.\n const { docs: parsedDocs, warnings, newColumns, workerParseMs } = await stages.time('parse', () => reparseFiles(toReparse, features, cfg, seenColumns, report.tick, { pool }));\n timing.workerParseMs += workerParseMs;\n report.finish();\n for (const col of newColumns) seenColumns.add(col);\n\n const allColumns = [...seenColumns];\n // Fence before ALTERing: a store's own failure past this point is a raw, engine-specific\n // error with no indication of the boundary or the levers -- dialect.checkColumnLimit names both.\n dialect.checkColumnLimit(allColumns.length);\n // Columns the frontmatter upsert actually writes: core + parsed frontmatter keys, never a\n // feature-owned reserved column (see CORE_FRONTMATTER_COLUMNS above).\n const writableColumns = allColumns.filter((c) => CORE_FRONTMATTER_COLUMNS.has(c) || !RESERVED_COLUMNS.has(c));\n // ON CONFLICT DO UPDATE (not OR REPLACE) keeps the row's rowid stable across reparses --\n // sqlite's content rows are coupled to that rowid.\n const insertSql = `INSERT INTO frontmatter (${writableColumns.map(quoteIdent).join(', ')}) VALUES (${writableColumns.map(() => '?').join(', ')}) ON CONFLICT(\"path\") DO UPDATE SET ${writableColumns\n .filter((c) => c !== 'path')\n .map((c) => `${quoteIdent(c)} = excluded.${quoteIdent(c)}`)\n .join(', ')}`;\n\n const added = toReparse.filter((f) => !existing.has(f.relPath)).map((f) => f.relPath);\n const delta: ReconcileDelta = { files, reparsed: parsedDocs.map((d) => d.relPath), added, vanished };\n const addedSet = new Set(added);\n const reparsedExisting = parsedDocs.map((d) => d.relPath).filter((p) => !addedSet.has(p));\n // Paths whose content (and, per feature, other rows) need clearing: gone entirely, or about to\n // be reinserted fresh. Disjoint from `added`, which has nothing to clear.\n const touched = [...vanished, ...reparsedExisting];\n\n return {\n mutated: true,\n parsed: parsedDocs.length,\n warnings,\n async apply(conn) {\n // The generation fence already proved the planning snapshot current under this write lock.\n // Re-read columns only because schema setup is not itself a core generation publication.\n const present = await getColumns(conn);\n const missingColumns = newColumns.filter((col) => !present.has(col));\n if (missingColumns.length > 0) await stages.time('alter', () => dialect.addColumns(conn, missingColumns));\n\n if (parsedDocs.length > 0) {\n const toRow = (doc: (typeof parsedDocs)[number]) =>\n writableColumns.map((col) => {\n if (col === 'path') return doc.relPath;\n if (col === '_mtime') return doc.mtimeMs;\n if (col === '_ctime') return doc.ctimeMs;\n if (col === '_size') return doc.size;\n if (col === '_parse_error') return doc.parseError;\n return doc.data[col] ?? null;\n });\n await stages.time('fm-upsert', async () => {\n const newDocs = parsedDocs.filter((d) => addedSet.has(d.relPath));\n const updateDocs = parsedDocs.filter((d) => !addedSet.has(d.relPath));\n await appendRows(conn, 'frontmatter', writableColumns, insertSql, newDocs.map(toRow));\n if (updateDocs.length > 0) {\n const rows = updateDocs.map(toRow);\n if (dialect.updateFrontmatter) await dialect.updateFrontmatter(conn, writableColumns, rows);\n else await conn.runBatch(insertSql, rows);\n }\n });\n }\n\n await stages.time('text-index', () => dialect.reconcileContent(conn, touched, parsedDocs, delta, cfg));\n if (touched.length > 0)\n await conn.runBatch(\n 'DELETE FROM indexed_sources WHERE \"path\" = ?',\n touched.map((p) => [p])\n );\n await appendRows(\n conn,\n 'indexed_sources',\n ['path', 'text'],\n 'INSERT INTO indexed_sources (\"path\", text) VALUES (?, ?) ON CONFLICT(\"path\") DO UPDATE SET text = excluded.text',\n parsedDocs.map((doc) => [doc.relPath, doc.source])\n );\n\n await stages.time('presets', async () => {\n if (touched.length > 0)\n await conn.runBatch(\n 'DELETE FROM preset_files WHERE \"path\" = ?',\n touched.map((p) => [p])\n );\n const presetRows: unknown[][] = [];\n for (const doc of parsedDocs) for (const presetName of doc.presets) presetRows.push([doc.relPath, presetName]);\n await appendRows(conn, 'preset_files', ['path', 'preset'], 'INSERT INTO preset_files (\"path\", preset) VALUES (?, ?) ON CONFLICT(\"path\", preset) DO NOTHING', presetRows);\n });\n\n if (vanished.length > 0)\n await stages.time('vanished', () =>\n conn.runBatch(\n 'DELETE FROM frontmatter WHERE \"path\" = ?',\n vanished.map((p) => [p])\n )\n );\n\n if (touched.length > 0) for (const feature of features) await stages.time(featureStage(feature.name, 'remove'), () => feature.remove?.(conn, touched, delta));\n for (const feature of features) {\n const docsForFeature: ExtractedDoc[] = parsedDocs.map((doc) => ({ path: doc.relPath, extracted: doc.extracted[feature.name] }));\n await stages.time(featureStage(feature.name, 'store'), () => feature.store?.(conn, docsForFeature, delta));\n }\n for (const feature of features) await stages.time(featureStage(feature.name, 'after'), () => feature.afterReconcile?.(conn, delta));\n },\n finish: (txMs) => stages.take(elapsed(), txMs, timing.workerParseMs),\n async record(conn, txMs) {\n recordLockWaitMs(configDir, txMs);\n if (dialect.recordDuration) await stages.time('meta', () => dialect.recordDuration?.(conn, txMs));\n },\n };\n}\n\n// Lower-level entrypoint retained only for focused reconcile tests. It has no generation fence;\n// production publication must go through builder.ts, and any new caller must provide exclusivity.\nexport async function reconcile(conn: Connection, cfg: Config, paths: ReconcilePaths, dialect: ReconcileDialect, pool?: ParsePool, forcedPaths?: ReadonlySet<string>): Promise<{ parsed: number; warnings: string[]; stages: Stages }> {\n const timing = createReconcileTiming(cfg);\n const snapshot = await withTransaction(conn, () => readReconcileSnapshot(conn, timing));\n const plan = await prepareReconcile(snapshot, cfg, paths, dialect, timing, pool, forcedPaths);\n if (!plan.mutated) return { parsed: plan.parsed, warnings: plan.warnings, stages: plan.finish(0) };\n const txStart = Date.now();\n let txMs: number;\n try {\n await withTransaction(conn, () => plan.apply(conn), dialect.beginMode());\n } finally {\n txMs = Date.now() - txStart;\n timing.txMs += txMs;\n }\n await plan.record(conn, txMs);\n return { parsed: plan.parsed, warnings: plan.warnings, stages: plan.finish(timing.txMs) };\n}\n"],"names":["CORE_FRONTMATTER_COLUMNS","createReconcileTiming","prepareReconcile","readReconcileSnapshot","reconcile","Set","cfg","start","process","hrtime","bigint","stages","stageRecorder","activeFeatures","map","feature","name","elapsed","Number","workerParseMs","txMs","conn","timing","existingRows","time","existingStmt","prepare","all","getColumns","seenColumns","snapshot","paths","dialect","pool","forcedPaths","rootDir","configDir","features","files","currentSet","existing","vanished","toReparse","report","parsedDocs","warnings","newColumns","col","allColumns","writableColumns","insertSql","added","delta","addedSet","reparsedExisting","touched","listFiles","f","relPath","Map","r","path","filter","has","row","get","_mtime","mtimeMs","_size","size","length","mutated","parsed","apply","finish","take","record","progress","reparseFiles","tick","docs","add","checkColumnLimit","c","RESERVED_COLUMNS","quoteIdent","join","reparsed","d","p","present","missingColumns","toRow","addColumns","doc","ctimeMs","parseError","data","newDocs","updateDocs","rows","appendRows","updateFrontmatter","runBatch","reconcileContent","source","presetRows","presetName","presets","push","featureStage","remove","docsForFeature","extracted","store","afterReconcile","recordLockWaitMs","recordDuration","plan","txStart","withTransaction","Date","now","beginMode"],"mappings":";;;;;;;;;;;QAqBaA;eAAAA;;QA4BGC;eAAAA;;QAqBMC;eAAAA;;QARAC;eAAAA;;QA2JAC;eAAAA;;;uBAxNS;0BAEN;wBACmB;yBAEf;0BACI;wBACkB;wBAC0B;6BAC7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWzB,IAAMJ,2BAA2B,IAAIK,IAAI;IAAC;IAAQ;IAAU;IAAU;IAAS;CAAe;AA4B9F,SAASJ,sBAAsBK,GAAW;IAC/C,IAAMC,QAAQC,QAAQC,MAAM,CAACC,MAAM;IACnC,OAAO;QACLC,QAAQC,IAAAA,uBAAa,EAACC,IAAAA,uBAAc,EAACP,KAAKQ,GAAG,CAAC,SAACC;mBAAYA,QAAQC,IAAI;;QACvEC,SAAS,SAATA;mBAAeC,OAAOV,QAAQC,MAAM,CAACC,MAAM,KAAKH,SAAS;;QACzDY,eAAe;QACfC,MAAM;IACR;AACF;AAKO,SAAejB,sBAAsBkB,IAAgB,EAAEC,MAAuB;;YAC7EC;;;;oBAAe;;wBAAMD,OAAOX,MAAM,CAACa,IAAI,CAAC,YAAY;;oCAClDC;;;;4CAAe;;gDAAMJ,KAAKK,OAAO,CAAC;;;4CAAlCD,eAAe;4CACb;;gDAAMA,aAAaE,GAAG;;;4CAA9B;;gDAAQ;;;;4BACV;;;;oBAHMJ,eAAe;;wBAIZA,cAAAA;;oBAA2B;;wBAAMK,IAAAA,oBAAU,EAACP;;;oBAArD;;8BAAuBQ,cAAa;;;;IACtC;;AAEO,SAAe3B,iBAAiB4B,QAA2B,EAAExB,GAAW,EAAEyB,KAAqB,EAAEC,OAAyB,EAAEV,MAAuB,EAAEW,IAAgB,EAAEC,WAAiC;;YACrMC,SAASC,WACXC,UACE1B,QAAQM,SACVqB,OACAC,YACAhB,cACAiB,UAIAC,UAIAC,WAgBAb,aAIAc,QAE4D,MAApDC,YAAYC,UAAUC,YAAY3B,eAG3C,2BAAA,mBAAA,gBAAA,WAAA,OAAM4B,KAELC,YAMAC,iBAGAC,WAKAC,OACAC,OACAC,UACAC,kBAGAC;;;;oBA7DEpB,UAAuBJ,MAAvBI,SAASC,YAAcL,MAAdK;oBACXC,WAAWxB,IAAAA,uBAAc,EAACP;oBACxBK,SAAoBW,OAApBX,QAAQM,UAAYK,OAAZL;oBACF;;wBAAMN,OAAOa,IAAI,CAAC,QAAQ;mCAAMgC,IAAAA,mBAAS,EAAClD,KAAK6B;;;;oBAAvDG,QAAQ;oBACRC,aAAa,IAAIlC,IAAIiC,MAAMxB,GAAG,CAAC,SAAC2C;+BAAMA,EAAEC,OAAO;;oBAC/CnC,eAAeO,SAASP,YAAY;oBACpCiB,WAAW,IAAImB,IAAIpC,aAAaT,GAAG,CAAC,SAAC8C;+BAAM;4BAACA,EAAEC,IAAI;4BAAED;yBAAE;;oBAC5D,+FAA+F;oBAC/F,+FAA+F;oBAC/F,gFAAgF;oBAC1EnB,WAAWlB,aAAauC,MAAM,CAAC,SAACF;+BAAM,CAACrB,WAAWwB,GAAG,CAACH,EAAEC,IAAI;uBAAG/C,GAAG,CAAC,SAAC8C;+BAAMA,EAAEC,IAAI;;oBAEtF,6FAA6F;oBAC7F,0FAA0F;oBACpFnB,YAAYJ,MAAMwB,MAAM,CAAC,SAACL;;wBAC9B,IAAMO,MAAMxB,SAASyB,GAAG,CAACR,EAAEC,OAAO;wBAClC,OAAO,CAACM,OAAOA,IAAIE,MAAM,KAAKT,EAAEU,OAAO,IAAIH,IAAII,KAAK,KAAKX,EAAEY,IAAI,aAAKnC,wBAAAA,kCAAAA,YAAa6B,GAAG,CAACN,EAAEC,OAAO,wCAAK;oBACrG;oBAEA,IAAIjB,SAAS6B,MAAM,KAAK,KAAK5B,UAAU4B,MAAM,KAAK,GAAG;wBACnD;;4BAAO;gCACLC,SAAS;gCACTC,QAAQ;gCACR3B,QAAQ;gCACR4B,OAAO,SAAPA;;;;;;;oCAAoB;;gCACpBC,QAAQ,SAARA,OAAStD;2CAAST,OAAOgE,IAAI,CAAC1D,WAAWG,MAAME,OAAOH,aAAa;;gCACnEyD,QAAQ,SAARA;;;;;;;oCAAqB;;4BACvB;;oBACF;oBAEM/C,cAAc,IAAIxB,IAAIyB,SAASD,WAAW;oBAEhD,oFAAoF;oBACpF,uDAAuD;oBACjDc,SAASkC,IAAAA,oBAAQ,EAAC,mBAAmBnC,UAAU4B,MAAM;oBAEO;;wBAAM3D,OAAOa,IAAI,CAAC,SAAS;mCAAMsD,IAAAA,uBAAY,EAACpC,WAAWL,UAAU/B,KAAKuB,aAAac,OAAOoC,IAAI,EAAE;gCAAE9C,MAAAA;4BAAK;;;;oBAAzG,OAAA,eAApDW,aAAoD,KAA1DoC,MAAkBnC,WAAwC,KAAxCA,UAAUC,aAA8B,KAA9BA,YAAY3B,gBAAkB,KAAlBA;oBAChDG,OAAOH,aAAa,IAAIA;oBACxBwB,OAAO+B,MAAM;oBACR,kCAAA,2BAAA;;wBAAL,IAAK,YAAa5B,iCAAb,6BAAA,QAAA,yBAAA;4BAAMC,MAAN;4BAAyBlB,YAAYoD,GAAG,CAAClC;;;wBAAzC;wBAAA;;;iCAAA,6BAAA;gCAAA;;;gCAAA;sCAAA;;;;oBAECC,aAAc,qBAAGnB;oBACvB,yFAAyF;oBACzF,iGAAiG;oBACjGG,QAAQkD,gBAAgB,CAAClC,WAAWsB,MAAM;oBAC1C,0FAA0F;oBAC1F,sEAAsE;oBAChErB,kBAAkBD,WAAWc,MAAM,CAAC,SAACqB;+BAAMnF,yBAAyB+D,GAAG,CAACoB,MAAM,CAACC,0BAAgB,CAACrB,GAAG,CAACoB;;oBAC1G,yFAAyF;oBACzF,mDAAmD;oBAC7CjC,YAAY,AAAC,4BAAkFD,OAAvDA,gBAAgBnC,GAAG,CAACuE,oBAAU,EAAEC,IAAI,CAAC,OAAM,cAA4FrC,OAAhFA,gBAAgBnC,GAAG,CAAC;+BAAM;uBAAKwE,IAAI,CAAC,OAAM,wCAGjI,OAHuKrC,gBAClLa,MAAM,CAAC,SAACqB;+BAAMA,MAAM;uBACpBrE,GAAG,CAAC,SAACqE;+BAAM,AAAC,GAA8BE,OAA5BA,IAAAA,oBAAU,EAACF,IAAG,gBAA4B,OAAdE,IAAAA,oBAAU,EAACF;uBACrDG,IAAI,CAAC;oBAEFnC,QAAQT,UAAUoB,MAAM,CAAC,SAACL;+BAAM,CAACjB,SAASuB,GAAG,CAACN,EAAEC,OAAO;uBAAG5C,GAAG,CAAC,SAAC2C;+BAAMA,EAAEC,OAAO;;oBAC9EN,QAAwB;wBAAEd,OAAAA;wBAAOiD,UAAU3C,WAAW9B,GAAG,CAAC,SAAC0E;mCAAMA,EAAE9B,OAAO;;wBAAGP,OAAAA;wBAAOV,UAAAA;oBAAS;oBAC7FY,WAAW,IAAIhD,IAAI8C;oBACnBG,mBAAmBV,WAAW9B,GAAG,CAAC,SAAC0E;+BAAMA,EAAE9B,OAAO;uBAAEI,MAAM,CAAC,SAAC2B;+BAAM,CAACpC,SAASU,GAAG,CAAC0B;;oBACtF,+FAA+F;oBAC/F,0EAA0E;oBACpElC,UAAU,AAAC,qBAAGd,iBAAU,qBAAGa;oBAEjC;;wBAAO;4BACLiB,SAAS;4BACTC,QAAQ5B,WAAW0B,MAAM;4BACzBzB,UAAAA;4BACM4B,OAAN,SAAMA,MAAMpD,IAAI;;wCAGRqE,SACAC,gBAIEC,OAsDqB,2BAAA,mBAAA,uBAAA,WAAA,YACxB,4BAAA,oBAAA,yBAAA,YAAA,aAIA,4BAAA,oBAAA,yBAAA,YAAA;;;;gDAhEW;;oDAAMhE,IAAAA,oBAAU,EAACP;;;gDAA3BqE,UAAU;gDACVC,iBAAiB7C,WAAWgB,MAAM,CAAC,SAACf;2DAAQ,CAAC2C,QAAQ3B,GAAG,CAAChB;;qDAC3D4C,CAAAA,eAAerB,MAAM,GAAG,CAAA,GAAxBqB;;;;gDAA2B;;oDAAMhF,OAAOa,IAAI,CAAC,SAAS;+DAAMQ,QAAQ6D,UAAU,CAACxE,MAAMsE;;;;gDAA1D;;;qDAE3B/C,CAAAA,WAAW0B,MAAM,GAAG,CAAA,GAApB1B;;;;gDACIgD,QAAQ,eAACE;2DACb7C,gBAAgBnC,GAAG,CAAC,SAACiC;4DAMZ+C;wDALP,IAAI/C,QAAQ,QAAQ,OAAO+C,IAAIpC,OAAO;wDACtC,IAAIX,QAAQ,UAAU,OAAO+C,IAAI3B,OAAO;wDACxC,IAAIpB,QAAQ,UAAU,OAAO+C,IAAIC,OAAO;wDACxC,IAAIhD,QAAQ,SAAS,OAAO+C,IAAIzB,IAAI;wDACpC,IAAItB,QAAQ,gBAAgB,OAAO+C,IAAIE,UAAU;wDACjD,QAAOF,gBAAAA,IAAIG,IAAI,CAAClD,IAAI,cAAb+C,2BAAAA,gBAAiB;oDAC1B;;gDACF;;oDAAMnF,OAAOa,IAAI,CAAC,aAAa;;gEACvB0E,SACAC,YAGEC;;;;wEAJFF,UAAUtD,WAAWkB,MAAM,CAAC,SAAC0B;mFAAMnC,SAASU,GAAG,CAACyB,EAAE9B,OAAO;;wEACzDyC,aAAavD,WAAWkB,MAAM,CAAC,SAAC0B;mFAAM,CAACnC,SAASU,GAAG,CAACyB,EAAE9B,OAAO;;wEACnE;;4EAAM2C,IAAAA,oBAAU,EAAChF,MAAM,eAAe4B,iBAAiBC,WAAWgD,QAAQpF,GAAG,CAAC8E;;;wEAA9E;6EACIO,CAAAA,WAAW7B,MAAM,GAAG,CAAA,GAApB6B;;;;wEACIC,OAAOD,WAAWrF,GAAG,CAAC8E;6EACxB5D,QAAQsE,iBAAiB,EAAzBtE;;;;wEAA2B;;4EAAMA,QAAQsE,iBAAiB,CAACjF,MAAM4B,iBAAiBmD;;;wEAAvD;;;;;;wEAC1B;;4EAAM/E,KAAKkF,QAAQ,CAACrD,WAAWkD;;;wEAA/B;;;;;;;;wDAET;;;;gDATA;;;gDAYF;;oDAAMzF,OAAOa,IAAI,CAAC,cAAc;+DAAMQ,QAAQwE,gBAAgB,CAACnF,MAAMkC,SAASX,YAAYQ,OAAO9C;;;;gDAAjG;qDACIiD,CAAAA,QAAQe,MAAM,GAAG,CAAA,GAAjBf;;;;gDACF;;oDAAMlC,KAAKkF,QAAQ,CACjB,gDACAhD,QAAQzC,GAAG,CAAC,SAAC2E;+DAAM;4DAACA;yDAAE;;;;gDAFxB;;;gDAIF;;oDAAMY,IAAAA,oBAAU,EACdhF,MACA;wDACC;wDAAQ;uDACT,mHACAuB,WAAW9B,GAAG,CAAC,SAACgF;+DAAQ;4DAACA,IAAIpC,OAAO;4DAAEoC,IAAIW,MAAM;yDAAC;;;;gDALnD;gDAQA;;oDAAM9F,OAAOa,IAAI,CAAC,WAAW;;gEAMrBkF,YAC6B,2BAAA,mBAAA,gBAA9B,4BAAA,oBAAA,iBAAA,WAAA,OAAMZ,KAAwB,YAAA,QAAMa;;;;6EANrCpD,CAAAA,QAAQe,MAAM,GAAG,CAAA,GAAjBf;;;;wEACF;;4EAAMlC,KAAKkF,QAAQ,CACjB,6CACAhD,QAAQzC,GAAG,CAAC,SAAC2E;uFAAM;oFAACA;iFAAE;;;;wEAFxB;;;wEAIIiB;wEAC6B,kCAAA,2BAAA,4BAA9B,mCAAA,4BAAA;;4EAAL,IAAK,YAAa9D,iCAAb,8BAAA,QAAA,yBAAA;gFAAMkD,MAAN;;oFAAyB,IAAK,aAAoBA,IAAIc,OAAO,uBAA/B,6BAAA,SAAA,0BAAA;wFAAMD,aAAN;wFAAiCD,WAAWG,IAAI;4FAAEf,IAAIpC,OAAO;4FAAEiD;;;;oFAA/D;oFAAA;;;6FAAA,6BAAA;4FAAA;;;4FAAA;kGAAA;;;;;;4EAA9B;4EAAA;;;qFAAA,8BAAA;oFAAA;;;oFAAA;0FAAA;;;;wEACL;;4EAAMN,IAAAA,oBAAU,EAAChF,MAAM;gFAAiB;gFAAQ;+EAAW,kGAAkGqF;;;wEAA7J;;;;;;wDACF;;;;gDATA;qDAWIjE,CAAAA,SAAS6B,MAAM,GAAG,CAAA,GAAlB7B;;;;gDACF;;oDAAM9B,OAAOa,IAAI,CAAC,YAAY;+DAC5BH,KAAKkF,QAAQ,CACX,4CACA9D,SAAS3B,GAAG,CAAC,SAAC2E;mEAAM;gEAACA;6DAAE;;;;;gDAH3B;;;gDAO2B,kCAAA,2BAAA;qDAAzBlC,CAAAA,QAAQe,MAAM,GAAG,CAAA,GAAjBf;;;;;;;;;;;;;wDAA+BxC;;;;gEAAAA,UAAN;gEAA2B;;oEAAMJ,OAAOa,IAAI,CAACsF,IAAAA,sBAAY,EAAC/F,QAAQC,IAAI,EAAE,WAAW;4EAAMD;gFAAAA,kBAAAA,QAAQgG,MAAM,cAAdhG,sCAAAA,qBAAAA,SAAiBM,MAAMkC,SAASH;;;;gEAA9F;;;;;;;gDAA3B,YAAiBf;;;uDAAjB,6BAAA,QAAA;;;;;;;;;;;;gDAAA;;;;;;;;;;;;gDAAA;gDAAA;;;;;;;yDAAA,6BAAA;wDAAA;;;wDAAA;8DAAA;;;;;;;gDACxB,mCAAA,4BAAA;;;;;;;;;;wDAAMtB,SACHiG;;;;gEADGjG,UAAN;gEACGiG,iBAAiCpE,WAAW9B,GAAG,CAAC,SAACgF;2EAAS;wEAAEjC,MAAMiC,IAAIpC,OAAO;wEAAEuD,WAAWnB,IAAImB,SAAS,CAAClG,QAAQC,IAAI,CAAC;oEAAC;;gEAC5H;;oEAAML,OAAOa,IAAI,CAACsF,IAAAA,sBAAY,EAAC/F,QAAQC,IAAI,EAAE,UAAU;4EAAMD;gFAAAA,iBAAAA,QAAQmG,KAAK,cAAbnG,qCAAAA,oBAAAA,SAAgBM,MAAM2F,gBAAgB5D;;;;gEAAnG;;;;;;gDACF;gDAHK,aAAiBf;;;uDAAjB,8BAAA,SAAA;;;;;;;;;;;;gDAAA;;;;;;;;;;;;gDAAA;gDAAA;;;;;;;yDAAA,8BAAA;wDAAA;;;wDAAA;8DAAA;;;;;;;gDAIA,mCAAA,4BAAA;;;;;;;;;;wDAAMtB;;;;gEAAAA,UAAN;gEAA2B;;oEAAMJ,OAAOa,IAAI,CAACsF,IAAAA,sBAAY,EAAC/F,QAAQC,IAAI,EAAE,UAAU;4EAAMD;gFAAAA,0BAAAA,QAAQoG,cAAc,cAAtBpG,8CAAAA,6BAAAA,SAAyBM,MAAM+B;;;;gEAA5F;;;;;;;gDAA3B,aAAiBf;;;uDAAjB,8BAAA,SAAA;;;;;;;;;;;;gDAAA;;;;;;;;;;;;gDAAA;gDAAA;;;;;;;yDAAA,8BAAA;wDAAA;;;wDAAA;8DAAA;;;;;;;;;;;;gCACP;;4BACAqC,QAAQ,SAARA,OAAStD;uCAAST,OAAOgE,IAAI,CAAC1D,WAAWG,MAAME,OAAOH,aAAa;;4BAC7DyD,QAAN,SAAMA,OAAOvD,IAAI,EAAED,IAAI;;;;;gDACrBgG,IAAAA,4BAAgB,EAAChF,WAAWhB;qDACxBY,QAAQqF,cAAc,EAAtBrF;;;;gDAAwB;;oDAAMrB,OAAOa,IAAI,CAAC,QAAQ;4DAAMQ;gEAAAA,0BAAAA,QAAQqF,cAAc,cAAtBrF,8CAAAA,6BAAAA,SAAyBX,MAAMD;;;;gDAA/D;;;;;;;;gCAC9B;;wBACF;;;;IACF;;AAIO,SAAehB,UAAUiB,IAAgB,EAAEf,GAAW,EAAEyB,KAAqB,EAAEC,OAAyB,EAAEC,IAAgB,EAAEC,WAAiC;;YAC5JZ,QACAQ,UACAwF,MAEAC,SACFnG;;;;oBALEE,SAASrB,sBAAsBK;oBACpB;;wBAAMkH,IAAAA,8BAAe,EAACnG,MAAM;mCAAMlB,sBAAsBkB,MAAMC;;;;oBAAzEQ,WAAW;oBACJ;;wBAAM5B,iBAAiB4B,UAAUxB,KAAKyB,OAAOC,SAASV,QAAQW,MAAMC;;;oBAA3EoF,OAAO;oBACb,IAAI,CAACA,KAAK/C,OAAO,EAAE;;wBAAO;4BAAEC,QAAQ8C,KAAK9C,MAAM;4BAAE3B,UAAUyE,KAAKzE,QAAQ;4BAAElC,QAAQ2G,KAAK5C,MAAM,CAAC;wBAAG;;oBAC3F6C,UAAUE,KAAKC,GAAG;;;;;;;;;oBAGtB;;wBAAMF,IAAAA,8BAAe,EAACnG,MAAM;mCAAMiG,KAAK7C,KAAK,CAACpD;2BAAOW,QAAQ2F,SAAS;;;oBAArE;;;;;;oBAEAvG,OAAOqG,KAAKC,GAAG,KAAKH;oBACpBjG,OAAOF,IAAI,IAAIA;;;;;oBAEjB;;wBAAMkG,KAAK1C,MAAM,CAACvD,MAAMD;;;oBAAxB;oBACA;;wBAAO;4BAAEoD,QAAQ8C,KAAK9C,MAAM;4BAAE3B,UAAUyE,KAAKzE,QAAQ;4BAAElC,QAAQ2G,KAAK5C,MAAM,CAACpD,OAAOF,IAAI;wBAAE;;;;IAC1F"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/reconcile.ts"],"sourcesContent":["import type { Config } from '../config/index.ts';\nimport { activeFeatures } from '../features/index.ts';\nimport type { ExtractedDoc, ReconcileDelta } from '../features/types.ts';\nimport { progress } from '../output/progress.ts';\nimport { listFiles, RESERVED_COLUMNS } from '../scan/index.ts';\nimport type { ParsePool } from '../scan/pool.ts';\nimport { reparseFiles } from '../scan/reparse.ts';\nimport { recordLockWaitMs } from './lock-wait.ts';\nimport { appendRows, getColumns, quoteIdent } from './shared.ts';\nimport { featureStage, type StageRecorder, type Stages, stageRecorder } from './stages.ts';\nimport { withTransaction } from './transaction.ts';\nimport type { Connection, ReconcileDialect } from './types.ts';\n\n// One reconcile algorithm shared by every store, parameterised by a per-engine ReconcileDialect\n// (types.ts). Ordering is universal, not a dialect concern: ALTER, then the frontmatter upsert,\n// then reconcileContent, then preset_files, then the vanished-frontmatter delete, then feature hooks\n// -- a vanished path's content delete (inside reconcileContent) must precede its frontmatter\n// delete, since sqlite's delete SQL resolves the row via its frontmatter rowid.\n\n// Feature-owned columns (`_rank`) must stay out of the upsert: a reparse would null the last\n// computed value on every touch, not just the reconciles that recompute it.\nexport const CORE_FRONTMATTER_COLUMNS = new Set(['path', '_mtime', '_ctime', '_size', '_parse_error']);\n\nexport interface ReconcilePaths {\n rootDir: string;\n configDir: string;\n}\n\nexport interface ReconcileSnapshot {\n existingRows: Array<{ path: string; _mtime: number; _size: number }>;\n seenColumns: Set<string>;\n}\n\nexport interface ReconcilePlan {\n mutated: boolean;\n parsed: number;\n warnings: string[];\n apply(conn: Connection): Promise<void>;\n finish(txMs: number): Stages;\n record(conn: Connection, txMs: number): Promise<void>;\n}\n\nexport interface ReconcileTiming {\n stages: StageRecorder;\n elapsed(): number;\n workerParseMs: number;\n txMs: number;\n}\n\nexport function createReconcileTiming(cfg: Config): ReconcileTiming {\n const start = process.hrtime.bigint();\n return {\n stages: stageRecorder(activeFeatures(cfg).map((feature) => feature.name)),\n elapsed: () => Number(process.hrtime.bigint() - start) / 1e6,\n workerParseMs: 0,\n txMs: 0,\n };\n}\n\n// Called inside the builder's short planning snapshot, alongside its metadata baseline. Parsing\n// happens only after that transaction closes; publication later rejects this state if generation\n// or configuration moved in the meantime.\nexport async function readReconcileSnapshot(conn: Connection, timing: ReconcileTiming): Promise<ReconcileSnapshot> {\n const existingRows = await timing.stages.time('existing', async () => {\n const existingStmt = await conn.prepare('SELECT \"path\", \"_mtime\", \"_size\" FROM frontmatter');\n return (await existingStmt.all()) as ReconcileSnapshot['existingRows'];\n });\n return { existingRows, seenColumns: await getColumns(conn) };\n}\n\nexport async function prepareReconcile(snapshot: ReconcileSnapshot, cfg: Config, paths: ReconcilePaths, dialect: ReconcileDialect, timing: ReconcileTiming, pool?: ParsePool, forcedPaths?: ReadonlySet<string>): Promise<ReconcilePlan> {\n const { rootDir, configDir } = paths;\n const features = activeFeatures(cfg);\n const { stages, elapsed } = timing;\n const files = await stages.time('list', () => listFiles(cfg, rootDir));\n const currentSet = new Set(files.map((f) => f.relPath));\n const existingRows = snapshot.existingRows;\n const existing = new Map(existingRows.map((r) => [r.path, r]));\n // A path whose coverage moved between presets (forcedPaths) but is no longer covered at all is\n // already caught below by !currentSet.has, since it can only be forced by having existed under\n // an old preset's match, which means it was reconciled into `existing` already.\n const vanished = existingRows.filter((r) => !currentSet.has(r.path)).map((r) => r.path);\n\n // forcedPaths treats an unchanged file as touched because its preset coverage moved, not its\n // stamp -- reconcile still owns add/update/remove and every cross-feature cascade for it.\n const toReparse = files.filter((f) => {\n const row = existing.get(f.relPath);\n return !row || row._mtime !== f.mtimeMs || row._size !== f.size || (forcedPaths?.has(f.relPath) ?? false);\n });\n\n if (vanished.length === 0 && toReparse.length === 0) {\n return {\n mutated: false,\n parsed: 0,\n warnings: [],\n apply: async () => {},\n finish: (txMs) => stages.take(elapsed(), txMs, timing.workerParseMs),\n record: async () => {},\n };\n }\n\n const seenColumns = new Set(snapshot.seenColumns);\n\n // Bulk reparses (a sync, a cold build) are the long silences a query can hit; short\n // reconciles stay silent (progress() has a threshold).\n const report = progress('reparsing files', toReparse.length);\n // Pool wall time, dispatch to drain, so this stage shares a clock with every other one.\n const { docs: parsedDocs, warnings, newColumns, workerParseMs } = await stages.time('parse', () => reparseFiles(toReparse, features, cfg, seenColumns, report.tick, { pool }));\n timing.workerParseMs += workerParseMs;\n report.finish();\n for (const col of newColumns) seenColumns.add(col);\n\n const allColumns = [...seenColumns];\n // Fence before ALTERing: a store's own failure past this point is a raw, engine-specific\n // error with no indication of the boundary or the levers -- dialect.checkColumnLimit names both.\n dialect.checkColumnLimit(allColumns.length);\n // Columns the frontmatter upsert actually writes: core + parsed frontmatter keys, never a\n // feature-owned reserved column (see CORE_FRONTMATTER_COLUMNS above).\n const writableColumns = allColumns.filter((c) => CORE_FRONTMATTER_COLUMNS.has(c) || !RESERVED_COLUMNS.has(c));\n // ON CONFLICT DO UPDATE (not OR REPLACE) keeps the row's rowid stable across reparses --\n // sqlite's content rows are coupled to that rowid.\n const insertSql = `INSERT INTO frontmatter (${writableColumns.map(quoteIdent).join(', ')}) VALUES (${writableColumns.map(() => '?').join(', ')}) ON CONFLICT(\"path\") DO UPDATE SET ${writableColumns\n .filter((c) => c !== 'path')\n .map((c) => `${quoteIdent(c)} = excluded.${quoteIdent(c)}`)\n .join(', ')}`;\n\n const added = toReparse.filter((f) => !existing.has(f.relPath)).map((f) => f.relPath);\n const delta: ReconcileDelta = { files, reparsed: parsedDocs.map((d) => d.relPath), added, vanished };\n const addedSet = new Set(added);\n const reparsedExisting = parsedDocs.map((d) => d.relPath).filter((p) => !addedSet.has(p));\n // Paths whose content (and, per feature, other rows) need clearing: gone entirely, or about to\n // be reinserted fresh. Disjoint from `added`, which has nothing to clear.\n const touched = [...vanished, ...reparsedExisting];\n\n return {\n mutated: true,\n parsed: parsedDocs.length,\n warnings,\n async apply(conn) {\n // The generation fence already proved the planning snapshot current under this write lock.\n // Re-read columns only because schema setup is not itself a core generation publication.\n const present = await getColumns(conn);\n const missingColumns = newColumns.filter((col) => !present.has(col));\n if (missingColumns.length > 0) await stages.time('alter', () => dialect.addColumns(conn, missingColumns));\n\n if (parsedDocs.length > 0) {\n const toRow = (doc: (typeof parsedDocs)[number]) =>\n writableColumns.map((col) => {\n if (col === 'path') return doc.relPath;\n if (col === '_mtime') return doc.mtimeMs;\n if (col === '_ctime') return doc.ctimeMs;\n if (col === '_size') return doc.size;\n if (col === '_parse_error') return doc.parseError;\n return doc.data[col] ?? null;\n });\n await stages.time('fm-upsert', async () => {\n const newDocs = parsedDocs.filter((d) => addedSet.has(d.relPath));\n const updateDocs = parsedDocs.filter((d) => !addedSet.has(d.relPath));\n await appendRows(conn, 'frontmatter', writableColumns, insertSql, newDocs.map(toRow));\n if (updateDocs.length > 0) {\n const rows = updateDocs.map(toRow);\n if (dialect.updateFrontmatter) await dialect.updateFrontmatter(conn, writableColumns, rows);\n else await conn.runBatch(insertSql, rows);\n }\n });\n }\n\n await stages.time('text-index', () => dialect.reconcileContent(conn, touched, parsedDocs, delta, cfg));\n if (touched.length > 0)\n await conn.runBatch(\n 'DELETE FROM indexed_sources WHERE \"path\" = ?',\n touched.map((p) => [p])\n );\n await appendRows(\n conn,\n 'indexed_sources',\n ['path', 'text'],\n 'INSERT INTO indexed_sources (\"path\", text) VALUES (?, ?) ON CONFLICT(\"path\") DO UPDATE SET text = excluded.text',\n parsedDocs.map((doc) => [doc.relPath, doc.source])\n );\n\n await stages.time('presets', async () => {\n if (touched.length > 0)\n await conn.runBatch(\n 'DELETE FROM preset_files WHERE \"path\" = ?',\n touched.map((p) => [p])\n );\n const presetRows: unknown[][] = [];\n for (const doc of parsedDocs) for (const presetName of doc.presets) presetRows.push([doc.relPath, presetName]);\n await appendRows(conn, 'preset_files', ['path', 'preset'], 'INSERT INTO preset_files (\"path\", preset) VALUES (?, ?) ON CONFLICT(\"path\", preset) DO NOTHING', presetRows);\n });\n\n if (vanished.length > 0)\n await stages.time('vanished', () =>\n conn.runBatch(\n 'DELETE FROM frontmatter WHERE \"path\" = ?',\n vanished.map((p) => [p])\n )\n );\n\n if (touched.length > 0) for (const feature of features) await stages.time(featureStage(feature.name, 'remove'), () => feature.remove?.(conn, touched, delta));\n for (const feature of features) {\n const docsForFeature: ExtractedDoc[] = parsedDocs.map((doc) => ({ path: doc.relPath, extracted: doc.extracted[feature.name] }));\n await stages.time(featureStage(feature.name, 'store'), () => feature.store?.(conn, docsForFeature, delta));\n }\n for (const feature of features) await stages.time(featureStage(feature.name, 'after'), () => feature.afterReconcile?.(conn, delta));\n },\n finish: (txMs) => stages.take(elapsed(), txMs, timing.workerParseMs),\n async record(conn, txMs) {\n recordLockWaitMs(configDir, txMs);\n if (dialect.recordDuration) await stages.time('meta', () => dialect.recordDuration?.(conn, txMs));\n },\n };\n}\n\n// Lower-level entrypoint retained only for focused reconcile tests. It has no generation fence;\n// production publication must go through builder.ts, and any new caller must provide exclusivity.\nexport async function reconcile(conn: Connection, cfg: Config, paths: ReconcilePaths, dialect: ReconcileDialect, pool?: ParsePool, forcedPaths?: ReadonlySet<string>): Promise<{ parsed: number; warnings: string[]; stages: Stages }> {\n const timing = createReconcileTiming(cfg);\n const snapshot = await withTransaction(conn, () => readReconcileSnapshot(conn, timing));\n const plan = await prepareReconcile(snapshot, cfg, paths, dialect, timing, pool, forcedPaths);\n if (!plan.mutated) return { parsed: plan.parsed, warnings: plan.warnings, stages: plan.finish(0) };\n const txStart = Date.now();\n let txMs: number;\n try {\n await withTransaction(conn, () => plan.apply(conn), dialect.beginMode());\n } finally {\n txMs = Date.now() - txStart;\n timing.txMs += txMs;\n }\n await plan.record(conn, txMs);\n return { parsed: plan.parsed, warnings: plan.warnings, stages: plan.finish(timing.txMs) };\n}\n"],"names":["CORE_FRONTMATTER_COLUMNS","createReconcileTiming","prepareReconcile","readReconcileSnapshot","reconcile","Set","cfg","start","process","hrtime","bigint","stages","stageRecorder","activeFeatures","map","feature","name","elapsed","Number","workerParseMs","txMs","conn","timing","existingRows","time","existingStmt","prepare","all","getColumns","seenColumns","snapshot","paths","dialect","pool","forcedPaths","rootDir","configDir","features","files","currentSet","existing","vanished","toReparse","report","parsedDocs","warnings","newColumns","col","allColumns","writableColumns","insertSql","added","delta","addedSet","reparsedExisting","touched","listFiles","f","relPath","Map","r","path","filter","has","row","get","_mtime","mtimeMs","_size","size","length","mutated","parsed","apply","finish","take","record","progress","reparseFiles","tick","docs","add","checkColumnLimit","c","RESERVED_COLUMNS","quoteIdent","join","reparsed","d","p","present","missingColumns","toRow","addColumns","doc","ctimeMs","parseError","data","newDocs","updateDocs","rows","appendRows","updateFrontmatter","runBatch","reconcileContent","source","presetRows","presetName","presets","push","featureStage","remove","docsForFeature","extracted","store","afterReconcile","recordLockWaitMs","recordDuration","plan","txStart","withTransaction","Date","now","beginMode"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/shared.ts"],"sourcesContent":["import type { Connection } from './types.ts';\n\n// SQL and meta-table primitives both stores' open()/reconcile() need. Engine-neutral: both\n// stores' Connection satisfies the same async exec/prepare/runBatch shape (types.ts).\n\n// Rows that cannot conflict, at whatever speed this connection offers: the append path where the\n// store has one, else the caller's own guarded `conflictSql` statement bound the ordinary way.\nexport async function appendRows(conn: Connection, table: string, columns: string[], conflictSql: string, rows: unknown[][]): Promise<void> {\n if (rows.length === 0) return;\n if (conn.appendRows) await conn.appendRows(table, columns, rows);\n else await conn.runBatch(conflictSql, rows);\n}\n\nexport function quoteIdent(name: string): string {\n return `\"${name.split('\"').join('\"\"')}\"`;\n}\n\nexport async function getColumns(conn: Connection): Promise<Set<string>> {\n const stmt = await conn.prepare('PRAGMA table_info(frontmatter)');\n const rows = (await stmt.all()) as Array<{ name: string }>;\n return new Set(rows.map((r) => r.name));\n}\n\nexport async function getMeta(conn: Connection, key: string): Promise<string | null> {\n const stmt = await conn.prepare('SELECT value FROM meta WHERE key = ?');\n const row = (await stmt.get(key)) as { value: string } | undefined;\n return row ? row.value : null;\n}\n\nexport async function setMeta(conn: Connection, key: string, value: string | null): Promise<void> {\n if (value === null) {\n const stmt = await conn.prepare('DELETE FROM meta WHERE key = ?');\n await stmt.run(key);\n return;\n }\n const stmt = await conn.prepare('INSERT INTO meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value');\n await stmt.run(key, value);\n}\n\n// Reconcile's own write-transaction duration, for open()'s derived busy_timeout: keep the\n// observed max so a big watcher reconcile's lock hold is what the next open bounds its wait against.\nexport async function recordReconcileDuration(conn: Connection, ms: number): Promise<void> {\n const prevRaw = await getMeta(conn, 'reconcile_max_ms');\n // -1, not 0, so a genuinely 0ms first reconcile (sub-millisecond, common on a tiny tree)\n // still gets recorded instead of losing to the \"nothing recorded yet\" default.\n const prevMax = prevRaw === null ? -1 : Number(prevRaw);\n if (ms > prevMax) await setMeta(conn, 'reconcile_max_ms', String(ms));\n}\n"],"names":["appendRows","getColumns","getMeta","quoteIdent","recordReconcileDuration","setMeta","conn","table","columns","conflictSql","rows","length","runBatch","name","split","join","stmt","prepare","all","Set","map","r","key","row","get","value","run","ms","prevRaw","prevMax","Number","String"],"mappings":";;;;;;;;;;;QAOsBA;eAAAA;;QAUAC;eAAAA;;QAMAC;eAAAA;;QAVNC;eAAAA;;QA4BMC;eAAAA;;QAZAC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAtBf,SAAeL,WAAWM,IAAgB,EAAEC,KAAa,EAAEC,OAAiB,EAAEC,WAAmB,EAAEC,IAAiB;;;;;oBACzH,IAAIA,KAAKC,MAAM,KAAK,GAAG;;;yBACnBL,KAAKN,UAAU,EAAfM;;;;oBAAiB;;wBAAMA,KAAKN,UAAU,CAACO,OAAOC,SAASE;;;oBAAtC;;;;;;oBAChB;;wBAAMJ,KAAKM,QAAQ,CAACH,aAAaC;;;oBAAjC;;;;;;;;IACP;;AAEO,SAASP,WAAWU,IAAY;IACrC,OAAO,AAAC,IAA8B,OAA3BA,KAAKC,KAAK,CAAC,KAAKC,IAAI,CAAC,OAAM;AACxC;AAEO,SAAed,WAAWK,IAAgB;;YACzCU,MACAN;;;;oBADO;;wBAAMJ,KAAKW,OAAO,CAAC;;;oBAA1BD,OAAO;oBACC;;wBAAMA,KAAKE,GAAG;;;oBAAtBR,OAAQ;oBACd;;wBAAO,IAAIS,IAAIT,KAAKU,GAAG,CAAC,SAACC;mCAAMA,EAAER,IAAI;;;;;IACvC;;AAEO,SAAeX,QAAQI,IAAgB,EAAEgB,GAAW;;YACnDN,MACAO;;;;oBADO;;wBAAMjB,KAAKW,OAAO,CAAC;;;oBAA1BD,OAAO;oBACA;;wBAAMA,KAAKQ,GAAG,CAACF;;;oBAAtBC,MAAO;oBACb;;wBAAOA,MAAMA,IAAIE,KAAK,GAAG;;;;IAC3B;;AAEO,SAAepB,QAAQC,IAAgB,EAAEgB,GAAW,EAAEG,KAAoB;;YAEvET,MAIFA;;;;yBALFS,CAAAA,UAAU,IAAG,GAAbA;;;;oBACW;;wBAAMnB,KAAKW,OAAO,CAAC;;;oBAA1BD,OAAO;oBACb;;wBAAMA,KAAKU,GAAG,CAACJ;;;oBAAf;oBACA;;;;oBAEW;;wBAAMhB,KAAKW,OAAO,CAAC;;;oBAA1BD,QAAO;oBACb;;wBAAMA,MAAKU,GAAG,CAACJ,KAAKG;;;oBAApB;;;;;;IACF;;AAIO,SAAerB,wBAAwBE,IAAgB,EAAEqB,EAAU;;YAClEC,SAGAC;;;;oBAHU;;wBAAM3B,QAAQI,MAAM;;;oBAA9BsB,UAAU;oBAChB,yFAAyF;oBACzF,+EAA+E;oBACzEC,UAAUD,YAAY,OAAO,CAAC,IAAIE,OAAOF;yBAC3CD,CAAAA,KAAKE,OAAM,GAAXF;;;;oBAAc;;wBAAMtB,QAAQC,MAAM,oBAAoByB,OAAOJ;;;oBAA/C;;;;;;;;IACpB"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/shared.ts"],"sourcesContent":["import type { Connection } from './types.ts';\n\n// SQL and meta-table primitives both stores' open()/reconcile() need. Engine-neutral: both\n// stores' Connection satisfies the same async exec/prepare/runBatch shape (types.ts).\n\n// Rows that cannot conflict, at whatever speed this connection offers: the append path where the\n// store has one, else the caller's own guarded `conflictSql` statement bound the ordinary way.\nexport async function appendRows(conn: Connection, table: string, columns: string[], conflictSql: string, rows: unknown[][]): Promise<void> {\n if (rows.length === 0) return;\n if (conn.appendRows) await conn.appendRows(table, columns, rows);\n else await conn.runBatch(conflictSql, rows);\n}\n\nexport function quoteIdent(name: string): string {\n return `\"${name.split('\"').join('\"\"')}\"`;\n}\n\nexport async function getColumns(conn: Connection): Promise<Set<string>> {\n const stmt = await conn.prepare('PRAGMA table_info(frontmatter)');\n const rows = (await stmt.all()) as Array<{ name: string }>;\n return new Set(rows.map((r) => r.name));\n}\n\nexport async function getMeta(conn: Connection, key: string): Promise<string | null> {\n const stmt = await conn.prepare('SELECT value FROM meta WHERE key = ?');\n const row = (await stmt.get(key)) as { value: string } | undefined;\n return row ? row.value : null;\n}\n\nexport async function setMeta(conn: Connection, key: string, value: string | null): Promise<void> {\n if (value === null) {\n const stmt = await conn.prepare('DELETE FROM meta WHERE key = ?');\n await stmt.run(key);\n return;\n }\n const stmt = await conn.prepare('INSERT INTO meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value');\n await stmt.run(key, value);\n}\n\n// Reconcile's own write-transaction duration, for open()'s derived busy_timeout: keep the\n// observed max so a big watcher reconcile's lock hold is what the next open bounds its wait against.\nexport async function recordReconcileDuration(conn: Connection, ms: number): Promise<void> {\n const prevRaw = await getMeta(conn, 'reconcile_max_ms');\n // -1, not 0, so a genuinely 0ms first reconcile (sub-millisecond, common on a tiny tree)\n // still gets recorded instead of losing to the \"nothing recorded yet\" default.\n const prevMax = prevRaw === null ? -1 : Number(prevRaw);\n if (ms > prevMax) await setMeta(conn, 'reconcile_max_ms', String(ms));\n}\n"],"names":["appendRows","getColumns","getMeta","quoteIdent","recordReconcileDuration","setMeta","conn","table","columns","conflictSql","rows","length","runBatch","name","split","join","stmt","prepare","all","Set","map","r","key","row","get","value","run","ms","prevRaw","prevMax","Number","String"],"mappings":";;;;;;;;;;;QAOsBA;eAAAA;;QAUAC;eAAAA;;QAMAC;eAAAA;;QAVNC;eAAAA;;QA4BMC;eAAAA;;QAZAC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAtBf,SAAeL,WAAWM,IAAgB,EAAEC,KAAa,EAAEC,OAAiB,EAAEC,WAAmB,EAAEC,IAAiB;;;;;oBACzH,IAAIA,KAAKC,MAAM,KAAK,GAAG;;;yBACnBL,KAAKN,UAAU,EAAfM;;;;oBAAiB;;wBAAMA,KAAKN,UAAU,CAACO,OAAOC,SAASE;;;oBAAtC;;;;;;oBAChB;;wBAAMJ,KAAKM,QAAQ,CAACH,aAAaC;;;oBAAjC;;;;;;;;IACP;;AAEO,SAASP,WAAWU,IAAY;IACrC,OAAO,AAAC,IAA8B,OAA3BA,KAAKC,KAAK,CAAC,KAAKC,IAAI,CAAC,OAAM;AACxC;AAEO,SAAed,WAAWK,IAAgB;;YACzCU,MACAN;;;;oBADO;;wBAAMJ,KAAKW,OAAO,CAAC;;;oBAA1BD,OAAO;oBACC;;wBAAMA,KAAKE,GAAG;;;oBAAtBR,OAAQ;oBACd;;wBAAO,IAAIS,IAAIT,KAAKU,GAAG,CAAC,SAACC;mCAAMA,EAAER,IAAI;;;;;IACvC;;AAEO,SAAeX,QAAQI,IAAgB,EAAEgB,GAAW;;YACnDN,MACAO;;;;oBADO;;wBAAMjB,KAAKW,OAAO,CAAC;;;oBAA1BD,OAAO;oBACA;;wBAAMA,KAAKQ,GAAG,CAACF;;;oBAAtBC,MAAO;oBACb;;wBAAOA,MAAMA,IAAIE,KAAK,GAAG;;;;IAC3B;;AAEO,SAAepB,QAAQC,IAAgB,EAAEgB,GAAW,EAAEG,KAAoB;;YAEvET,MAIFA;;;;yBALFS,CAAAA,UAAU,IAAG,GAAbA;;;;oBACW;;wBAAMnB,KAAKW,OAAO,CAAC;;;oBAA1BD,OAAO;oBACb;;wBAAMA,KAAKU,GAAG,CAACJ;;;oBAAf;oBACA;;;;oBAEW;;wBAAMhB,KAAKW,OAAO,CAAC;;;oBAA1BD,QAAO;oBACb;;wBAAMA,MAAKU,GAAG,CAACJ,KAAKG;;;oBAApB;;;;;;IACF;;AAIO,SAAerB,wBAAwBE,IAAgB,EAAEqB,EAAU;;YAClEC,SAGAC;;;;oBAHU;;wBAAM3B,QAAQI,MAAM;;;oBAA9BsB,UAAU;oBAChB,yFAAyF;oBACzF,+EAA+E;oBACzEC,UAAUD,YAAY,OAAO,CAAC,IAAIE,OAAOF;yBAC3CD,CAAAA,KAAKE,OAAM,GAAXF;;;;oBAAc;;wBAAMtB,QAAQC,MAAM,oBAAoByB,OAAOJ;;;oBAA/C;;;;;;;;IACpB"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/signature.ts"],"sourcesContent":["// Feature-signature comparison for open()'s rebuild-vs-adopt decision (config.featureSignature's\n// format: one `feature:<name>:on|off` segment per feature, embed provider, then one segment per\n// preset). Pure string comparison, no SQL, shared by every store's open dialect.\n\n// Segment keys that moved between two feature signatures. `preset:` and `feature:` segments key\n// on their first two colon-separated parts (e.g. `preset:default`, `feature:tags`) so a change to\n// one preset or one feature is independently detectable; every other segment keys on its prefix alone.\nexport function changedSignatureKeys(before: string, after: string): Set<string> {\n const keyOf = (part: string) => (part.startsWith('preset:') || part.startsWith('feature:') ? part.split(':').slice(0, 2).join(':') : part.split(':')[0]);\n const parse = (sig: string) => new Map(sig.split('|').map((part) => [keyOf(part), part]));\n const a = parse(before);\n const b = parse(after);\n const changed = new Set<string>();\n for (const [key, val] of b) if (a.get(key) !== val) changed.add(key);\n for (const key of a.keys()) if (!b.has(key)) changed.add(key);\n return changed;\n}\n\n// Whether the embed segment only gained its resolved weight identity: same provider and\n// model, no identity recorded before, one now -- adopted into meta without a rebuild.\nexport function embedIdentityAdopted(before: string, after: string): boolean {\n const embedPart = (sig: string) => sig.split('|').find((p) => p.startsWith('embed:'));\n const b = embedPart(before);\n const a = embedPart(after);\n if (b === undefined || a === undefined) return false;\n const at = a.indexOf('@');\n return b.indexOf('@') === -1 && at !== -1 && a.slice(0, at) === b;\n}\n\n// Embedding work captured against an unresolved static-model signature may finish under the\n// same model after its weight identity is known. Every published read still requires exactness.\nexport function embeddingSignatureCompatible(expected: string | null, actual: string): boolean {\n if (expected === actual) return true;\n if (expected === null) return false;\n const changed = changedSignatureKeys(expected, actual);\n return changed.size === 1 && changed.has('embed') && embedIdentityAdopted(expected, actual);\n}\n\n// Names what moved, for the rebuild notice.\nexport function signatureDiff(before: string, after: string): string {\n const changed = changedSignatureKeys(before, after);\n const label = (key: string) => (key === 'embed' ? 'embed settings' : key.startsWith('preset:') ? `preset \"${key.slice(7)}\"` : key.startsWith('feature:') ? `feature \"${key.slice(8)}\"` : 'features');\n return changed.size === 0 ? 'features' : [...changed].map(label).join(', ');\n}\n"],"names":["changedSignatureKeys","embedIdentityAdopted","embeddingSignatureCompatible","signatureDiff","before","after","keyOf","part","startsWith","split","slice","join","parse","sig","Map","map","a","b","changed","Set","key","val","get","add","keys","has","embedPart","find","p","undefined","at","indexOf","expected","actual","size","label"],"mappings":"AAAA,iGAAiG;AACjG,gGAAgG;AAChG,iFAAiF;AAEjF,gGAAgG;AAChG,kGAAkG;AAClG,uGAAuG;;;;;;;;;;;;QACvFA;eAAAA;;QAaAC;eAAAA;;QAWAC;eAAAA;;QAQAC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAhCT,SAASH,qBAAqBI,MAAc,EAAEC,KAAa;IAChE,IAAMC,QAAQ,eAACC;eAAkBA,KAAKC,UAAU,CAAC,cAAcD,KAAKC,UAAU,CAAC,cAAcD,KAAKE,KAAK,CAAC,KAAKC,KAAK,CAAC,GAAG,GAAGC,IAAI,CAAC,OAAOJ,KAAKE,KAAK,CAAC,IAAI,CAAC,EAAE;;IACvJ,IAAMG,QAAQ,eAACC;eAAgB,IAAIC,IAAID,IAAIJ,KAAK,CAAC,KAAKM,GAAG,CAAC,SAACR;mBAAS;gBAACD,MAAMC;gBAAOA;aAAK;;;IACvF,IAAMS,IAAIJ,MAAMR;IAChB,IAAMa,IAAIL,MAAMP;IAChB,IAAMa,UAAU,IAAIC;QACf,kCAAA,2BAAA;;QAAL,QAAK,YAAoBF,sBAApB,SAAA,6BAAA,QAAA,yBAAA;YAAA,mCAAA,iBAAOG,sBAAKC;YAAW,IAAIL,EAAEM,GAAG,CAACF,SAASC,KAAKH,QAAQK,GAAG,CAACH;;;QAA3D;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;QACA,mCAAA,4BAAA;;QAAL,QAAK,aAAaJ,EAAEQ,IAAI,uBAAnB,UAAA,8BAAA,SAAA,0BAAA;YAAA,IAAMJ,OAAN;YAAuB,IAAI,CAACH,EAAEQ,GAAG,CAACL,OAAMF,QAAQK,GAAG,CAACH;;;QAApD;QAAA;;;iBAAA,8BAAA;gBAAA;;;gBAAA;sBAAA;;;;IACL,OAAOF;AACT;AAIO,SAASjB,qBAAqBG,MAAc,EAAEC,KAAa;IAChE,IAAMqB,YAAY,mBAACb;eAAgBA,IAAIJ,KAAK,CAAC,KAAKkB,IAAI,CAAC,SAACC;mBAAMA,EAAEpB,UAAU,CAAC;;;IAC3E,IAAMS,IAAIS,UAAUtB;IACpB,IAAMY,IAAIU,UAAUrB;IACpB,IAAIY,MAAMY,aAAab,MAAMa,WAAW,OAAO;IAC/C,IAAMC,KAAKd,EAAEe,OAAO,CAAC;IACrB,OAAOd,EAAEc,OAAO,CAAC,SAAS,CAAC,KAAKD,OAAO,CAAC,KAAKd,EAAEN,KAAK,CAAC,GAAGoB,QAAQb;AAClE;AAIO,SAASf,6BAA6B8B,QAAuB,EAAEC,MAAc;IAClF,IAAID,aAAaC,QAAQ,OAAO;IAChC,IAAID,aAAa,MAAM,OAAO;IAC9B,IAAMd,UAAUlB,qBAAqBgC,UAAUC;IAC/C,OAAOf,QAAQgB,IAAI,KAAK,KAAKhB,QAAQO,GAAG,CAAC,YAAYxB,qBAAqB+B,UAAUC;AACtF;AAGO,SAAS9B,cAAcC,MAAc,EAAEC,KAAa;IACzD,IAAMa,UAAUlB,qBAAqBI,QAAQC;IAC7C,IAAM8B,QAAQ,eAACf;eAAiBA,QAAQ,UAAU,mBAAmBA,IAAIZ,UAAU,CAAC,aAAa,AAAC,WAAuB,OAAbY,IAAIV,KAAK,CAAC,IAAG,OAAKU,IAAIZ,UAAU,CAAC,cAAc,AAAC,YAAwB,OAAbY,IAAIV,KAAK,CAAC,IAAG,OAAK;;IACzL,OAAOQ,QAAQgB,IAAI,KAAK,IAAI,aAAa,AAAC,qBAAGhB,SAASH,GAAG,CAACoB,OAAOxB,IAAI,CAAC;AACxE"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/signature.ts"],"sourcesContent":["// Feature-signature comparison for open()'s rebuild-vs-adopt decision (config.featureSignature's\n// format: one `feature:<name>:on|off` segment per feature, embed provider, then one segment per\n// preset). Pure string comparison, no SQL, shared by every store's open dialect.\n\n// Segment keys that moved between two feature signatures. `preset:` and `feature:` segments key\n// on their first two colon-separated parts (e.g. `preset:default`, `feature:tags`) so a change to\n// one preset or one feature is independently detectable; every other segment keys on its prefix alone.\nexport function changedSignatureKeys(before: string, after: string): Set<string> {\n const keyOf = (part: string) => (part.startsWith('preset:') || part.startsWith('feature:') ? part.split(':').slice(0, 2).join(':') : part.split(':')[0]);\n const parse = (sig: string) => new Map(sig.split('|').map((part) => [keyOf(part), part]));\n const a = parse(before);\n const b = parse(after);\n const changed = new Set<string>();\n for (const [key, val] of b) if (a.get(key) !== val) changed.add(key);\n for (const key of a.keys()) if (!b.has(key)) changed.add(key);\n return changed;\n}\n\n// Whether the embed segment only gained its resolved weight identity: same provider and\n// model, no identity recorded before, one now -- adopted into meta without a rebuild.\nexport function embedIdentityAdopted(before: string, after: string): boolean {\n const embedPart = (sig: string) => sig.split('|').find((p) => p.startsWith('embed:'));\n const b = embedPart(before);\n const a = embedPart(after);\n if (b === undefined || a === undefined) return false;\n const at = a.indexOf('@');\n return b.indexOf('@') === -1 && at !== -1 && a.slice(0, at) === b;\n}\n\n// Embedding work captured against an unresolved static-model signature may finish under the\n// same model after its weight identity is known. Every published read still requires exactness.\nexport function embeddingSignatureCompatible(expected: string | null, actual: string): boolean {\n if (expected === actual) return true;\n if (expected === null) return false;\n const changed = changedSignatureKeys(expected, actual);\n return changed.size === 1 && changed.has('embed') && embedIdentityAdopted(expected, actual);\n}\n\n// Names what moved, for the rebuild notice.\nexport function signatureDiff(before: string, after: string): string {\n const changed = changedSignatureKeys(before, after);\n const label = (key: string) => (key === 'embed' ? 'embed settings' : key.startsWith('preset:') ? `preset \"${key.slice(7)}\"` : key.startsWith('feature:') ? `feature \"${key.slice(8)}\"` : 'features');\n return changed.size === 0 ? 'features' : [...changed].map(label).join(', ');\n}\n"],"names":["changedSignatureKeys","embedIdentityAdopted","embeddingSignatureCompatible","signatureDiff","before","after","keyOf","part","startsWith","split","slice","join","parse","sig","Map","map","a","b","changed","Set","key","val","get","add","keys","has","embedPart","find","p","undefined","at","indexOf","expected","actual","size","label"],"mappings":"AAAA,iGAAiG;AACjG,gGAAgG;AAChG,iFAAiF;AAEjF,gGAAgG;AAChG,kGAAkG;AAClG,uGAAuG;;;;;;;;;;;;QACvFA;eAAAA;;QAaAC;eAAAA;;QAWAC;eAAAA;;QAQAC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAhCT,SAASH,qBAAqBI,MAAc,EAAEC,KAAa;IAChE,IAAMC,QAAQ,eAACC;eAAkBA,KAAKC,UAAU,CAAC,cAAcD,KAAKC,UAAU,CAAC,cAAcD,KAAKE,KAAK,CAAC,KAAKC,KAAK,CAAC,GAAG,GAAGC,IAAI,CAAC,OAAOJ,KAAKE,KAAK,CAAC,IAAI,CAAC,EAAE;;IACvJ,IAAMG,QAAQ,eAACC;eAAgB,IAAIC,IAAID,IAAIJ,KAAK,CAAC,KAAKM,GAAG,CAAC,SAACR;mBAAS;gBAACD,MAAMC;gBAAOA;aAAK;;;IACvF,IAAMS,IAAIJ,MAAMR;IAChB,IAAMa,IAAIL,MAAMP;IAChB,IAAMa,UAAU,IAAIC;QACf,kCAAA,2BAAA;;QAAL,QAAK,YAAoBF,sBAApB,SAAA,6BAAA,QAAA,yBAAA;YAAA,mCAAA,iBAAOG,sBAAKC;YAAW,IAAIL,EAAEM,GAAG,CAACF,SAASC,KAAKH,QAAQK,GAAG,CAACH;;;QAA3D;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;QACA,mCAAA,4BAAA;;QAAL,QAAK,aAAaJ,EAAEQ,IAAI,uBAAnB,UAAA,8BAAA,SAAA,0BAAA;YAAA,IAAMJ,OAAN;YAAuB,IAAI,CAACH,EAAEQ,GAAG,CAACL,OAAMF,QAAQK,GAAG,CAACH;;;QAApD;QAAA;;;iBAAA,8BAAA;gBAAA;;;gBAAA;sBAAA;;;;IACL,OAAOF;AACT;AAIO,SAASjB,qBAAqBG,MAAc,EAAEC,KAAa;IAChE,IAAMqB,YAAY,mBAACb;eAAgBA,IAAIJ,KAAK,CAAC,KAAKkB,IAAI,CAAC,SAACC;mBAAMA,EAAEpB,UAAU,CAAC;;;IAC3E,IAAMS,IAAIS,UAAUtB;IACpB,IAAMY,IAAIU,UAAUrB;IACpB,IAAIY,MAAMY,aAAab,MAAMa,WAAW,OAAO;IAC/C,IAAMC,KAAKd,EAAEe,OAAO,CAAC;IACrB,OAAOd,EAAEc,OAAO,CAAC,SAAS,CAAC,KAAKD,OAAO,CAAC,KAAKd,EAAEN,KAAK,CAAC,GAAGoB,QAAQb;AAClE;AAIO,SAASf,6BAA6B8B,QAAuB,EAAEC,MAAc;IAClF,IAAID,aAAaC,QAAQ,OAAO;IAChC,IAAID,aAAa,MAAM,OAAO;IAC9B,IAAMd,UAAUlB,qBAAqBgC,UAAUC;IAC/C,OAAOf,QAAQgB,IAAI,KAAK,KAAKhB,QAAQO,GAAG,CAAC,YAAYxB,qBAAqB+B,UAAUC;AACtF;AAGO,SAAS9B,cAAcC,MAAc,EAAEC,KAAa;IACzD,IAAMa,UAAUlB,qBAAqBI,QAAQC;IAC7C,IAAM8B,QAAQ,eAACf;eAAiBA,QAAQ,UAAU,mBAAmBA,IAAIZ,UAAU,CAAC,aAAa,AAAC,WAAuB,OAAbY,IAAIV,KAAK,CAAC,IAAG,OAAKU,IAAIZ,UAAU,CAAC,cAAc,AAAC,YAAwB,OAAbY,IAAIV,KAAK,CAAC,IAAG,OAAK;;IACzL,OAAOQ,QAAQgB,IAAI,KAAK,IAAI,aAAa,AAAC,qBAAGhB,SAASH,GAAG,CAACoB,OAAOxB,IAAI,CAAC;AACxE"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sql-functions.ts"],"sourcesContent":["import posix from 'node:path/posix';\n\n// has(field, value) / basename(path, suffix): the two sense-supplied SQL functions with no\n// engine-specific pieces, registered identically by each store instead of a hand-copied one.\n\n// JSON-array field -> membership, string field -> substring, NULL -> false.\nexport function hasImpl(field: unknown, value: unknown): number {\n if (field === null || field === undefined) return 0;\n const needle = String(value);\n if (typeof field === 'string') {\n if (field.startsWith('[')) {\n try {\n const parsed = JSON.parse(field);\n if (Array.isArray(parsed)) return parsed.some((item) => String(item) === needle) ? 1 : 0;\n } catch {}\n }\n return field.includes(needle) ? 1 : 0;\n }\n return String(field).includes(needle) ? 1 : 0;\n}\n\n// Unix basename(path, suffix?): the filename, minus suffix when it ends with one. Neither engine\n// has a filename function of its own, and LIKE tricks that fake one also match folder names.\nexport function basenameImpl(path: unknown, suffix?: unknown): string | null {\n if (path === null || path === undefined) return null;\n const name = posix.basename(String(path));\n const tail = suffix === null || suffix === undefined ? '' : String(suffix);\n // POSIX: a suffix identical to the whole name is not removed (node's own basename strips it).\n return tail !== '' && tail !== name && name.endsWith(tail) ? name.slice(0, -tail.length) : name;\n}\n"],"names":["basenameImpl","hasImpl","field","value","undefined","needle","String","startsWith","parsed","JSON","parse","Array","isArray","some","item","includes","path","suffix","name","posix","basename","tail","endsWith","slice","length"],"mappings":";;;;;;;;;;;QAuBgBA;eAAAA;;QAjBAC;eAAAA;;;4DANE;;;;;;AAMX,SAASA,QAAQC,KAAc,EAAEC,KAAc;IACpD,IAAID,UAAU,QAAQA,UAAUE,WAAW,OAAO;IAClD,IAAMC,SAASC,OAAOH;IACtB,IAAI,OAAOD,UAAU,UAAU;QAC7B,IAAIA,MAAMK,UAAU,CAAC,MAAM;YACzB,IAAI;gBACF,IAAMC,SAASC,KAAKC,KAAK,CAACR;gBAC1B,IAAIS,MAAMC,OAAO,CAACJ,SAAS,OAAOA,OAAOK,IAAI,CAAC,SAACC;2BAASR,OAAOQ,UAAUT;qBAAU,IAAI;YACzF,EAAE,eAAM,CAAC;QACX;QACA,OAAOH,MAAMa,QAAQ,CAACV,UAAU,IAAI;IACtC;IACA,OAAOC,OAAOJ,OAAOa,QAAQ,CAACV,UAAU,IAAI;AAC9C;AAIO,SAASL,aAAagB,IAAa,EAAEC,MAAgB;IAC1D,IAAID,SAAS,QAAQA,SAASZ,WAAW,OAAO;IAChD,IAAMc,OAAOC,cAAK,CAACC,QAAQ,CAACd,OAAOU;IACnC,IAAMK,OAAOJ,WAAW,QAAQA,WAAWb,YAAY,KAAKE,OAAOW;IACnE,8FAA8F;IAC9F,OAAOI,SAAS,MAAMA,SAASH,QAAQA,KAAKI,QAAQ,CAACD,QAAQH,KAAKK,KAAK,CAAC,GAAG,CAACF,KAAKG,MAAM,IAAIN;AAC7F"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/sql-functions.ts"],"sourcesContent":["import posix from 'node:path/posix';\n\n// has(field, value) / basename(path, suffix): the two sense-supplied SQL functions with no\n// engine-specific pieces, registered identically by each store instead of a hand-copied one.\n\n// JSON-array field -> membership, string field -> substring, NULL -> false.\nexport function hasImpl(field: unknown, value: unknown): number {\n if (field === null || field === undefined) return 0;\n const needle = String(value);\n if (typeof field === 'string') {\n if (field.startsWith('[')) {\n try {\n const parsed = JSON.parse(field);\n if (Array.isArray(parsed)) return parsed.some((item) => String(item) === needle) ? 1 : 0;\n } catch {}\n }\n return field.includes(needle) ? 1 : 0;\n }\n return String(field).includes(needle) ? 1 : 0;\n}\n\n// Unix basename(path, suffix?): the filename, minus suffix when it ends with one. Neither engine\n// has a filename function of its own, and LIKE tricks that fake one also match folder names.\nexport function basenameImpl(path: unknown, suffix?: unknown): string | null {\n if (path === null || path === undefined) return null;\n const name = posix.basename(String(path));\n const tail = suffix === null || suffix === undefined ? '' : String(suffix);\n // POSIX: a suffix identical to the whole name is not removed (node's own basename strips it).\n return tail !== '' && tail !== name && name.endsWith(tail) ? name.slice(0, -tail.length) : name;\n}\n"],"names":["basenameImpl","hasImpl","field","value","undefined","needle","String","startsWith","parsed","JSON","parse","Array","isArray","some","item","includes","path","suffix","name","posix","basename","tail","endsWith","slice","length"],"mappings":";;;;;;;;;;;QAuBgBA;eAAAA;;QAjBAC;eAAAA;;;4DANE;;;;;;AAMX,SAASA,QAAQC,KAAc,EAAEC,KAAc;IACpD,IAAID,UAAU,QAAQA,UAAUE,WAAW,OAAO;IAClD,IAAMC,SAASC,OAAOH;IACtB,IAAI,OAAOD,UAAU,UAAU;QAC7B,IAAIA,MAAMK,UAAU,CAAC,MAAM;YACzB,IAAI;gBACF,IAAMC,SAASC,KAAKC,KAAK,CAACR;gBAC1B,IAAIS,MAAMC,OAAO,CAACJ,SAAS,OAAOA,OAAOK,IAAI,CAAC,SAACC;2BAASR,OAAOQ,UAAUT;qBAAU,IAAI;YACzF,EAAE,eAAM,CAAC;QACX;QACA,OAAOH,MAAMa,QAAQ,CAACV,UAAU,IAAI;IACtC;IACA,OAAOC,OAAOJ,OAAOa,QAAQ,CAACV,UAAU,IAAI;AAC9C;AAIO,SAASL,aAAagB,IAAa,EAAEC,MAAgB;IAC1D,IAAID,SAAS,QAAQA,SAASZ,WAAW,OAAO;IAChD,IAAMc,OAAOC,cAAK,CAACC,QAAQ,CAACd,OAAOU;IACnC,IAAMK,OAAOJ,WAAW,QAAQA,WAAWb,YAAY,KAAKE,OAAOW;IACnE,8FAA8F;IAC9F,OAAOI,SAAS,MAAMA,SAASH,QAAQA,KAAKI,QAAQ,CAACD,QAAQH,KAAKK,KAAK,CAAC,GAAG,CAACF,KAAKG,MAAM,IAAIN;AAC7F"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/connection.ts"],"sourcesContent":["import type { DatabaseSync, StatementSync } from 'node:sqlite';\nimport { BEGIN_WRITE, withTransaction } from '../transaction.ts';\nimport type { Connection, RunResult, Statement } from '../types.ts';\n\n// Wraps node:sqlite's synchronous DatabaseSync in the async Connection/Statement shape every store presents. Every method does its real\n// work synchronously and returns an already-resolved promise, so reconcile's loop, the feature hooks, and runBatch never cross an async boundary internally.\nclass SqliteStatement implements Statement {\n private stmt: StatementSync;\n\n constructor(stmt: StatementSync) {\n this.stmt = stmt;\n }\n\n async run(...params: unknown[]): Promise<RunResult> {\n return this.stmt.run(...(params as Parameters<StatementSync['run']>));\n }\n\n async get(...params: unknown[]): Promise<unknown> {\n return this.stmt.get(...(params as Parameters<StatementSync['get']>));\n }\n\n async all(...params: unknown[]): Promise<unknown[]> {\n return this.stmt.all(...(params as Parameters<StatementSync['all']>));\n }\n\n async *iterate(...params: unknown[]): AsyncIterable<unknown> {\n yield* this.stmt.iterate(...(params as Parameters<StatementSync['iterate']>));\n }\n\n columns(): Array<{ name: string }> {\n return this.stmt.columns();\n }\n\n setReadBigInts(enabled: boolean): void {\n this.stmt.setReadBigInts(enabled);\n }\n}\n\nexport function createConnection(db: DatabaseSync): Connection {\n const conn: Connection = {\n async exec(sql: string): Promise<void> {\n db.exec(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n return new SqliteStatement(db.prepare(sql));\n },\n // Prepares once and loops synchronously, wrapped as one async call so features share one\n // Connection contract with DuckDB. Joins the caller's transaction when there is one (reconcile); otherwise opens its own, so a standalone batch stays atomic and commits once, not per row.\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n if (paramRows.length === 0) return;\n await withTransaction(\n conn,\n async () => {\n const stmt = db.prepare(sql);\n for (const row of paramRows) stmt.run(...(row as Parameters<StatementSync['run']>));\n },\n BEGIN_WRITE\n );\n },\n };\n return conn;\n}\n"],"names":["createConnection","SqliteStatement","stmt","run","params","get","all","iterate","columns","setReadBigInts","enabled","db","conn","exec","sql","prepare","runBatch","paramRows","length","withTransaction","row","BEGIN_WRITE"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/sqlite/connection.ts"],"sourcesContent":["import type { DatabaseSync, StatementSync } from 'node:sqlite';\nimport { BEGIN_WRITE, withTransaction } from '../transaction.ts';\nimport type { Connection, RunResult, Statement } from '../types.ts';\n\n// Wraps node:sqlite's synchronous DatabaseSync in the async Connection/Statement shape every store presents. Every method does its real\n// work synchronously and returns an already-resolved promise, so reconcile's loop, the feature hooks, and runBatch never cross an async boundary internally.\nclass SqliteStatement implements Statement {\n private stmt: StatementSync;\n\n constructor(stmt: StatementSync) {\n this.stmt = stmt;\n }\n\n async run(...params: unknown[]): Promise<RunResult> {\n return this.stmt.run(...(params as Parameters<StatementSync['run']>));\n }\n\n async get(...params: unknown[]): Promise<unknown> {\n return this.stmt.get(...(params as Parameters<StatementSync['get']>));\n }\n\n async all(...params: unknown[]): Promise<unknown[]> {\n return this.stmt.all(...(params as Parameters<StatementSync['all']>));\n }\n\n async *iterate(...params: unknown[]): AsyncIterable<unknown> {\n yield* this.stmt.iterate(...(params as Parameters<StatementSync['iterate']>));\n }\n\n columns(): Array<{ name: string }> {\n return this.stmt.columns();\n }\n\n setReadBigInts(enabled: boolean): void {\n this.stmt.setReadBigInts(enabled);\n }\n}\n\nexport function createConnection(db: DatabaseSync): Connection {\n const conn: Connection = {\n async exec(sql: string): Promise<void> {\n db.exec(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n return new SqliteStatement(db.prepare(sql));\n },\n // Prepares once and loops synchronously, wrapped as one async call so features share one\n // Connection contract with DuckDB. Joins the caller's transaction when there is one (reconcile); otherwise opens its own, so a standalone batch stays atomic and commits once, not per row.\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n if (paramRows.length === 0) return;\n await withTransaction(\n conn,\n async () => {\n const stmt = db.prepare(sql);\n for (const row of paramRows) stmt.run(...(row as Parameters<StatementSync['run']>));\n },\n BEGIN_WRITE\n );\n },\n };\n return conn;\n}\n"],"names":["createConnection","SqliteStatement","stmt","run","params","get","all","iterate","columns","setReadBigInts","enabled","db","conn","exec","sql","prepare","runBatch","paramRows","length","withTransaction","row","BEGIN_WRITE"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/fieldStats.ts"],"sourcesContent":["import { quoteIdent } from '../shared.ts';\nimport type { Connection, FieldStat } from '../types.ts';\n\n// One aggregate query per column (COUNT + GROUP_CONCAT(DISTINCT typeof())), O(columns) not O(rows x columns);\n// typeof()'s output is already the shared vocabulary, and GROUP_CONCAT's order is unsorted, so JS sorts the type set.\nexport async function fieldStats(conn: Connection, columns: string[], scopeWhere: string): Promise<FieldStat[]> {\n const exprs = columns.map((name, i) => {\n const quoted = quoteIdent(name);\n return `COUNT(${quoted}) AS n${i}, GROUP_CONCAT(DISTINCT typeof(${quoted})) FILTER (WHERE ${quoted} IS NOT NULL) AS t${i}`;\n });\n const stmt = await conn.prepare(`SELECT ${exprs.join(', ')} FROM frontmatter ${scopeWhere}`);\n const row = (await stmt.get()) as Record<string, number | string | null>;\n return columns.map((name, i) => ({\n field: name,\n coverage: Number(row[`n${i}`] ?? 0),\n type: [...new Set(((row[`t${i}`] as string) ?? '').split(',').filter(Boolean))].sort().join(','),\n }));\n}\n"],"names":["fieldStats","conn","columns","scopeWhere","exprs","stmt","row","map","name","i","quoted","quoteIdent","prepare","join","get","field","coverage","Number","type","Set","split","filter","Boolean","sort"],"mappings":";;;;+BAKsBA;;;eAAAA;;;wBALK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKpB,SAAeA,WAAWC,IAAgB,EAAEC,OAAiB,EAAEC,UAAkB;;YAChFC,OAIAC,MACAC;;;;oBALAF,QAAQF,QAAQK,GAAG,CAAC,SAACC,MAAMC;wBAC/B,IAAMC,SAASC,IAAAA,oBAAU,EAACH;wBAC1B,OAAO,AAAC,SAAuBC,OAAfC,QAAO,UAA2CA,OAAnCD,GAAE,mCAA2DC,OAA1BA,QAAO,qBAA8CD,OAA3BC,QAAO,sBAAsB,OAAFD;oBACzH;oBACa;;wBAAMR,KAAKW,OAAO,CAAC,AAAC,UAA8CT,OAArCC,MAAMS,IAAI,CAAC,OAAM,sBAA+B,OAAXV;;;oBAAzEE,OAAO;oBACA;;wBAAMA,KAAKS,GAAG;;;oBAArBR,MAAO;oBACb;;wBAAOJ,QAAQK,GAAG,CAAC,SAACC,MAAMC;gCAEPH,OACGA;mCAHW;gCAC/BS,OAAOP;gCACPQ,UAAUC,QAAOX,QAAAA,GAAG,CAAC,AAAC,IAAK,OAAFG,GAAI,cAAZH,mBAAAA,QAAgB;gCACjCY,MAAM,AAAC,qBAAG,IAAIC,IAAI,EAAEb,SAAAA,GAAG,CAAC,AAAC,IAAK,OAAFG,GAAI,cAAZH,oBAAAA,SAA2B,IAAIc,KAAK,CAAC,KAAKC,MAAM,CAACC,WAAWC,IAAI,GAAGV,IAAI,CAAC;4BAC9F;;;;;IACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/sqlite/fieldStats.ts"],"sourcesContent":["import { quoteIdent } from '../shared.ts';\nimport type { Connection, FieldStat } from '../types.ts';\n\n// One aggregate query per column (COUNT + GROUP_CONCAT(DISTINCT typeof())), O(columns) not O(rows x columns);\n// typeof()'s output is already the shared vocabulary, and GROUP_CONCAT's order is unsorted, so JS sorts the type set.\nexport async function fieldStats(conn: Connection, columns: string[], scopeWhere: string): Promise<FieldStat[]> {\n const exprs = columns.map((name, i) => {\n const quoted = quoteIdent(name);\n return `COUNT(${quoted}) AS n${i}, GROUP_CONCAT(DISTINCT typeof(${quoted})) FILTER (WHERE ${quoted} IS NOT NULL) AS t${i}`;\n });\n const stmt = await conn.prepare(`SELECT ${exprs.join(', ')} FROM frontmatter ${scopeWhere}`);\n const row = (await stmt.get()) as Record<string, number | string | null>;\n return columns.map((name, i) => ({\n field: name,\n coverage: Number(row[`n${i}`] ?? 0),\n type: [...new Set(((row[`t${i}`] as string) ?? '').split(',').filter(Boolean))].sort().join(','),\n }));\n}\n"],"names":["fieldStats","conn","columns","scopeWhere","exprs","stmt","row","map","name","i","quoted","quoteIdent","prepare","join","get","field","coverage","Number","type","Set","split","filter","Boolean","sort"],"mappings":";;;;+BAKsBA;;;eAAAA;;;wBALK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKpB,SAAeA,WAAWC,IAAgB,EAAEC,OAAiB,EAAEC,UAAkB;;YAChFC,OAIAC,MACAC;;;;oBALAF,QAAQF,QAAQK,GAAG,CAAC,SAACC,MAAMC;wBAC/B,IAAMC,SAASC,IAAAA,oBAAU,EAACH;wBAC1B,OAAO,AAAC,SAAuBC,OAAfC,QAAO,UAA2CA,OAAnCD,GAAE,mCAA2DC,OAA1BA,QAAO,qBAA8CD,OAA3BC,QAAO,sBAAsB,OAAFD;oBACzH;oBACa;;wBAAMR,KAAKW,OAAO,CAAC,AAAC,UAA8CT,OAArCC,MAAMS,IAAI,CAAC,OAAM,sBAA+B,OAAXV;;;oBAAzEE,OAAO;oBACA;;wBAAMA,KAAKS,GAAG;;;oBAArBR,MAAO;oBACb;;wBAAOJ,QAAQK,GAAG,CAAC,SAACC,MAAMC;gCAEPH,OACGA;mCAHW;gCAC/BS,OAAOP;gCACPQ,UAAUC,QAAOX,QAAAA,GAAG,CAAC,AAAC,IAAK,OAAFG,GAAI,cAAZH,mBAAAA,QAAgB;gCACjCY,MAAM,AAAC,qBAAG,IAAIC,IAAI,EAAEb,SAAAA,GAAG,CAAC,AAAC,IAAK,OAAFG,GAAI,cAAZH,oBAAAA,SAA2B,IAAIc,KAAK,CAAC,KAAKC,MAAM,CAACC,WAAWC,IAAI,GAAGV,IAAI,CAAC;4BAC9F;;;;;IACF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/lexical.ts"],"sourcesContent":["import { segmentMatch } from '../../text/segment.ts';\nimport type { Connection, LexicalHit, LexicalQueryOptions } from '../types.ts';\n\nconst WEIGHTED_BM25 = 'bm25(content, 10.0, 5.0, 1.0, 0, 10.0, 5.0, 1.0)';\n\n// Ranked BM25 word-match query, scoped by the caller-built SQL fragments. An\n// unspaced-script run in `terms` becomes a quoted grapheme phrase against the `_seg` sidecars.\nexport async function queryLexical(conn: Connection, terms: string, opts: LexicalQueryOptions): Promise<LexicalHit[]> {\n const { whereJoin, whereCond, scopeCond, limit } = opts;\n const query = segmentMatch(terms);\n // A run of pure unspaced-script punctuation segments to nothing searchable: an empty MATCH\n // string is an FTS5 syntax error, not zero rows, so return zero rows directly rather than issuing it.\n if (query.trim() === '') return [];\n const sql = `SELECT content.path AS path FROM content ${whereJoin} WHERE content MATCH ? ${whereCond} ${scopeCond} ORDER BY ${WEIGHTED_BM25} LIMIT ${limit}`;\n const stmt = await conn.prepare(sql);\n return (await stmt.all(query)) as unknown as LexicalHit[];\n}\n"],"names":["queryLexical","WEIGHTED_BM25","conn","terms","opts","whereJoin","whereCond","scopeCond","limit","query","sql","stmt","segmentMatch","trim","prepare","all"],"mappings":";;;;+BAOsBA;;;eAAAA;;;yBAPO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG7B,IAAMC,gBAAgB;AAIf,SAAeD,aAAaE,IAAgB,EAAEC,KAAa,EAAEC,IAAyB;;YACnFC,WAAWC,WAAWC,WAAWC,OACnCC,OAIAC,KACAC;;;;oBANEN,YAA2CD,KAA3CC,WAAWC,YAAgCF,KAAhCE,WAAWC,YAAqBH,KAArBG,WAAWC,QAAUJ,KAAVI;oBACnCC,QAAQG,IAAAA,uBAAY,EAACT;oBAC3B,2FAA2F;oBAC3F,sGAAsG;oBACtG,IAAIM,MAAMI,IAAI,OAAO,IAAI;;;;oBACnBH,MAAM,AAAC,4CAA8EJ,OAAnCD,WAAU,2BAAsCE,OAAbD,WAAU,KAAyBL,OAAtBM,WAAU,cAAmCC,OAAvBP,eAAc,WAAe,OAANO;oBACxI;;wBAAMN,KAAKY,OAAO,CAACJ;;;oBAA1BC,OAAO;oBACL;;wBAAMA,KAAKI,GAAG,CAACN;;;oBAAvB;;wBAAQ;;;;IACV"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/sqlite/lexical.ts"],"sourcesContent":["import { segmentMatch } from '../../text/segment.ts';\nimport type { Connection, LexicalHit, LexicalQueryOptions } from '../types.ts';\n\nconst WEIGHTED_BM25 = 'bm25(content, 10.0, 5.0, 1.0, 0, 10.0, 5.0, 1.0)';\n\n// Ranked BM25 word-match query, scoped by the caller-built SQL fragments. An\n// unspaced-script run in `terms` becomes a quoted grapheme phrase against the `_seg` sidecars.\nexport async function queryLexical(conn: Connection, terms: string, opts: LexicalQueryOptions): Promise<LexicalHit[]> {\n const { whereJoin, whereCond, scopeCond, limit } = opts;\n const query = segmentMatch(terms);\n // A run of pure unspaced-script punctuation segments to nothing searchable: an empty MATCH\n // string is an FTS5 syntax error, not zero rows, so return zero rows directly rather than issuing it.\n if (query.trim() === '') return [];\n const sql = `SELECT content.path AS path FROM content ${whereJoin} WHERE content MATCH ? ${whereCond} ${scopeCond} ORDER BY ${WEIGHTED_BM25} LIMIT ${limit}`;\n const stmt = await conn.prepare(sql);\n return (await stmt.all(query)) as unknown as LexicalHit[];\n}\n"],"names":["queryLexical","WEIGHTED_BM25","conn","terms","opts","whereJoin","whereCond","scopeCond","limit","query","sql","stmt","segmentMatch","trim","prepare","all"],"mappings":";;;;+BAOsBA;;;eAAAA;;;yBAPO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG7B,IAAMC,gBAAgB;AAIf,SAAeD,aAAaE,IAAgB,EAAEC,KAAa,EAAEC,IAAyB;;YACnFC,WAAWC,WAAWC,WAAWC,OACnCC,OAIAC,KACAC;;;;oBANEN,YAA2CD,KAA3CC,WAAWC,YAAgCF,KAAhCE,WAAWC,YAAqBH,KAArBG,WAAWC,QAAUJ,KAAVI;oBACnCC,QAAQG,IAAAA,uBAAY,EAACT;oBAC3B,2FAA2F;oBAC3F,sGAAsG;oBACtG,IAAIM,MAAMI,IAAI,OAAO,IAAI;;;;oBACnBH,MAAM,AAAC,4CAA8EJ,OAAnCD,WAAU,2BAAsCE,OAAbD,WAAU,KAAyBL,OAAtBM,WAAU,cAAmCC,OAAvBP,eAAc,WAAe,OAANO;oBACxI;;wBAAMN,KAAKY,OAAO,CAACJ;;;oBAA1BC,OAAO;oBACL;;wBAAMA,KAAKI,GAAG,CAACN;;;oBAAvB;;wBAAQ;;;;IACV"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/open.ts"],"sourcesContent":["// The Node floor (>=22.20) is explained here and nowhere else: 22.20 is the first release with\n// both FTS5 and row-returning INSERT ... RETURNING. Raise it only for a load-bearing capability.\nimport { DatabaseSync } from 'node:sqlite';\nimport type { Config, ResolvedConfig } from '../../config/index.ts';\nimport { activeFeatures } from '../../features/index.ts';\nimport type { InternalOpenOptions, OpenResult } from '../open.ts';\nimport { openWithDialect } from '../open.ts';\nimport { getMeta, setMeta } from '../shared.ts';\nimport { BEGIN_WRITE, withTransaction } from '../transaction.ts';\nimport type { Connection, OpenDialect } from '../types.ts';\nimport { createConnection } from './connection.ts';\nimport { sqliteDialect } from './reconcile.ts';\nimport { registerFunctions } from './sql-functions.ts';\nimport { createStore } from './store.ts';\n\nexport const DB_FILENAME = 'cache.db';\n// Cache shape version, independent of the config's own `version`. Bumping it rebuilds\n// existing trees on first query.\nexport const SCHEMA_VERSION = '22';\n\nexport type { OpenResult };\n\n// unicode61 splits on spaces, so a language written without them indexes a whole run as one\n// token and word search finds nothing; the `_seg` sidecars (always populated) cover that case.\nconst TOKENIZE = 'porter unicode61';\n\ninterface SqliteHandle {\n db: DatabaseSync;\n}\n\n// The `_seg` sidecars are appended after path, never inserted: bm25() and snippet(content, 2)\n// are documented against the first three columns. Each holds its field's exploded unspaced runs.\nasync function createContentTable(conn: Connection): Promise<void> {\n await conn.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS content USING fts5(title, summary, text, path UNINDEXED, title_seg, summary_seg, text_seg, tokenize = '${TOKENIZE}')`);\n}\n\n// Content is a separate table (not a column on frontmatter) so `SELECT * FROM frontmatter`\n// can't dump file text into context. Feature schema is published later with its generation.\nasync function ensureCoreSchemaTables(conn: Connection): Promise<void> {\n await conn.exec(`CREATE TABLE IF NOT EXISTS frontmatter (\"path\" TEXT PRIMARY KEY, \"_mtime\" REAL, \"_ctime\" REAL, \"_size\" INTEGER, \"_parse_error\" TEXT)`);\n await createContentTable(conn);\n await conn.exec(`CREATE TABLE IF NOT EXISTS indexed_sources (\"path\" TEXT PRIMARY KEY, text TEXT NOT NULL)`);\n // Coverage, not ownership: a path can appear under several presets. path leads the PK so the\n // per-doc delete is an index hit -- keyed the other way, cold builds went quadratic.\n await conn.exec(`CREATE TABLE IF NOT EXISTS preset_files (\"path\" TEXT, preset TEXT, PRIMARY KEY (\"path\", preset))`);\n await conn.exec('CREATE INDEX IF NOT EXISTS preset_files_preset ON preset_files(preset)');\n if ((await getMeta(conn, 'schema_version')) === null) await setMeta(conn, 'schema_version', SCHEMA_VERSION);\n}\n\n// Two processes opening the same fresh tree both try to convert it, and the loser gets SQLITE_BUSY\n// with no busy handler behind it. Bounded because a lock held past this is a real problem, not a race.\nfunction setJournalWal(db: DatabaseSync): void {\n const deadline = Date.now() + 5000;\n for (;;) {\n try {\n db.exec('PRAGMA journal_mode = WAL');\n return;\n } catch (err) {\n if (Date.now() >= deadline || !/database is locked|busy/i.test((err as Error).message)) throw err;\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 20);\n }\n }\n}\n\nasync function connect(dbPath: string, _cfg: ResolvedConfig, options: { existingOnly: boolean; observational: boolean }): Promise<{ handle: SqliteHandle; conn: Connection }> {\n const db = new DatabaseSync(dbPath, options.existingOnly ? { readOnly: true } : {});\n try {\n // Before journal_mode, not after: converting a fresh database to WAL takes a brief exclusive\n // lock, and with no timeout set yet a second process opening the same tree fails in 1ms.\n db.exec('PRAGMA busy_timeout = 30000');\n // busy_timeout does not cover the WAL conversion itself: SQLite does not invoke the busy\n // handler for it, so a concurrent cold open needs its own bounded wait.\n if (!options.observational) setJournalWal(db);\n registerFunctions(db);\n const conn = createConnection(db);\n return { handle: { db }, conn };\n } catch (err) {\n // A throw here must release this handle, or on Windows the leaked WAL db is undeletable and\n // scratch cleanup fails with EPERM/EBUSY.\n db.close();\n throw err;\n }\n}\n\nasync function close(handle: SqliteHandle): Promise<void> {\n handle.db.close();\n}\n\nasync function ensureCoreSchema(_handle: SqliteHandle, conn: Connection): Promise<void> {\n // One writer at a time: two cold opens can bootstrap the same database concurrently.\n await withTransaction(conn, () => ensureCoreSchemaTables(conn), BEGIN_WRITE);\n}\n\nasync function ensureFeatureSchema(_handle: SqliteHandle, conn: Connection, cfg: Config): Promise<void> {\n for (const feature of activeFeatures(cfg)) await feature.schema(conn);\n}\n\nasync function setDerivedBusyTimeout(handle: SqliteHandle, _conn: Connection, ms: number): Promise<void> {\n handle.db.exec(`PRAGMA busy_timeout = ${ms}`);\n}\n\n// This store's dialect (types.ts's OpenDialect) for the shared orchestration in store/open.ts.\nexport const sqliteOpenDialect: OpenDialect<SqliteHandle> = {\n filename: DB_FILENAME,\n schemaVersion: SCHEMA_VERSION,\n reconcileDialect: sqliteDialect,\n connect,\n close,\n ensureCoreSchema,\n ensureFeatureSchema,\n setDerivedBusyTimeout,\n createStore: (handle, conn) => createStore(handle.db, conn),\n};\n\nexport async function openSqlite(cfg: ResolvedConfig, options?: InternalOpenOptions): Promise<OpenResult> {\n return openWithDialect(cfg, sqliteOpenDialect, options);\n}\n"],"names":["DB_FILENAME","SCHEMA_VERSION","openSqlite","sqliteOpenDialect","TOKENIZE","createContentTable","conn","exec","ensureCoreSchemaTables","getMeta","setMeta","setJournalWal","db","deadline","Date","now","err","test","message","Atomics","wait","Int32Array","SharedArrayBuffer","connect","dbPath","_cfg","options","DatabaseSync","existingOnly","readOnly","observational","registerFunctions","createConnection","handle","close","ensureCoreSchema","_handle","withTransaction","BEGIN_WRITE","ensureFeatureSchema","cfg","feature","activeFeatures","schema","setDerivedBusyTimeout","_conn","ms","filename","schemaVersion","reconcileDialect","sqliteDialect","createStore","openWithDialect"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/sqlite/open.ts"],"sourcesContent":["// The Node floor (>=22.20) is explained here and nowhere else: 22.20 is the first release with\n// both FTS5 and row-returning INSERT ... RETURNING. Raise it only for a load-bearing capability.\nimport { DatabaseSync } from 'node:sqlite';\nimport type { Config, ResolvedConfig } from '../../config/index.ts';\nimport { activeFeatures } from '../../features/index.ts';\nimport type { InternalOpenOptions, OpenResult } from '../open.ts';\nimport { openWithDialect } from '../open.ts';\nimport { getMeta, setMeta } from '../shared.ts';\nimport { BEGIN_WRITE, withTransaction } from '../transaction.ts';\nimport type { Connection, OpenDialect } from '../types.ts';\nimport { createConnection } from './connection.ts';\nimport { sqliteDialect } from './reconcile.ts';\nimport { registerFunctions } from './sql-functions.ts';\nimport { createStore } from './store.ts';\n\nexport const DB_FILENAME = 'cache.db';\n// Cache shape version, independent of the config's own `version`. Bumping it rebuilds\n// existing trees on first query.\nexport const SCHEMA_VERSION = '22';\n\nexport type { OpenResult };\n\n// unicode61 splits on spaces, so a language written without them indexes a whole run as one\n// token and word search finds nothing; the `_seg` sidecars (always populated) cover that case.\nconst TOKENIZE = 'porter unicode61';\n\ninterface SqliteHandle {\n db: DatabaseSync;\n}\n\n// The `_seg` sidecars are appended after path, never inserted: bm25() and snippet(content, 2)\n// are documented against the first three columns. Each holds its field's exploded unspaced runs.\nasync function createContentTable(conn: Connection): Promise<void> {\n await conn.exec(`CREATE VIRTUAL TABLE IF NOT EXISTS content USING fts5(title, summary, text, path UNINDEXED, title_seg, summary_seg, text_seg, tokenize = '${TOKENIZE}')`);\n}\n\n// Content is a separate table (not a column on frontmatter) so `SELECT * FROM frontmatter`\n// can't dump file text into context. Feature schema is published later with its generation.\nasync function ensureCoreSchemaTables(conn: Connection): Promise<void> {\n await conn.exec(`CREATE TABLE IF NOT EXISTS frontmatter (\"path\" TEXT PRIMARY KEY, \"_mtime\" REAL, \"_ctime\" REAL, \"_size\" INTEGER, \"_parse_error\" TEXT)`);\n await createContentTable(conn);\n await conn.exec(`CREATE TABLE IF NOT EXISTS indexed_sources (\"path\" TEXT PRIMARY KEY, text TEXT NOT NULL)`);\n // Coverage, not ownership: a path can appear under several presets. path leads the PK so the\n // per-doc delete is an index hit -- keyed the other way, cold builds went quadratic.\n await conn.exec(`CREATE TABLE IF NOT EXISTS preset_files (\"path\" TEXT, preset TEXT, PRIMARY KEY (\"path\", preset))`);\n await conn.exec('CREATE INDEX IF NOT EXISTS preset_files_preset ON preset_files(preset)');\n if ((await getMeta(conn, 'schema_version')) === null) await setMeta(conn, 'schema_version', SCHEMA_VERSION);\n}\n\n// Two processes opening the same fresh tree both try to convert it, and the loser gets SQLITE_BUSY\n// with no busy handler behind it. Bounded because a lock held past this is a real problem, not a race.\nfunction setJournalWal(db: DatabaseSync): void {\n const deadline = Date.now() + 5000;\n for (;;) {\n try {\n db.exec('PRAGMA journal_mode = WAL');\n return;\n } catch (err) {\n if (Date.now() >= deadline || !/database is locked|busy/i.test((err as Error).message)) throw err;\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 20);\n }\n }\n}\n\nasync function connect(dbPath: string, _cfg: ResolvedConfig, options: { existingOnly: boolean; observational: boolean }): Promise<{ handle: SqliteHandle; conn: Connection }> {\n const db = new DatabaseSync(dbPath, options.existingOnly ? { readOnly: true } : {});\n try {\n // Before journal_mode, not after: converting a fresh database to WAL takes a brief exclusive\n // lock, and with no timeout set yet a second process opening the same tree fails in 1ms.\n db.exec('PRAGMA busy_timeout = 30000');\n // busy_timeout does not cover the WAL conversion itself: SQLite does not invoke the busy\n // handler for it, so a concurrent cold open needs its own bounded wait.\n if (!options.observational) setJournalWal(db);\n registerFunctions(db);\n const conn = createConnection(db);\n return { handle: { db }, conn };\n } catch (err) {\n // A throw here must release this handle, or on Windows the leaked WAL db is undeletable and\n // scratch cleanup fails with EPERM/EBUSY.\n db.close();\n throw err;\n }\n}\n\nasync function close(handle: SqliteHandle): Promise<void> {\n handle.db.close();\n}\n\nasync function ensureCoreSchema(_handle: SqliteHandle, conn: Connection): Promise<void> {\n // One writer at a time: two cold opens can bootstrap the same database concurrently.\n await withTransaction(conn, () => ensureCoreSchemaTables(conn), BEGIN_WRITE);\n}\n\nasync function ensureFeatureSchema(_handle: SqliteHandle, conn: Connection, cfg: Config): Promise<void> {\n for (const feature of activeFeatures(cfg)) await feature.schema(conn);\n}\n\nasync function setDerivedBusyTimeout(handle: SqliteHandle, _conn: Connection, ms: number): Promise<void> {\n handle.db.exec(`PRAGMA busy_timeout = ${ms}`);\n}\n\n// This store's dialect (types.ts's OpenDialect) for the shared orchestration in store/open.ts.\nexport const sqliteOpenDialect: OpenDialect<SqliteHandle> = {\n filename: DB_FILENAME,\n schemaVersion: SCHEMA_VERSION,\n reconcileDialect: sqliteDialect,\n connect,\n close,\n ensureCoreSchema,\n ensureFeatureSchema,\n setDerivedBusyTimeout,\n createStore: (handle, conn) => createStore(handle.db, conn),\n};\n\nexport async function openSqlite(cfg: ResolvedConfig, options?: InternalOpenOptions): Promise<OpenResult> {\n return openWithDialect(cfg, sqliteOpenDialect, options);\n}\n"],"names":["DB_FILENAME","SCHEMA_VERSION","openSqlite","sqliteOpenDialect","TOKENIZE","createContentTable","conn","exec","ensureCoreSchemaTables","getMeta","setMeta","setJournalWal","db","deadline","Date","now","err","test","message","Atomics","wait","Int32Array","SharedArrayBuffer","connect","dbPath","_cfg","options","DatabaseSync","existingOnly","readOnly","observational","registerFunctions","createConnection","handle","close","ensureCoreSchema","_handle","withTransaction","BEGIN_WRITE","ensureFeatureSchema","cfg","feature","activeFeatures","schema","setDerivedBusyTimeout","_conn","ms","filename","schemaVersion","reconcileDialect","sqliteDialect","createStore","openWithDialect"],"mappings":"AAAA,+FAA+F;AAC/F,iGAAiG;;;;;;;;;;;;QAcpFA;eAAAA;;QAGAC;eAAAA;;QAgGSC;eAAAA;;QAZTC;eAAAA;;;0BApGgB;uBAEE;sBAEC;wBACC;6BACY;4BAEZ;2BACH;8BACI;uBACN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAErB,IAAMH,cAAc;AAGpB,IAAMC,iBAAiB;AAI9B,4FAA4F;AAC5F,+FAA+F;AAC/F,IAAMG,WAAW;AAMjB,8FAA8F;AAC9F,iGAAiG;AACjG,SAAeC,mBAAmBC,IAAgB;;;;;oBAChD;;wBAAMA,KAAKC,IAAI,CAAC,AAAC,6IAAqJ,OAATH,UAAS;;;oBAAtK;;;;;;IACF;;AAEA,2FAA2F;AAC3F,4FAA4F;AAC5F,SAAeI,uBAAuBF,IAAgB;;;;;oBACpD;;wBAAMA,KAAKC,IAAI,CAAC;;;oBAAhB;oBACA;;wBAAMF,mBAAmBC;;;oBAAzB;oBACA;;wBAAMA,KAAKC,IAAI,CAAC;;;oBAAhB;oBACA,6FAA6F;oBAC7F,qFAAqF;oBACrF;;wBAAMD,KAAKC,IAAI,CAAC;;;oBAAhB;oBACA;;wBAAMD,KAAKC,IAAI,CAAC;;;oBAAhB;oBACK;;wBAAME,IAAAA,iBAAO,EAACH,MAAM;;;yBAArB,CAAA,AAAC,kBAA2C,IAAG,GAA/C;;;;oBAAkD;;wBAAMI,IAAAA,iBAAO,EAACJ,MAAM,kBAAkBL;;;oBAAtC;;;;;;;;IACxD;;AAEA,mGAAmG;AACnG,uGAAuG;AACvG,SAASU,cAAcC,EAAgB;IACrC,IAAMC,WAAWC,KAAKC,GAAG,KAAK;IAC9B,OAAS;QACP,IAAI;YACFH,GAAGL,IAAI,CAAC;YACR;QACF,EAAE,OAAOS,KAAK;YACZ,IAAIF,KAAKC,GAAG,MAAMF,YAAY,CAAC,2BAA2BI,IAAI,CAAC,AAACD,IAAcE,OAAO,GAAG,MAAMF;YAC9FG,QAAQC,IAAI,CAAC,IAAIC,WAAW,IAAIC,kBAAkB,KAAK,GAAG,GAAG;QAC/D;IACF;AACF;AAEA,SAAeC,QAAQC,MAAc,EAAEC,IAAoB,EAAEC,OAA0D;;YAC/Gd,IASEN;;YATFM,KAAK,IAAIe,wBAAY,CAACH,QAAQE,QAAQE,YAAY,GAAG;gBAAEC,UAAU;YAAK,IAAI,CAAC;YACjF,IAAI;gBACF,6FAA6F;gBAC7F,yFAAyF;gBACzFjB,GAAGL,IAAI,CAAC;gBACR,yFAAyF;gBACzF,wEAAwE;gBACxE,IAAI,CAACmB,QAAQI,aAAa,EAAEnB,cAAcC;gBAC1CmB,IAAAA,iCAAiB,EAACnB;gBACZN,OAAO0B,IAAAA,8BAAgB,EAACpB;gBAC9B;;oBAAO;wBAAEqB,QAAQ;4BAAErB,IAAAA;wBAAG;wBAAGN,MAAAA;oBAAK;;YAChC,EAAE,OAAOU,KAAK;gBACZ,4FAA4F;gBAC5F,0CAA0C;gBAC1CJ,GAAGsB,KAAK;gBACR,MAAMlB;YACR;;;;;IACF;;AAEA,SAAekB,MAAMD,MAAoB;;;YACvCA,OAAOrB,EAAE,CAACsB,KAAK;;;;;IACjB;;AAEA,SAAeC,iBAAiBC,OAAqB,EAAE9B,IAAgB;;;;;oBACrE,qFAAqF;oBACrF;;wBAAM+B,IAAAA,8BAAe,EAAC/B,MAAM;mCAAME,uBAAuBF;2BAAOgC,0BAAW;;;oBAA3E;;;;;;IACF;;AAEA,SAAeC,oBAAoBH,OAAqB,EAAE9B,IAAgB,EAAEkC,GAAW;;YAChF,2BAAA,mBAAA,gBAAA,WAAA,OAAMC;;;;oBAAN,kCAAA,2BAAA;;;;;;;;;oBAAA,YAAiBC,IAAAA,uBAAc,EAACF;;;2BAAhC,6BAAA,QAAA;;;;oBAAMC,UAAN;oBAAsC;;wBAAMA,QAAQE,MAAM,CAACrC;;;oBAArB;;;oBAAtC;;;;;;;;;;;;oBAAA;oBAAA;;;;;;;6BAAA,6BAAA;4BAAA;;;4BAAA;kCAAA;;;;;;;;;;;;IACP;;AAEA,SAAesC,sBAAsBX,MAAoB,EAAEY,KAAiB,EAAEC,EAAU;;;YACtFb,OAAOrB,EAAE,CAACL,IAAI,CAAC,AAAC,yBAA2B,OAAHuC;;;;;IAC1C;;AAGO,IAAM3C,oBAA+C;IAC1D4C,UAAU/C;IACVgD,eAAe/C;IACfgD,kBAAkBC,0BAAa;IAC/B3B,SAAAA;IACAW,OAAAA;IACAC,kBAAAA;IACAI,qBAAAA;IACAK,uBAAAA;IACAO,aAAa,SAAbA,YAAclB,QAAQ3B;eAAS6C,IAAAA,oBAAW,EAAClB,OAAOrB,EAAE,EAAEN;;AACxD;AAEO,SAAeJ,WAAWsC,GAAmB,EAAEd,OAA6B;;;YACjF;;gBAAO0B,IAAAA,uBAAe,EAACZ,KAAKrC,mBAAmBuB;;;IACjD"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/reconcile.ts"],"sourcesContent":["import type { Config } from '../../config/index.ts';\nimport { SenseError } from '../../errors.ts';\nimport type { ReconcileDelta } from '../../features/types.ts';\nimport type { ParsedDoc } from '../../scan/index.ts';\nimport { segmentField } from '../../text/segment.ts';\nimport { quoteIdent, recordReconcileDuration } from '../shared.ts';\nimport { BEGIN_WRITE } from '../transaction.ts';\nimport type { Connection, ReconcileDialect } from '../types.ts';\n\n// This store's dialect (types.ts's ReconcileDialect) for the shared orchestration in\n// store/reconcile.ts. content is FTS5-virtual with \"_seg\" sidecars for lexical.ts.\n\n// SQLite's compile-time SQLITE_MAX_COLUMN, default 2000 (https://www.sqlite.org/limits.html).\nconst MAX_FRONTMATTER_COLUMNS = 2000;\n\n// Shared by reconcileContent() and the tokenize-only rebuild in open.ts, so both prepare the\n// same literal instead of two copies drifting apart.\nexport const INSERT_CONTENT_SQL = `INSERT INTO content (rowid, title, summary, text, \"path\", title_seg, summary_seg, text_seg) VALUES ((SELECT rowid FROM frontmatter WHERE \"path\" = ?), ?, ?, ?, ?, ?, ?, ?)`;\n\n// A single content row's param tuple, matching INSERT_CONTENT_SQL's placeholder order.\n// Assumes the frontmatter row for doc.relPath already exists (rowid subquery).\nexport function contentRow(doc: ParsedDoc): unknown[] {\n return [doc.relPath, doc.search.title, doc.search.summary, doc.search.text, doc.relPath, segmentField(doc.search.title), segmentField(doc.search.summary), segmentField(doc.search.text)];\n}\n\nasync function reconcileContent(conn: Connection, touched: string[], docs: ParsedDoc[], _delta: ReconcileDelta, _cfg: Config): Promise<void> {\n // FTS5 has no upsert, so delete-before-insert, coupled to the frontmatter rowid (indexed via\n // its PRIMARY KEY) rather than the UNINDEXED `path` column, which a per-row DELETE would scan to find.\n // builder.ts's generation fence rejects a plan whose added/touched classification went stale\n // behind another publication, so this receives one classification from the locked generation.\n if (touched.length > 0)\n await conn.runBatch(\n 'DELETE FROM content WHERE rowid = (SELECT rowid FROM frontmatter WHERE \"path\" = ?)',\n touched.map((p) => [p])\n );\n\n if (docs.length > 0) await conn.runBatch(INSERT_CONTENT_SQL, docs.map(contentRow));\n}\n\n// SQLite's ADD COLUMN is metadata-only, so a loop costs nothing extra over one statement.\nasync function addColumns(conn: Connection, names: string[]): Promise<void> {\n for (const name of names) await conn.exec(`ALTER TABLE frontmatter ADD COLUMN ${quoteIdent(name)}`);\n}\n\nexport const sqliteDialect: ReconcileDialect = {\n beginMode: () => BEGIN_WRITE,\n checkColumnLimit(count) {\n // Fence before ALTERing: SQLite's own failure past this point is a raw\n // \"too many columns on sqlite_altertab_frontmatter\" with no indication of the boundary or the levers.\n if (count > MAX_FRONTMATTER_COLUMNS) {\n throw new SenseError(\n 'COLUMN_LIMIT',\n `frontmatter would need ${count} columns, crossing SQLite's compile-time SQLITE_MAX_COLUMN limit (default ${MAX_FRONTMATTER_COLUMNS}; see https://www.sqlite.org/limits.html). Narrow the presets' include globs so fewer/other files are indexed, or fix whatever is generating unbounded frontmatter keys.`\n );\n }\n },\n addColumns,\n reconcileContent,\n recordDuration: recordReconcileDuration,\n};\n"],"names":["INSERT_CONTENT_SQL","contentRow","sqliteDialect","MAX_FRONTMATTER_COLUMNS","doc","relPath","search","title","summary","text","segmentField","reconcileContent","conn","touched","docs","_delta","_cfg","length","runBatch","map","p","addColumns","names","name","exec","quoteIdent","beginMode","BEGIN_WRITE","checkColumnLimit","count","SenseError","recordDuration","recordReconcileDuration"],"mappings":";;;;;;;;;;;QAiBaA;eAAAA;;QAIGC;eAAAA;;QAuBHC;eAAAA;;;wBA3Cc;yBAGE;wBACuB;6BACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG5B,qFAAqF;AACrF,mFAAmF;AAEnF,8FAA8F;AAC9F,IAAMC,0BAA0B;AAIzB,IAAMH,qBAAqB;AAI3B,SAASC,WAAWG,GAAc;IACvC,OAAO;QAACA,IAAIC,OAAO;QAAED,IAAIE,MAAM,CAACC,KAAK;QAAEH,IAAIE,MAAM,CAACE,OAAO;QAAEJ,IAAIE,MAAM,CAACG,IAAI;QAAEL,IAAIC,OAAO;QAAEK,IAAAA,uBAAY,EAACN,IAAIE,MAAM,CAACC,KAAK;QAAGG,IAAAA,uBAAY,EAACN,IAAIE,MAAM,CAACE,OAAO;QAAGE,IAAAA,uBAAY,EAACN,IAAIE,MAAM,CAACG,IAAI;KAAE;AAC3L;AAEA,SAAeE,iBAAiBC,IAAgB,EAAEC,OAAiB,EAAEC,IAAiB,EAAEC,MAAsB,EAAEC,IAAY;;;;;yBAKtHH,CAAAA,QAAQI,MAAM,GAAG,CAAA,GAAjBJ;;;;oBACF;;wBAAMD,KAAKM,QAAQ,CACjB,sFACAL,QAAQM,GAAG,CAAC,SAACC;mCAAM;gCAACA;6BAAE;;;;oBAFxB;;;yBAKEN,CAAAA,KAAKG,MAAM,GAAG,CAAA,GAAdH;;;;oBAAiB;;wBAAMF,KAAKM,QAAQ,CAAClB,oBAAoBc,KAAKK,GAAG,CAAClB;;;oBAAjD;;;;;;;;IACvB;;AAEA,0FAA0F;AAC1F,SAAeoB,WAAWT,IAAgB,EAAEU,KAAe;;YACpD,2BAAA,mBAAA,gBAAA,WAAA,OAAMC;;;;oBAAN,kCAAA,2BAAA;;;;;;;;;oBAAA,YAAcD;;;2BAAd,6BAAA,QAAA;;;;oBAAMC,OAAN;oBAAqB;;wBAAMX,KAAKY,IAAI,CAAC,AAAC,sCAAsD,OAAjBC,IAAAA,oBAAU,EAACF;;;oBAAjE;;;oBAArB;;;;;;;;;;;;oBAAA;oBAAA;;;;;;;6BAAA,6BAAA;4BAAA;;;4BAAA;kCAAA;;;;;;;;;;;;IACP;;AAEO,IAAMrB,gBAAkC;IAC7CwB,WAAW,SAAXA;eAAiBC,0BAAW;;IAC5BC,kBAAAA,SAAAA,iBAAiBC,KAAK;QACpB,uEAAuE;QACvE,sGAAsG;QACtG,IAAIA,QAAQ1B,yBAAyB;YACnC,MAAM,IAAI2B,oBAAU,CAClB,gBACA,AAAC,0BAA2G3B,OAAlF0B,OAAM,8EAAoG,OAAxB1B,yBAAwB;QAExI;IACF;IACAkB,YAAAA;IACAV,kBAAAA;IACAoB,gBAAgBC,iCAAuB;AACzC"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/sqlite/reconcile.ts"],"sourcesContent":["import type { Config } from '../../config/index.ts';\nimport { SenseError } from '../../errors.ts';\nimport type { ReconcileDelta } from '../../features/types.ts';\nimport type { ParsedDoc } from '../../scan/index.ts';\nimport { segmentField } from '../../text/segment.ts';\nimport { quoteIdent, recordReconcileDuration } from '../shared.ts';\nimport { BEGIN_WRITE } from '../transaction.ts';\nimport type { Connection, ReconcileDialect } from '../types.ts';\n\n// This store's dialect (types.ts's ReconcileDialect) for the shared orchestration in\n// store/reconcile.ts. content is FTS5-virtual with \"_seg\" sidecars for lexical.ts.\n\n// SQLite's compile-time SQLITE_MAX_COLUMN, default 2000 (https://www.sqlite.org/limits.html).\nconst MAX_FRONTMATTER_COLUMNS = 2000;\n\n// Shared by reconcileContent() and the tokenize-only rebuild in open.ts, so both prepare the\n// same literal instead of two copies drifting apart.\nexport const INSERT_CONTENT_SQL = `INSERT INTO content (rowid, title, summary, text, \"path\", title_seg, summary_seg, text_seg) VALUES ((SELECT rowid FROM frontmatter WHERE \"path\" = ?), ?, ?, ?, ?, ?, ?, ?)`;\n\n// A single content row's param tuple, matching INSERT_CONTENT_SQL's placeholder order.\n// Assumes the frontmatter row for doc.relPath already exists (rowid subquery).\nexport function contentRow(doc: ParsedDoc): unknown[] {\n return [doc.relPath, doc.search.title, doc.search.summary, doc.search.text, doc.relPath, segmentField(doc.search.title), segmentField(doc.search.summary), segmentField(doc.search.text)];\n}\n\nasync function reconcileContent(conn: Connection, touched: string[], docs: ParsedDoc[], _delta: ReconcileDelta, _cfg: Config): Promise<void> {\n // FTS5 has no upsert, so delete-before-insert, coupled to the frontmatter rowid (indexed via\n // its PRIMARY KEY) rather than the UNINDEXED `path` column, which a per-row DELETE would scan to find.\n // builder.ts's generation fence rejects a plan whose added/touched classification went stale\n // behind another publication, so this receives one classification from the locked generation.\n if (touched.length > 0)\n await conn.runBatch(\n 'DELETE FROM content WHERE rowid = (SELECT rowid FROM frontmatter WHERE \"path\" = ?)',\n touched.map((p) => [p])\n );\n\n if (docs.length > 0) await conn.runBatch(INSERT_CONTENT_SQL, docs.map(contentRow));\n}\n\n// SQLite's ADD COLUMN is metadata-only, so a loop costs nothing extra over one statement.\nasync function addColumns(conn: Connection, names: string[]): Promise<void> {\n for (const name of names) await conn.exec(`ALTER TABLE frontmatter ADD COLUMN ${quoteIdent(name)}`);\n}\n\nexport const sqliteDialect: ReconcileDialect = {\n beginMode: () => BEGIN_WRITE,\n checkColumnLimit(count) {\n // Fence before ALTERing: SQLite's own failure past this point is a raw\n // \"too many columns on sqlite_altertab_frontmatter\" with no indication of the boundary or the levers.\n if (count > MAX_FRONTMATTER_COLUMNS) {\n throw new SenseError(\n 'COLUMN_LIMIT',\n `frontmatter would need ${count} columns, crossing SQLite's compile-time SQLITE_MAX_COLUMN limit (default ${MAX_FRONTMATTER_COLUMNS}; see https://www.sqlite.org/limits.html). Narrow the presets' include globs so fewer/other files are indexed, or fix whatever is generating unbounded frontmatter keys.`\n );\n }\n },\n addColumns,\n reconcileContent,\n recordDuration: recordReconcileDuration,\n};\n"],"names":["INSERT_CONTENT_SQL","contentRow","sqliteDialect","MAX_FRONTMATTER_COLUMNS","doc","relPath","search","title","summary","text","segmentField","reconcileContent","conn","touched","docs","_delta","_cfg","length","runBatch","map","p","addColumns","names","name","exec","quoteIdent","beginMode","BEGIN_WRITE","checkColumnLimit","count","SenseError","recordDuration","recordReconcileDuration"],"mappings":";;;;;;;;;;;QAiBaA;eAAAA;;QAIGC;eAAAA;;QAuBHC;eAAAA;;;wBA3Cc;yBAGE;wBACuB;6BACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG5B,qFAAqF;AACrF,mFAAmF;AAEnF,8FAA8F;AAC9F,IAAMC,0BAA0B;AAIzB,IAAMH,qBAAqB;AAI3B,SAASC,WAAWG,GAAc;IACvC,OAAO;QAACA,IAAIC,OAAO;QAAED,IAAIE,MAAM,CAACC,KAAK;QAAEH,IAAIE,MAAM,CAACE,OAAO;QAAEJ,IAAIE,MAAM,CAACG,IAAI;QAAEL,IAAIC,OAAO;QAAEK,IAAAA,uBAAY,EAACN,IAAIE,MAAM,CAACC,KAAK;QAAGG,IAAAA,uBAAY,EAACN,IAAIE,MAAM,CAACE,OAAO;QAAGE,IAAAA,uBAAY,EAACN,IAAIE,MAAM,CAACG,IAAI;KAAE;AAC3L;AAEA,SAAeE,iBAAiBC,IAAgB,EAAEC,OAAiB,EAAEC,IAAiB,EAAEC,MAAsB,EAAEC,IAAY;;;;;yBAKtHH,CAAAA,QAAQI,MAAM,GAAG,CAAA,GAAjBJ;;;;oBACF;;wBAAMD,KAAKM,QAAQ,CACjB,sFACAL,QAAQM,GAAG,CAAC,SAACC;mCAAM;gCAACA;6BAAE;;;;oBAFxB;;;yBAKEN,CAAAA,KAAKG,MAAM,GAAG,CAAA,GAAdH;;;;oBAAiB;;wBAAMF,KAAKM,QAAQ,CAAClB,oBAAoBc,KAAKK,GAAG,CAAClB;;;oBAAjD;;;;;;;;IACvB;;AAEA,0FAA0F;AAC1F,SAAeoB,WAAWT,IAAgB,EAAEU,KAAe;;YACpD,2BAAA,mBAAA,gBAAA,WAAA,OAAMC;;;;oBAAN,kCAAA,2BAAA;;;;;;;;;oBAAA,YAAcD;;;2BAAd,6BAAA,QAAA;;;;oBAAMC,OAAN;oBAAqB;;wBAAMX,KAAKY,IAAI,CAAC,AAAC,sCAAsD,OAAjBC,IAAAA,oBAAU,EAACF;;;oBAAjE;;;oBAArB;;;;;;;;;;;;oBAAA;oBAAA;;;;;;;6BAAA,6BAAA;4BAAA;;;4BAAA;kCAAA;;;;;;;;;;;;IACP;;AAEO,IAAMrB,gBAAkC;IAC7CwB,WAAW,SAAXA;eAAiBC,0BAAW;;IAC5BC,kBAAAA,SAAAA,iBAAiBC,KAAK;QACpB,uEAAuE;QACvE,sGAAsG;QACtG,IAAIA,QAAQ1B,yBAAyB;YACnC,MAAM,IAAI2B,oBAAU,CAClB,gBACA,AAAC,0BAA2G3B,OAAlF0B,OAAM,8EAAoG,OAAxB1B,yBAAwB;QAExI;IACF;IACAkB,YAAAA;IACAV,kBAAAA;IACAoB,gBAAgBC,iCAAuB;AACzC"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/sql-functions.ts"],"sourcesContent":["import type { DatabaseSync } from 'node:sqlite';\nimport { segmentMatch } from '../../text/segment.ts';\nimport { basenameImpl, hasImpl } from '../sql-functions.ts';\n\nexport function registerFunctions(db: DatabaseSync): void {\n db.function('has', { deterministic: true, varargs: false }, hasImpl);\n\n db.function('basename', { deterministic: true, varargs: true }, basenameImpl);\n\n // Raw `content MATCH '<unspaced text>'` cannot be rewritten behind the author's back and matches\n // nothing, so the same transform is available to hand-written SQL by name.\n db.function('segment', { deterministic: true, varargs: false }, (terms: unknown): string => {\n const text = terms === null || terms === undefined ? '' : String(terms);\n return segmentMatch(text);\n });\n}\n"],"names":["registerFunctions","db","function","deterministic","varargs","hasImpl","basenameImpl","terms","text","undefined","String","segmentMatch"],"mappings":";;;;+BAIgBA;;;eAAAA;;;yBAHa;8BACS;AAE/B,SAASA,kBAAkBC,EAAgB;IAChDA,GAAGC,QAAQ,CAAC,OAAO;QAAEC,eAAe;QAAMC,SAAS;IAAM,GAAGC,uBAAO;IAEnEJ,GAAGC,QAAQ,CAAC,YAAY;QAAEC,eAAe;QAAMC,SAAS;IAAK,GAAGE,4BAAY;IAE5E,iGAAiG;IACjG,2EAA2E;IAC3EL,GAAGC,QAAQ,CAAC,WAAW;QAAEC,eAAe;QAAMC,SAAS;IAAM,GAAG,SAACG;QAC/D,IAAMC,OAAOD,UAAU,QAAQA,UAAUE,YAAY,KAAKC,OAAOH;QACjE,OAAOI,IAAAA,uBAAY,EAACH;IACtB;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/sqlite/sql-functions.ts"],"sourcesContent":["import type { DatabaseSync } from 'node:sqlite';\nimport { segmentMatch } from '../../text/segment.ts';\nimport { basenameImpl, hasImpl } from '../sql-functions.ts';\n\nexport function registerFunctions(db: DatabaseSync): void {\n db.function('has', { deterministic: true, varargs: false }, hasImpl);\n\n db.function('basename', { deterministic: true, varargs: true }, basenameImpl);\n\n // Raw `content MATCH '<unspaced text>'` cannot be rewritten behind the author's back and matches\n // nothing, so the same transform is available to hand-written SQL by name.\n db.function('segment', { deterministic: true, varargs: false }, (terms: unknown): string => {\n const text = terms === null || terms === undefined ? '' : String(terms);\n return segmentMatch(text);\n });\n}\n"],"names":["registerFunctions","db","function","deterministic","varargs","hasImpl","basenameImpl","terms","text","undefined","String","segmentMatch"],"mappings":";;;;+BAIgBA;;;eAAAA;;;yBAHa;8BACS;AAE/B,SAASA,kBAAkBC,EAAgB;IAChDA,GAAGC,QAAQ,CAAC,OAAO;QAAEC,eAAe;QAAMC,SAAS;IAAM,GAAGC,uBAAO;IAEnEJ,GAAGC,QAAQ,CAAC,YAAY;QAAEC,eAAe;QAAMC,SAAS;IAAK,GAAGE,4BAAY;IAE5E,iGAAiG;IACjG,2EAA2E;IAC3EL,GAAGC,QAAQ,CAAC,WAAW;QAAEC,eAAe;QAAMC,SAAS;IAAM,GAAG,SAACG;QAC/D,IAAMC,OAAOD,UAAU,QAAQA,UAAUE,YAAY,KAAKC,OAAOH;QACjE,OAAOI,IAAAA,uBAAY,EAACH;IACtB;AACF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/store.ts"],"sourcesContent":["import type { DatabaseSync } from 'node:sqlite';\nimport { getColumns } from '../shared.ts';\nimport { withTransaction } from '../transaction.ts';\nimport type { Capability, Connection, Statement, Store, VectorStore, VectorWriteRow } from '../types.ts';\nimport { createNativeVectorScopeOwner, hasVectorRow, pendingRows } from '../vectors.ts';\nimport { fieldStats } from './fieldStats.ts';\nimport { queryLexical } from './lexical.ts';\nimport { scanCandidates, scanSimilar, writeVectorBatch } from './vectors.ts';\n\nexport const CAPABILITIES: ReadonlySet<Capability> = new Set(['vectors', 'segment']);\n\n// Wraps the synchronous DatabaseSync connection in the async Store interface, sharing one\n// Connection instance (conn) with the builder's own reconcile call so transaction depth is tracked against the same object everywhere.\nexport function createStore(db: DatabaseSync, conn: Connection): Store {\n const vectorScope = createNativeVectorScopeOwner();\n const vectors: VectorStore = {\n async pending() {\n return pendingRows(conn);\n },\n async writeVectors(rows: VectorWriteRow[]) {\n await writeVectorBatch(conn, rows);\n },\n async candidates(qv, storeDims, fetch, allowed) {\n return scanCandidates(conn, qv, storeDims, fetch, allowed, vectorScope.activeFor(allowed));\n },\n async similar(path, opts) {\n return scanSimilar(conn, path, opts, vectorScope.activeFor(opts.allowed));\n },\n async hasVector(path) {\n return hasVectorRow(conn, path);\n },\n };\n vectorScope.bind(vectors);\n\n return {\n name: 'sqlite',\n capabilities: CAPABILITIES,\n async exec(sql: string): Promise<void> {\n await conn.exec(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n return conn.prepare(sql);\n },\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n await conn.runBatch(sql, paramRows);\n },\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n return withTransaction(conn, fn);\n },\n docs: {\n async columns() {\n return [...(await getColumns(conn))];\n },\n async fieldStats(columns, scopeWhere) {\n return fieldStats(conn, columns, scopeWhere);\n },\n },\n lexical: {\n async query(terms, opts) {\n return queryLexical(conn, terms, opts);\n },\n },\n vectors,\n async engineStatus() {\n // Read back rather than recomputed: this is what open() actually set (3x the largest\n // recorded reconcile, floored at 30s, capped at 10min), not a value re-derived here.\n const row = db.prepare('PRAGMA busy_timeout').get() as { timeout: number };\n return { busy_timeout: `${row.timeout}ms (derived: 3x the largest reconcile this cache has recorded, floored at 30000ms)` };\n },\n raw: {\n async prepare(sql: string) {\n const stmt = db.prepare(sql);\n stmt.setReadBigInts(true); // int64 past 2^53 arrives as BigInt instead of throwing at step time\n return {\n columns: () => stmt.columns(),\n // sense sql streams through an async iterator wrapping the sync iterate().\n iterate: async function* (...params: unknown[]) {\n yield* stmt.iterate(...(params as Parameters<typeof stmt.iterate>));\n },\n };\n },\n },\n async close() {\n db.close();\n },\n };\n}\n"],"names":["CAPABILITIES","createStore","Set","db","conn","vectorScope","createNativeVectorScopeOwner","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","candidates","qv","storeDims","fetch","allowed","scanCandidates","activeFor","similar","path","opts","scanSimilar","hasVector","hasVectorRow","bind","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","docs","columns","getColumns","fieldStats","scopeWhere","lexical","query","terms","queryLexical","engineStatus","row","get","busy_timeout","timeout","raw","stmt","setReadBigInts","iterate","params","close"],"mappings":";;;;;;;;;;;QASaA;eAAAA;;QAIGC;eAAAA;;;wBAZW;6BACK;yBAEwC;4BAC7C;yBACE;0BACiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEvD,IAAMD,eAAwC,IAAIE,IAAI;IAAC;IAAW;CAAU;AAI5E,SAASD,YAAYE,EAAgB,EAAEC,IAAgB;IAC5D,IAAMC,cAAcC,IAAAA,uCAA4B;IAChD,IAAMC,UAAuB;QACrBC,SAAN,SAAMA;;;oBACJ;;wBAAOC,IAAAA,sBAAW,EAACL;;;YACrB;;QACMM,cAAN,SAAMA,aAAaC,IAAsB;;;;;4BACvC;;gCAAMC,IAAAA,4BAAgB,EAACR,MAAMO;;;4BAA7B;;;;;;YACF;;QACME,YAAN,SAAMA,WAAWC,EAAE,EAAEC,SAAS,EAAEC,KAAK,EAAEC,OAAO;;;oBAC5C;;wBAAOC,IAAAA,0BAAc,EAACd,MAAMU,IAAIC,WAAWC,OAAOC,SAASZ,YAAYc,SAAS,CAACF;;;YACnF;;QACMG,SAAN,SAAMA,QAAQC,IAAI,EAAEC,IAAI;;;oBACtB;;wBAAOC,IAAAA,uBAAW,EAACnB,MAAMiB,MAAMC,MAAMjB,YAAYc,SAAS,CAACG,KAAKL,OAAO;;;YACzE;;QACMO,WAAN,SAAMA,UAAUH,IAAI;;;oBAClB;;wBAAOI,IAAAA,uBAAY,EAACrB,MAAMiB;;;YAC5B;;IACF;IACAhB,YAAYqB,IAAI,CAACnB;IAEjB,OAAO;QACLoB,MAAM;QACNC,cAAc5B;QACR6B,MAAN,SAAMA,KAAKC,GAAW;;;;;4BACpB;;gCAAM1B,KAAKyB,IAAI,CAACC;;;4BAAhB;;;;;;YACF;;QACMC,SAAN,SAAMA,QAAQD,GAAW;;;oBACvB;;wBAAO1B,KAAK2B,OAAO,CAACD;;;YACtB;;QACME,UAAN,SAAMA,SAASF,GAAW,EAAEG,SAAsB;;;;;4BAChD;;gCAAM7B,KAAK4B,QAAQ,CAACF,KAAKG;;;4BAAzB;;;;;;YACF;;QACMC,aAAN,SAAMA,YAAeC,EAAoB;;;oBACvC;;wBAAOC,IAAAA,8BAAe,EAAChC,MAAM+B;;;YAC/B;;QACAE,MAAM;YACEC,SAAN,SAAMA;;;;;gCACQ;;oCAAMC,IAAAA,oBAAU,EAACnC;;;gCAA7B;;oCAAQ;wCAAI;;;;;gBACd;;YACMoC,YAAN,SAAMA,WAAWF,OAAO,EAAEG,UAAU;;;wBAClC;;4BAAOD,IAAAA,wBAAU,EAACpC,MAAMkC,SAASG;;;gBACnC;;QACF;QACAC,SAAS;YACDC,OAAN,SAAMA,MAAMC,KAAK,EAAEtB,IAAI;;;wBACrB;;4BAAOuB,IAAAA,uBAAY,EAACzC,MAAMwC,OAAOtB;;;gBACnC;;QACF;QACAf,SAAAA;QACMuC,cAAN,SAAMA;;oBAGEC;;oBAFN,qFAAqF;oBACrF,qFAAqF;oBAC/EA,MAAM5C,GAAG4B,OAAO,CAAC,uBAAuBiB,GAAG;oBACjD;;wBAAO;4BAAEC,cAAc,AAAC,GAAc,OAAZF,IAAIG,OAAO,EAAC;wBAAoF;;;YAC5H;;QACAC,KAAK;YACGpB,SAAN,SAAMA,QAAQD,GAAW;;wBACjBsB;;wBAAAA,OAAOjD,GAAG4B,OAAO,CAACD;wBACxBsB,KAAKC,cAAc,CAAC,OAAO,qEAAqE;wBAChG;;4BAAO;gCACLf,SAAS,SAATA;2CAAec,KAAKd,OAAO;;gCAC3B,2EAA2E;gCAC3EgB,SAAS,SAATA;oCAA0B,IAAA,IAAA,OAAA,UAAA,QAAA,AAAGC,SAAH,UAAA,OAAA,OAAA,GAAA,OAAA,MAAA;wCAAGA,OAAH,QAAA,SAAA,CAAA,KAAoB;;;4CACrCH;;;;oDAAP;;mEAAA,0CAAOA,CAAAA,QAAAA,MAAKE,OAAO,OAAZF,OAAa,qBAAIG;;;oDAAxB;;;;;;oCACF;;4BACF;;;gBACF;;QACF;QACMC,OAAN,SAAMA;;;oBACJrD,GAAGqD,KAAK;;;;;YACV;;IACF;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/sqlite/store.ts"],"sourcesContent":["import type { DatabaseSync } from 'node:sqlite';\nimport { getColumns } from '../shared.ts';\nimport { withTransaction } from '../transaction.ts';\nimport type { Capability, Connection, Statement, Store, VectorStore, VectorWriteRow } from '../types.ts';\nimport { createNativeVectorScopeOwner, hasVectorRow, pendingRows } from '../vectors.ts';\nimport { fieldStats } from './fieldStats.ts';\nimport { queryLexical } from './lexical.ts';\nimport { scanCandidates, scanSimilar, writeVectorBatch } from './vectors.ts';\n\nexport const CAPABILITIES: ReadonlySet<Capability> = new Set(['vectors', 'segment']);\n\n// Wraps the synchronous DatabaseSync connection in the async Store interface, sharing one\n// Connection instance (conn) with the builder's own reconcile call so transaction depth is tracked against the same object everywhere.\nexport function createStore(db: DatabaseSync, conn: Connection): Store {\n const vectorScope = createNativeVectorScopeOwner();\n const vectors: VectorStore = {\n async pending() {\n return pendingRows(conn);\n },\n async writeVectors(rows: VectorWriteRow[]) {\n await writeVectorBatch(conn, rows);\n },\n async candidates(qv, storeDims, fetch, allowed) {\n return scanCandidates(conn, qv, storeDims, fetch, allowed, vectorScope.activeFor(allowed));\n },\n async similar(path, opts) {\n return scanSimilar(conn, path, opts, vectorScope.activeFor(opts.allowed));\n },\n async hasVector(path) {\n return hasVectorRow(conn, path);\n },\n };\n vectorScope.bind(vectors);\n\n return {\n name: 'sqlite',\n capabilities: CAPABILITIES,\n async exec(sql: string): Promise<void> {\n await conn.exec(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n return conn.prepare(sql);\n },\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n await conn.runBatch(sql, paramRows);\n },\n async transaction<T>(fn: () => Promise<T>): Promise<T> {\n return withTransaction(conn, fn);\n },\n docs: {\n async columns() {\n return [...(await getColumns(conn))];\n },\n async fieldStats(columns, scopeWhere) {\n return fieldStats(conn, columns, scopeWhere);\n },\n },\n lexical: {\n async query(terms, opts) {\n return queryLexical(conn, terms, opts);\n },\n },\n vectors,\n async engineStatus() {\n // Read back rather than recomputed: this is what open() actually set (3x the largest\n // recorded reconcile, floored at 30s, capped at 10min), not a value re-derived here.\n const row = db.prepare('PRAGMA busy_timeout').get() as { timeout: number };\n return { busy_timeout: `${row.timeout}ms (derived: 3x the largest reconcile this cache has recorded, floored at 30000ms)` };\n },\n raw: {\n async prepare(sql: string) {\n const stmt = db.prepare(sql);\n stmt.setReadBigInts(true); // int64 past 2^53 arrives as BigInt instead of throwing at step time\n return {\n columns: () => stmt.columns(),\n // sense sql streams through an async iterator wrapping the sync iterate().\n iterate: async function* (...params: unknown[]) {\n yield* stmt.iterate(...(params as Parameters<typeof stmt.iterate>));\n },\n };\n },\n },\n async close() {\n db.close();\n },\n };\n}\n"],"names":["CAPABILITIES","createStore","Set","db","conn","vectorScope","createNativeVectorScopeOwner","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","candidates","qv","storeDims","fetch","allowed","scanCandidates","activeFor","similar","path","opts","scanSimilar","hasVector","hasVectorRow","bind","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","docs","columns","getColumns","fieldStats","scopeWhere","lexical","query","terms","queryLexical","engineStatus","row","get","busy_timeout","timeout","raw","stmt","setReadBigInts","iterate","params","close"],"mappings":";;;;;;;;;;;QASaA;eAAAA;;QAIGC;eAAAA;;;wBAZW;6BACK;yBAEwC;4BAC7C;yBACE;0BACiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEvD,IAAMD,eAAwC,IAAIE,IAAI;IAAC;IAAW;CAAU;AAI5E,SAASD,YAAYE,EAAgB,EAAEC,IAAgB;IAC5D,IAAMC,cAAcC,IAAAA,uCAA4B;IAChD,IAAMC,UAAuB;QACrBC,SAAN,SAAMA;;;oBACJ;;wBAAOC,IAAAA,sBAAW,EAACL;;;YACrB;;QACMM,cAAN,SAAMA,aAAaC,IAAsB;;;;;4BACvC;;gCAAMC,IAAAA,4BAAgB,EAACR,MAAMO;;;4BAA7B;;;;;;YACF;;QACME,YAAN,SAAMA,WAAWC,EAAE,EAAEC,SAAS,EAAEC,KAAK,EAAEC,OAAO;;;oBAC5C;;wBAAOC,IAAAA,0BAAc,EAACd,MAAMU,IAAIC,WAAWC,OAAOC,SAASZ,YAAYc,SAAS,CAACF;;;YACnF;;QACMG,SAAN,SAAMA,QAAQC,IAAI,EAAEC,IAAI;;;oBACtB;;wBAAOC,IAAAA,uBAAW,EAACnB,MAAMiB,MAAMC,MAAMjB,YAAYc,SAAS,CAACG,KAAKL,OAAO;;;YACzE;;QACMO,WAAN,SAAMA,UAAUH,IAAI;;;oBAClB;;wBAAOI,IAAAA,uBAAY,EAACrB,MAAMiB;;;YAC5B;;IACF;IACAhB,YAAYqB,IAAI,CAACnB;IAEjB,OAAO;QACLoB,MAAM;QACNC,cAAc5B;QACR6B,MAAN,SAAMA,KAAKC,GAAW;;;;;4BACpB;;gCAAM1B,KAAKyB,IAAI,CAACC;;;4BAAhB;;;;;;YACF;;QACMC,SAAN,SAAMA,QAAQD,GAAW;;;oBACvB;;wBAAO1B,KAAK2B,OAAO,CAACD;;;YACtB;;QACME,UAAN,SAAMA,SAASF,GAAW,EAAEG,SAAsB;;;;;4BAChD;;gCAAM7B,KAAK4B,QAAQ,CAACF,KAAKG;;;4BAAzB;;;;;;YACF;;QACMC,aAAN,SAAMA,YAAeC,EAAoB;;;oBACvC;;wBAAOC,IAAAA,8BAAe,EAAChC,MAAM+B;;;YAC/B;;QACAE,MAAM;YACEC,SAAN,SAAMA;;;;;gCACQ;;oCAAMC,IAAAA,oBAAU,EAACnC;;;gCAA7B;;oCAAQ;wCAAI;;;;;gBACd;;YACMoC,YAAN,SAAMA,WAAWF,OAAO,EAAEG,UAAU;;;wBAClC;;4BAAOD,IAAAA,wBAAU,EAACpC,MAAMkC,SAASG;;;gBACnC;;QACF;QACAC,SAAS;YACDC,OAAN,SAAMA,MAAMC,KAAK,EAAEtB,IAAI;;;wBACrB;;4BAAOuB,IAAAA,uBAAY,EAACzC,MAAMwC,OAAOtB;;;gBACnC;;QACF;QACAf,SAAAA;QACMuC,cAAN,SAAMA;;oBAGEC;;oBAFN,qFAAqF;oBACrF,qFAAqF;oBAC/EA,MAAM5C,GAAG4B,OAAO,CAAC,uBAAuBiB,GAAG;oBACjD;;wBAAO;4BAAEC,cAAc,AAAC,GAAc,OAAZF,IAAIG,OAAO,EAAC;wBAAoF;;;YAC5H;;QACAC,KAAK;YACGpB,SAAN,SAAMA,QAAQD,GAAW;;wBACjBsB;;wBAAAA,OAAOjD,GAAG4B,OAAO,CAACD;wBACxBsB,KAAKC,cAAc,CAAC,OAAO,qEAAqE;wBAChG;;4BAAO;gCACLf,SAAS,SAATA;2CAAec,KAAKd,OAAO;;gCAC3B,2EAA2E;gCAC3EgB,SAAS,SAATA;oCAA0B,IAAA,IAAA,OAAA,UAAA,QAAA,AAAGC,SAAH,UAAA,OAAA,OAAA,GAAA,OAAA,MAAA;wCAAGA,OAAH,QAAA,SAAA,CAAA,KAAoB;;;4CACrCH;;;;oDAAP;;mEAAA,0CAAOA,CAAAA,QAAAA,MAAKE,OAAO,OAAZF,OAAa,qBAAIG;;;oDAAxB;;;;;;oCACF;;4BACF;;;gBACF;;QACF;QACMC,OAAN,SAAMA;;;oBACJrD,GAAGqD,KAAK;;;;;YACV;;IACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/sqlite/vectors.ts"],"sourcesContent":["import type { Connection, VectorCandidate, VectorSimilar, VectorWriteRow } from '../types.ts';\nimport { asCosine, compareVectorScores, NATIVE_VECTOR_SCOPE_TABLE, sampleEvenly } from '../vectors.ts';\n\n// One runBatch call per provider batch: the caller (embed/query.ts) already batches by the\n// provider's batchCap, so this is one crossing per batch, never per row.\nexport async function writeVectorBatch(conn: Connection, rows: VectorWriteRow[]): Promise<void> {\n if (rows.length === 0) return;\n await conn.runBatch(\n 'UPDATE embeddings SET scale = ?, vector = ? WHERE \"path\" = ? AND chunk = ?',\n rows.map((row) => [row.scale, row.vector, row.path, row.chunk])\n );\n}\n\n// Best chunk per file by cosine, its line range riding along: the JS loop over stored int8\n// BLOBs this store's scan strategy is (a native store scans differently, same contract).\nexport async function scanCandidates(conn: Connection, qv: Float32Array, storeDims: number, fetch: number, allowed?: Set<string>, nativeScope = false): Promise<VectorCandidate[]> {\n const scope = nativeScope ? ` AND \"path\" IN (SELECT \"path\" FROM ${NATIVE_VECTOR_SCOPE_TABLE})` : '';\n const stmt = await conn.prepare(`SELECT \"path\", chunk, start_line, end_line, vector FROM embeddings WHERE vector IS NOT NULL${scope} ORDER BY \"path\", chunk`);\n const rows = (await stmt.all()) as Array<{\n path: string;\n chunk: number;\n start_line: number;\n end_line: number;\n vector: Uint8Array;\n }>;\n\n let queryNorm = 0;\n for (let d = 0; d < Math.min(storeDims, qv.length); d++) queryNorm += qv[d] * qv[d];\n queryNorm = Math.sqrt(queryNorm);\n\n const best = new Map<string, { score: number; chunk: number; lines: string }>();\n for (const row of rows) {\n if (allowed && !allowed.has(row.path)) continue;\n const q = new Int8Array(row.vector.buffer, row.vector.byteOffset, Math.min(storeDims, row.vector.byteLength));\n // Rounding to int8 costs the stored row its unit norm, so dividing by that norm is what makes\n // this a cosine rather than a scaled dot product. `scale` cancels out of the ratio.\n let dot = 0;\n let norm = 0;\n const length = Math.min(q.length, qv.length);\n for (let d = 0; d < length; d++) {\n dot += q[d] * qv[d];\n norm += q[d] * q[d];\n }\n for (let d = length; d < q.length; d++) norm += q[d] * q[d];\n const score = norm === 0 || queryNorm === 0 ? 0 : dot / (Math.sqrt(norm) * queryNorm);\n const existing = best.get(row.path);\n if (!existing || score > existing.score || (score === existing.score && row.chunk < existing.chunk)) {\n best.set(row.path, { score, chunk: row.chunk, lines: `L${row.start_line}-${row.end_line}` });\n }\n }\n return [...best.entries()]\n .map(([path, value]) => ({ path, ...value }))\n .sort(compareVectorScores)\n .slice(0, fetch)\n .map(({ path, lines, score }) => ({ path, lines, similarity: asCosine(score) }));\n}\n\n// Note-to-note similarity is the max cosine over (target chunk, other chunk) pairs, one linear\n// scan of stored vectors.\nexport async function scanSimilar(conn: Connection, path: string, opts: { exclude: Set<string>; allowed?: Set<string>; k: number }, nativeScope = false): Promise<VectorSimilar[]> {\n const targetStmt = await conn.prepare('SELECT vector FROM embeddings WHERE \"path\" = ? AND vector IS NOT NULL ORDER BY chunk');\n const targetRows = (await targetStmt.all(path)) as Array<{ vector: Uint8Array }>;\n if (targetRows.length === 0) return [];\n // Each side's norm divides its own dot product, so both are taken once here rather than per pair.\n const target = sampleEvenly(targetRows).map((row) => {\n const v = new Int8Array(row.vector.buffer, row.vector.byteOffset, row.vector.byteLength);\n let norm = 0;\n for (let d = 0; d < v.length; d++) norm += v[d] * v[d];\n return { v, norm: Math.sqrt(norm) };\n });\n\n const scope = nativeScope ? ` AND \"path\" IN (SELECT \"path\" FROM ${NATIVE_VECTOR_SCOPE_TABLE})` : '';\n const stmt = await conn.prepare(`SELECT \"path\", vector FROM embeddings WHERE vector IS NOT NULL${scope}`);\n const rows = (await stmt.all()) as Array<{ path: string; vector: Uint8Array }>;\n const best = new Map<string, number>();\n for (const row of rows) {\n if (row.path === path || opts.exclude.has(row.path) || (opts.allowed && !opts.allowed.has(row.path))) continue;\n const other = new Int8Array(row.vector.buffer, row.vector.byteOffset, row.vector.byteLength);\n let otherNorm = 0;\n for (let d = 0; d < other.length; d++) otherNorm += other[d] * other[d];\n otherNorm = Math.sqrt(otherNorm);\n for (const t of target) {\n let dot = 0;\n const len = Math.min(t.v.length, other.length);\n for (let d = 0; d < len; d++) dot += t.v[d] * other[d];\n const score = t.norm === 0 || otherNorm === 0 ? 0 : dot / (t.norm * otherNorm);\n const existing = best.get(row.path);\n if (existing === undefined || score > existing) best.set(row.path, score);\n }\n }\n\n return [...best.entries()]\n .map(([p, score]) => ({ path: p, score }))\n .sort(compareVectorScores)\n .slice(0, opts.k)\n .map(({ path: p, score }) => ({ path: p, similarity: asCosine(score) }));\n}\n"],"names":["scanCandidates","scanSimilar","writeVectorBatch","conn","rows","length","runBatch","map","row","scale","vector","path","chunk","qv","storeDims","fetch","allowed","nativeScope","scope","stmt","queryNorm","d","best","q","dot","norm","score","existing","NATIVE_VECTOR_SCOPE_TABLE","prepare","all","Math","min","sqrt","Map","has","Int8Array","buffer","byteOffset","byteLength","get","set","lines","start_line","end_line","entries","value","sort","compareVectorScores","slice","similarity","asCosine","opts","targetStmt","targetRows","target","other","otherNorm","t","len","sampleEvenly","v","exclude","undefined","p","k"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/sqlite/vectors.ts"],"sourcesContent":["import type { Connection, VectorCandidate, VectorSimilar, VectorWriteRow } from '../types.ts';\nimport { asCosine, compareVectorScores, NATIVE_VECTOR_SCOPE_TABLE, sampleEvenly } from '../vectors.ts';\n\n// One runBatch call per provider batch: the caller (embed/query.ts) already batches by the\n// provider's batchCap, so this is one crossing per batch, never per row.\nexport async function writeVectorBatch(conn: Connection, rows: VectorWriteRow[]): Promise<void> {\n if (rows.length === 0) return;\n await conn.runBatch(\n 'UPDATE embeddings SET scale = ?, vector = ? WHERE \"path\" = ? AND chunk = ?',\n rows.map((row) => [row.scale, row.vector, row.path, row.chunk])\n );\n}\n\n// Best chunk per file by cosine, its line range riding along: the JS loop over stored int8\n// BLOBs this store's scan strategy is (a native store scans differently, same contract).\nexport async function scanCandidates(conn: Connection, qv: Float32Array, storeDims: number, fetch: number, allowed?: Set<string>, nativeScope = false): Promise<VectorCandidate[]> {\n const scope = nativeScope ? ` AND \"path\" IN (SELECT \"path\" FROM ${NATIVE_VECTOR_SCOPE_TABLE})` : '';\n const stmt = await conn.prepare(`SELECT \"path\", chunk, start_line, end_line, vector FROM embeddings WHERE vector IS NOT NULL${scope} ORDER BY \"path\", chunk`);\n const rows = (await stmt.all()) as Array<{\n path: string;\n chunk: number;\n start_line: number;\n end_line: number;\n vector: Uint8Array;\n }>;\n\n let queryNorm = 0;\n for (let d = 0; d < Math.min(storeDims, qv.length); d++) queryNorm += qv[d] * qv[d];\n queryNorm = Math.sqrt(queryNorm);\n\n const best = new Map<string, { score: number; chunk: number; lines: string }>();\n for (const row of rows) {\n if (allowed && !allowed.has(row.path)) continue;\n const q = new Int8Array(row.vector.buffer, row.vector.byteOffset, Math.min(storeDims, row.vector.byteLength));\n // Rounding to int8 costs the stored row its unit norm, so dividing by that norm is what makes\n // this a cosine rather than a scaled dot product. `scale` cancels out of the ratio.\n let dot = 0;\n let norm = 0;\n const length = Math.min(q.length, qv.length);\n for (let d = 0; d < length; d++) {\n dot += q[d] * qv[d];\n norm += q[d] * q[d];\n }\n for (let d = length; d < q.length; d++) norm += q[d] * q[d];\n const score = norm === 0 || queryNorm === 0 ? 0 : dot / (Math.sqrt(norm) * queryNorm);\n const existing = best.get(row.path);\n if (!existing || score > existing.score || (score === existing.score && row.chunk < existing.chunk)) {\n best.set(row.path, { score, chunk: row.chunk, lines: `L${row.start_line}-${row.end_line}` });\n }\n }\n return [...best.entries()]\n .map(([path, value]) => ({ path, ...value }))\n .sort(compareVectorScores)\n .slice(0, fetch)\n .map(({ path, lines, score }) => ({ path, lines, similarity: asCosine(score) }));\n}\n\n// Note-to-note similarity is the max cosine over (target chunk, other chunk) pairs, one linear\n// scan of stored vectors.\nexport async function scanSimilar(conn: Connection, path: string, opts: { exclude: Set<string>; allowed?: Set<string>; k: number }, nativeScope = false): Promise<VectorSimilar[]> {\n const targetStmt = await conn.prepare('SELECT vector FROM embeddings WHERE \"path\" = ? AND vector IS NOT NULL ORDER BY chunk');\n const targetRows = (await targetStmt.all(path)) as Array<{ vector: Uint8Array }>;\n if (targetRows.length === 0) return [];\n // Each side's norm divides its own dot product, so both are taken once here rather than per pair.\n const target = sampleEvenly(targetRows).map((row) => {\n const v = new Int8Array(row.vector.buffer, row.vector.byteOffset, row.vector.byteLength);\n let norm = 0;\n for (let d = 0; d < v.length; d++) norm += v[d] * v[d];\n return { v, norm: Math.sqrt(norm) };\n });\n\n const scope = nativeScope ? ` AND \"path\" IN (SELECT \"path\" FROM ${NATIVE_VECTOR_SCOPE_TABLE})` : '';\n const stmt = await conn.prepare(`SELECT \"path\", vector FROM embeddings WHERE vector IS NOT NULL${scope}`);\n const rows = (await stmt.all()) as Array<{ path: string; vector: Uint8Array }>;\n const best = new Map<string, number>();\n for (const row of rows) {\n if (row.path === path || opts.exclude.has(row.path) || (opts.allowed && !opts.allowed.has(row.path))) continue;\n const other = new Int8Array(row.vector.buffer, row.vector.byteOffset, row.vector.byteLength);\n let otherNorm = 0;\n for (let d = 0; d < other.length; d++) otherNorm += other[d] * other[d];\n otherNorm = Math.sqrt(otherNorm);\n for (const t of target) {\n let dot = 0;\n const len = Math.min(t.v.length, other.length);\n for (let d = 0; d < len; d++) dot += t.v[d] * other[d];\n const score = t.norm === 0 || otherNorm === 0 ? 0 : dot / (t.norm * otherNorm);\n const existing = best.get(row.path);\n if (existing === undefined || score > existing) best.set(row.path, score);\n }\n }\n\n return [...best.entries()]\n .map(([p, score]) => ({ path: p, score }))\n .sort(compareVectorScores)\n .slice(0, opts.k)\n .map(({ path: p, score }) => ({ path: p, similarity: asCosine(score) }));\n}\n"],"names":["scanCandidates","scanSimilar","writeVectorBatch","conn","rows","length","runBatch","map","row","scale","vector","path","chunk","qv","storeDims","fetch","allowed","nativeScope","scope","stmt","queryNorm","d","best","q","dot","norm","score","existing","NATIVE_VECTOR_SCOPE_TABLE","prepare","all","Math","min","sqrt","Map","has","Int8Array","buffer","byteOffset","byteLength","get","set","lines","start_line","end_line","entries","value","sort","compareVectorScores","slice","similarity","asCosine","opts","targetStmt","targetRows","target","other","otherNorm","t","len","sampleEvenly","v","exclude","undefined","p","k"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/stages.ts"],"sourcesContent":["// Per-stage wall time for one reconcile, all on this thread's clock. Stages name work a build has\n// to do, never the function or file doing it, so the vocabulary outlives a pipeline refactor.\nexport const STAGES_VERSION = 's1';\n\n// Every stage outside the feature hooks, in execution order. Feature hooks add\n// `feature:<name>:<hook>` keys, so a new feature becomes visible without touching this list.\nexport const FIXED_STAGES = ['list', 'existing', 'parse', 'alter', 'added-recheck', 'fm-upsert', 'text-index', 'presets', 'vanished', 'meta'] as const;\n\nexport const FEATURE_HOOKS = ['remove', 'store', 'after'] as const;\n\nexport type FeatureHook = (typeof FEATURE_HOOKS)[number];\n\nexport interface Stages {\n version: string;\n totalMs: number;\n // The write transaction's own duration. It contains most of the spans below, so it is reported\n // beside them rather than among them, and never counts toward the sum.\n txMs: number;\n // Summed worker-side parseFile elapsed time inside `parse`: concurrent workers can make it\n // exceed the wall span, so it sits beside the spans like txMs and never counts toward the sum.\n parseWorkerMs: number;\n // Disjoint spans, so `totalMs` less their sum is time no stage claims.\n spans: Record<string, number>;\n}\n\nexport interface StageRecorder {\n time<T>(stage: string, fn: () => T | Promise<T>): Promise<T>;\n take(totalMs: number, txMs: number, parseWorkerMs?: number): Stages;\n}\n\nexport function featureStage(name: string, hook: FeatureHook): string {\n return `feature:${name}:${hook}`;\n}\n\nconst round = (ms: number): number => Math.round(ms * 10) / 10;\n\n// `featureNames` seeds this build's feature-hook keys, so the key set is a function of config\n// alone: a cold build (nothing to remove) and an incremental one report the same stages.\nexport function stageRecorder(featureNames: readonly string[] = []): StageRecorder {\n const spans = new Map<string, number>();\n for (const stage of FIXED_STAGES) spans.set(stage, 0);\n for (const name of featureNames) for (const hook of FEATURE_HOOKS) spans.set(featureStage(name, hook), 0);\n return {\n // A throw records nothing: an aborted reconcile must not report a partial stage as a complete one.\n async time(stage, fn) {\n const at = process.hrtime.bigint();\n const value = await fn();\n spans.set(stage, (spans.get(stage) ?? 0) + Number(process.hrtime.bigint() - at) / 1e6);\n return value;\n },\n // Every declared stage reports, 0 included, so a store that skips some work and a store that\n // does it cheaply read alike across a timeline. An absent `stages` is a build with no timers.\n take(totalMs, txMs, parseWorkerMs = 0) {\n const out: Record<string, number> = {};\n for (const [stage, ms] of spans) out[stage] = round(ms);\n return { version: STAGES_VERSION, totalMs: round(totalMs), txMs: round(txMs), parseWorkerMs: round(parseWorkerMs), spans: out };\n },\n };\n}\n\n// Time no stage claims: transaction commit, lock wait, and any cost added since without a timer.\n// A residual that grows across releases is the signal that this vocabulary stopped covering the build.\nexport function unaccountedMs(stages: Stages): number {\n let sum = 0;\n for (const ms of Object.values(stages.spans)) sum += ms;\n return round(stages.totalMs - sum);\n}\n"],"names":["FEATURE_HOOKS","FIXED_STAGES","STAGES_VERSION","featureStage","stageRecorder","unaccountedMs","name","hook","round","ms","Math","featureNames","spans","Map","stage","set","time","fn","at","value","process","hrtime","bigint","get","Number","take","totalMs","txMs","parseWorkerMs","out","version","stages","sum","Object","values"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/stages.ts"],"sourcesContent":["// Per-stage wall time for one reconcile, all on this thread's clock. Stages name work a build has\n// to do, never the function or file doing it, so the vocabulary outlives a pipeline refactor.\nexport const STAGES_VERSION = 's1';\n\n// Every stage outside the feature hooks, in execution order. Feature hooks add\n// `feature:<name>:<hook>` keys, so a new feature becomes visible without touching this list.\nexport const FIXED_STAGES = ['list', 'existing', 'parse', 'alter', 'added-recheck', 'fm-upsert', 'text-index', 'presets', 'vanished', 'meta'] as const;\n\nexport const FEATURE_HOOKS = ['remove', 'store', 'after'] as const;\n\nexport type FeatureHook = (typeof FEATURE_HOOKS)[number];\n\nexport interface Stages {\n version: string;\n totalMs: number;\n // The write transaction's own duration. It contains most of the spans below, so it is reported\n // beside them rather than among them, and never counts toward the sum.\n txMs: number;\n // Summed worker-side parseFile elapsed time inside `parse`: concurrent workers can make it\n // exceed the wall span, so it sits beside the spans like txMs and never counts toward the sum.\n parseWorkerMs: number;\n // Disjoint spans, so `totalMs` less their sum is time no stage claims.\n spans: Record<string, number>;\n}\n\nexport interface StageRecorder {\n time<T>(stage: string, fn: () => T | Promise<T>): Promise<T>;\n take(totalMs: number, txMs: number, parseWorkerMs?: number): Stages;\n}\n\nexport function featureStage(name: string, hook: FeatureHook): string {\n return `feature:${name}:${hook}`;\n}\n\nconst round = (ms: number): number => Math.round(ms * 10) / 10;\n\n// `featureNames` seeds this build's feature-hook keys, so the key set is a function of config\n// alone: a cold build (nothing to remove) and an incremental one report the same stages.\nexport function stageRecorder(featureNames: readonly string[] = []): StageRecorder {\n const spans = new Map<string, number>();\n for (const stage of FIXED_STAGES) spans.set(stage, 0);\n for (const name of featureNames) for (const hook of FEATURE_HOOKS) spans.set(featureStage(name, hook), 0);\n return {\n // A throw records nothing: an aborted reconcile must not report a partial stage as a complete one.\n async time(stage, fn) {\n const at = process.hrtime.bigint();\n const value = await fn();\n spans.set(stage, (spans.get(stage) ?? 0) + Number(process.hrtime.bigint() - at) / 1e6);\n return value;\n },\n // Every declared stage reports, 0 included, so a store that skips some work and a store that\n // does it cheaply read alike across a timeline. An absent `stages` is a build with no timers.\n take(totalMs, txMs, parseWorkerMs = 0) {\n const out: Record<string, number> = {};\n for (const [stage, ms] of spans) out[stage] = round(ms);\n return { version: STAGES_VERSION, totalMs: round(totalMs), txMs: round(txMs), parseWorkerMs: round(parseWorkerMs), spans: out };\n },\n };\n}\n\n// Time no stage claims: transaction commit, lock wait, and any cost added since without a timer.\n// A residual that grows across releases is the signal that this vocabulary stopped covering the build.\nexport function unaccountedMs(stages: Stages): number {\n let sum = 0;\n for (const ms of Object.values(stages.spans)) sum += ms;\n return round(stages.totalMs - sum);\n}\n"],"names":["FEATURE_HOOKS","FIXED_STAGES","STAGES_VERSION","featureStage","stageRecorder","unaccountedMs","name","hook","round","ms","Math","featureNames","spans","Map","stage","set","time","fn","at","value","process","hrtime","bigint","get","Number","take","totalMs","txMs","parseWorkerMs","out","version","stages","sum","Object","values"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/transaction.ts"],"sourcesContent":["// Store-agnostic joining transaction helper: node:sqlite and DuckDB both support only\n// BEGIN/COMMIT/ROLLBACK, no SAVEPOINT -- nesting joins the outer transaction, sharing one semantics through exec(sql).\ninterface ExecConnection {\n exec(sql: string): Promise<void>;\n}\n\ninterface TxState {\n depth: number;\n rollbackOnly: boolean;\n}\n\n// Keyed by connection, not a module singleton: two connections can coexist in one process\n// (e.g. watch.ts alongside a CLI query) and must not share depth.\nconst states = new WeakMap<ExecConnection, TxState>();\n\nfunction stateFor(conn: ExecConnection): TxState {\n let state = states.get(conn);\n if (!state) {\n state = { depth: 0, rollbackOnly: false };\n states.set(conn, state);\n }\n return state;\n}\n\nasync function enter(conn: ExecConnection, state: TxState, begin: string): Promise<void> {\n if (state.depth === 0) {\n await conn.exec(begin);\n state.rollbackOnly = false;\n }\n state.depth++;\n}\n\n// Reaching depth 0 still rollback-only means an inner scope failed and an enclosing catch\n// swallowed it; commit here would persist a partial write, so this rolls back and throws instead.\nasync function leaveOk(conn: ExecConnection, state: TxState): Promise<void> {\n state.depth--;\n if (state.depth > 0) return;\n if (state.rollbackOnly) {\n await conn.exec('ROLLBACK');\n throw new Error('transaction rolled back: a nested scope failed');\n }\n await conn.exec('COMMIT');\n}\n\nasync function leaveErr(conn: ExecConnection, state: TxState): Promise<void> {\n state.rollbackOnly = true;\n state.depth--;\n if (state.depth === 0) await conn.exec('ROLLBACK');\n}\n\n// A writer takes its lock at BEGIN rather than on first write: SQLite will not retry a deferred\n// transaction that read first and then upgrades, so busy_timeout never applies and the second\n// concurrent command fails outright instead of queueing. Reads keep plain BEGIN, or every snapshot\n// read (map, peek) would serialize against writers. DuckDB has no IMMEDIATE and passes nothing.\nexport const BEGIN_WRITE = 'BEGIN IMMEDIATE';\n\n// Depth-0 opens the transaction; a nested call joins it and issues no SQL of its own. The outermost\n// call owns COMMIT/ROLLBACK, so join semantics never differ by call site.\nexport async function withTransaction<T>(conn: ExecConnection, fn: () => Promise<T>, begin = 'BEGIN'): Promise<T> {\n const state = stateFor(conn);\n await enter(conn, state, begin);\n let result: T;\n try {\n result = await fn();\n } catch (err) {\n await leaveErr(conn, state);\n throw err;\n }\n await leaveOk(conn, state);\n return result;\n}\n"],"names":["BEGIN_WRITE","withTransaction","states","WeakMap","stateFor","conn","state","get","depth","rollbackOnly","set","enter","begin","exec","leaveOk","Error","leaveErr","fn","result","err"],"mappings":"AAAA,sFAAsF;AACtF,uHAAuH;;;;;;;;;;;;QAqD1GA;eAAAA;;QAISC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA/CtB,0FAA0F;AAC1F,kEAAkE;AAClE,IAAMC,SAAS,IAAIC;AAEnB,SAASC,SAASC,IAAoB;IACpC,IAAIC,QAAQJ,OAAOK,GAAG,CAACF;IACvB,IAAI,CAACC,OAAO;QACVA,QAAQ;YAAEE,OAAO;YAAGC,cAAc;QAAM;QACxCP,OAAOQ,GAAG,CAACL,MAAMC;IACnB;IACA,OAAOA;AACT;AAEA,SAAeK,MAAMN,IAAoB,EAAEC,KAAc,EAAEM,KAAa;;;;;yBAClEN,CAAAA,MAAME,KAAK,KAAK,CAAA,GAAhBF;;;;oBACF;;wBAAMD,KAAKQ,IAAI,CAACD;;;oBAAhB;oBACAN,MAAMG,YAAY,GAAG;;;oBAEvBH,MAAME,KAAK;;;;;;IACb;;AAEA,0FAA0F;AAC1F,kGAAkG;AAClG,SAAeM,QAAQT,IAAoB,EAAEC,KAAc;;;;;oBACzDA,MAAME,KAAK;oBACX,IAAIF,MAAME,KAAK,GAAG,GAAG;;;yBACjBF,MAAMG,YAAY,EAAlBH;;;;oBACF;;wBAAMD,KAAKQ,IAAI,CAAC;;;oBAAhB;oBACA,MAAM,IAAIE,MAAM;;oBAElB;;wBAAMV,KAAKQ,IAAI,CAAC;;;oBAAhB;;;;;;IACF;;AAEA,SAAeG,SAASX,IAAoB,EAAEC,KAAc;;;;;oBAC1DA,MAAMG,YAAY,GAAG;oBACrBH,MAAME,KAAK;yBACPF,CAAAA,MAAME,KAAK,KAAK,CAAA,GAAhBF;;;;oBAAmB;;wBAAMD,KAAKQ,IAAI,CAAC;;;oBAAhB;;;;;;;;IACzB;;AAMO,IAAMb,cAAc;AAIpB,SAAeC,gBAAmBI,IAAoB,EAAEY,EAAoB;QAAEL,QAAAA,iEAAQ;;YACrFN,OAEFY,QAGKC;;;;oBALHb,QAAQF,SAASC;oBACvB;;wBAAMM,MAAMN,MAAMC,OAAOM;;;oBAAzB;;;;;;;;;oBAGW;;wBAAMK;;;oBAAfC,SAAS;;;;;;oBACFC;oBACP;;wBAAMH,SAASX,MAAMC;;;oBAArB;oBACA,MAAMa;;oBAER;;wBAAML,QAAQT,MAAMC;;;oBAApB;oBACA;;wBAAOY;;;;IACT"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/transaction.ts"],"sourcesContent":["// Store-agnostic joining transaction helper: node:sqlite and DuckDB both support only\n// BEGIN/COMMIT/ROLLBACK, no SAVEPOINT -- nesting joins the outer transaction, sharing one semantics through exec(sql).\ninterface ExecConnection {\n exec(sql: string): Promise<void>;\n}\n\ninterface TxState {\n depth: number;\n rollbackOnly: boolean;\n}\n\n// Keyed by connection, not a module singleton: two connections can coexist in one process\n// (e.g. watch.ts alongside a CLI query) and must not share depth.\nconst states = new WeakMap<ExecConnection, TxState>();\n\nfunction stateFor(conn: ExecConnection): TxState {\n let state = states.get(conn);\n if (!state) {\n state = { depth: 0, rollbackOnly: false };\n states.set(conn, state);\n }\n return state;\n}\n\nasync function enter(conn: ExecConnection, state: TxState, begin: string): Promise<void> {\n if (state.depth === 0) {\n await conn.exec(begin);\n state.rollbackOnly = false;\n }\n state.depth++;\n}\n\n// Reaching depth 0 still rollback-only means an inner scope failed and an enclosing catch\n// swallowed it; commit here would persist a partial write, so this rolls back and throws instead.\nasync function leaveOk(conn: ExecConnection, state: TxState): Promise<void> {\n state.depth--;\n if (state.depth > 0) return;\n if (state.rollbackOnly) {\n await conn.exec('ROLLBACK');\n throw new Error('transaction rolled back: a nested scope failed');\n }\n await conn.exec('COMMIT');\n}\n\nasync function leaveErr(conn: ExecConnection, state: TxState): Promise<void> {\n state.rollbackOnly = true;\n state.depth--;\n if (state.depth === 0) await conn.exec('ROLLBACK');\n}\n\n// A writer takes its lock at BEGIN rather than on first write: SQLite will not retry a deferred\n// transaction that read first and then upgrades, so busy_timeout never applies and the second\n// concurrent command fails outright instead of queueing. Reads keep plain BEGIN, or every snapshot\n// read (map, peek) would serialize against writers. DuckDB has no IMMEDIATE and passes nothing.\nexport const BEGIN_WRITE = 'BEGIN IMMEDIATE';\n\n// Depth-0 opens the transaction; a nested call joins it and issues no SQL of its own. The outermost\n// call owns COMMIT/ROLLBACK, so join semantics never differ by call site.\nexport async function withTransaction<T>(conn: ExecConnection, fn: () => Promise<T>, begin = 'BEGIN'): Promise<T> {\n const state = stateFor(conn);\n await enter(conn, state, begin);\n let result: T;\n try {\n result = await fn();\n } catch (err) {\n await leaveErr(conn, state);\n throw err;\n }\n await leaveOk(conn, state);\n return result;\n}\n"],"names":["BEGIN_WRITE","withTransaction","states","WeakMap","stateFor","conn","state","get","depth","rollbackOnly","set","enter","begin","exec","leaveOk","Error","leaveErr","fn","result","err"],"mappings":"AAAA,sFAAsF;AACtF,uHAAuH;;;;;;;;;;;;QAqD1GA;eAAAA;;QAISC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA/CtB,0FAA0F;AAC1F,kEAAkE;AAClE,IAAMC,SAAS,IAAIC;AAEnB,SAASC,SAASC,IAAoB;IACpC,IAAIC,QAAQJ,OAAOK,GAAG,CAACF;IACvB,IAAI,CAACC,OAAO;QACVA,QAAQ;YAAEE,OAAO;YAAGC,cAAc;QAAM;QACxCP,OAAOQ,GAAG,CAACL,MAAMC;IACnB;IACA,OAAOA;AACT;AAEA,SAAeK,MAAMN,IAAoB,EAAEC,KAAc,EAAEM,KAAa;;;;;yBAClEN,CAAAA,MAAME,KAAK,KAAK,CAAA,GAAhBF;;;;oBACF;;wBAAMD,KAAKQ,IAAI,CAACD;;;oBAAhB;oBACAN,MAAMG,YAAY,GAAG;;;oBAEvBH,MAAME,KAAK;;;;;;IACb;;AAEA,0FAA0F;AAC1F,kGAAkG;AAClG,SAAeM,QAAQT,IAAoB,EAAEC,KAAc;;;;;oBACzDA,MAAME,KAAK;oBACX,IAAIF,MAAME,KAAK,GAAG,GAAG;;;yBACjBF,MAAMG,YAAY,EAAlBH;;;;oBACF;;wBAAMD,KAAKQ,IAAI,CAAC;;;oBAAhB;oBACA,MAAM,IAAIE,MAAM;;oBAElB;;wBAAMV,KAAKQ,IAAI,CAAC;;;oBAAhB;;;;;;IACF;;AAEA,SAAeG,SAASX,IAAoB,EAAEC,KAAc;;;;;oBAC1DA,MAAMG,YAAY,GAAG;oBACrBH,MAAME,KAAK;yBACPF,CAAAA,MAAME,KAAK,KAAK,CAAA,GAAhBF;;;;oBAAmB;;wBAAMD,KAAKQ,IAAI,CAAC;;;oBAAhB;;;;;;;;IACzB;;AAMO,IAAMb,cAAc;AAIpB,SAAeC,gBAAmBI,IAAoB,EAAEY,EAAoB;QAAEL,QAAAA,iEAAQ;;YACrFN,OAEFY,QAGKC;;;;oBALHb,QAAQF,SAASC;oBACvB;;wBAAMM,MAAMN,MAAMC,OAAOM;;;oBAAzB;;;;;;;;;oBAGW;;wBAAMK;;;oBAAfC,SAAS;;;;;;oBACFC;oBACP;;wBAAMH,SAASX,MAAMC;;;oBAArB;oBACA,MAAMa;;oBAER;;wBAAML,QAAQT,MAAMC;;;oBAApB;oBACA;;wBAAOY;;;;IACT"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/turso/connection.ts"],"sourcesContent":["import { stat } from 'node:fs/promises';\nimport { setImmediate } from 'node:timers/promises';\nimport type { Database } from '@tursodatabase/database';\nimport { rewriteInsert } from '../batch.ts';\nimport { setMeta } from '../shared.ts';\nimport { BEGIN_WRITE, withTransaction } from '../transaction.ts';\nimport type { Connection, RunResult, Statement } from '../types.ts';\nimport { CONNECT_OPTS, tursoApi } from './native.ts';\nimport { rewriteFunctions } from './sql-functions.ts';\n\n// The client's own Statement class isn't re-exported by name from '@tursodatabase/database',\n// so its type is derived structurally from Database.prepare()'s return type instead.\ntype TursoStatement = Awaited<ReturnType<Database['prepare']>>;\n\n// Bound native multi-row compilation work; this is not Turso's variable-count limit.\nexport const INSERT_BIND_BUDGET = 8192;\n\nasync function closeStatement(stmt: TursoStatement, failed: boolean, failure: unknown): Promise<void> {\n try {\n await stmt.close();\n } catch (cleanup) {\n if (failed) throw new AggregateError([failure, cleanup], 'Turso statement execution and cleanup failed');\n throw cleanup;\n } finally {\n // Native result cleanup can wait on the event loop even after the statement is finalized.\n await setImmediate();\n }\n}\n\n// Native statements are finalized after execution. Reusing the portable statement prepares\n// it again; column metadata remains available after execution without retaining native state.\nclass TursoStatementWrapper implements Statement {\n private stmt: TursoStatement | null;\n private readonly metadata: Array<{ name: string }>;\n private readBigInts = false;\n private readonly db: Database;\n private readonly sql: string;\n\n constructor(db: Database, sql: string, stmt: TursoStatement) {\n this.db = db;\n this.sql = sql;\n this.stmt = stmt;\n this.metadata = stmt.columns();\n }\n\n private async acquire(): Promise<TursoStatement> {\n const retained = this.stmt;\n this.stmt = null;\n const stmt = retained ?? (await this.db.prepare(this.sql));\n try {\n stmt.safeIntegers(this.readBigInts);\n } catch (error) {\n await closeStatement(stmt, true, error);\n throw error;\n }\n return stmt;\n }\n\n private async execute<T>(operation: (stmt: TursoStatement) => Promise<T>): Promise<T> {\n const stmt = await this.acquire();\n let failed = false;\n let failure: unknown;\n try {\n return await operation(stmt);\n } catch (error) {\n failed = true;\n failure = error;\n throw error;\n } finally {\n await closeStatement(stmt, failed, failure);\n }\n }\n\n async run(...params: unknown[]): Promise<RunResult> {\n return this.execute((stmt) => stmt.run(...params));\n }\n\n async get(...params: unknown[]): Promise<unknown> {\n return this.execute((stmt) => stmt.get(...params));\n }\n\n async all(...params: unknown[]): Promise<unknown[]> {\n return this.execute((stmt) => stmt.all(...params));\n }\n\n async *iterate(...params: unknown[]): AsyncIterable<unknown> {\n const stmt = await this.acquire();\n let failed = false;\n let failure: unknown;\n try {\n yield* stmt.iterate(...params);\n } catch (error) {\n failed = true;\n failure = error;\n throw error;\n } finally {\n await closeStatement(stmt, failed, failure);\n }\n }\n\n columns(): Array<{ name: string }> {\n return this.metadata;\n }\n\n setReadBigInts(enabled: boolean): void {\n this.readBigInts = enabled;\n }\n}\n\n// This client leaves the WAL behind for the next opener, where node:sqlite checkpoints on the last\n// close, so a tree reconciled over and over grows one without bound. Best-effort: close must not throw.\nexport async function checkpointWal(db: Database): Promise<void> {\n try {\n await db.exec('PRAGMA wal_checkpoint(TRUNCATE)');\n } catch (err) {\n console.error(`sense: turso WAL checkpoint failed, the -wal file will keep growing until one succeeds: ${(err as Error).message}`);\n }\n}\n\n// The main cache file's path, or null when unresolvable. The store holds a Database and\n// Connection, not a path (PLAN 3.52), so the path is read from the database itself.\nexport async function cacheFilePath(conn: Connection): Promise<string | null> {\n const rows = (await (await conn.prepare('PRAGMA database_list')).all()) as Array<{ name: string; file: string }>;\n return rows.find((r) => r.name === 'main')?.file || null;\n}\n\nexport async function fileSize(path: string): Promise<number | null> {\n try {\n return (await stat(path)).size;\n } catch {\n return null;\n }\n}\n\n// Reclaims turso#8170's FTS space amplification (PLAN 3.41), on a throwaway connection after the\n// store's own has closed: `vacuum` doubles incremental reconcile cost merely by being enabled (3.54).\nexport async function reclaimSpace(path: string): Promise<void> {\n try {\n const turso = await tursoApi();\n const db = await turso.connect(path, { ...CONNECT_OPTS, experimental: [...CONNECT_OPTS.experimental, 'vacuum'] });\n try {\n await db.exec('VACUUM');\n const size = await fileSize(path);\n // Recorded here, not by the caller: this connection is the only one still open on the file.\n if (size !== null) await setMeta(createConnection(db), 'compact_size', String(size));\n await checkpointWal(db);\n } finally {\n await db.close();\n }\n } catch (err) {\n console.error(`sense: turso VACUUM failed, the cache will keep the space until one succeeds: ${(err as Error).message}`);\n }\n}\n\nexport function createConnection(db: Database): Connection {\n const conn: Connection = {\n async exec(sql: string): Promise<void> {\n await db.exec(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n const rewritten = rewriteFunctions(sql);\n const stmt = await db.prepare(rewritten);\n try {\n return new TursoStatementWrapper(db, rewritten, stmt);\n } catch (error) {\n await closeStatement(stmt, true, error);\n throw error;\n }\n },\n // Fold INSERTs into bounded multi-row statements in one transaction. UPDATE/DELETE keep\n // the per-row loop; each native statement owns its finalization and cleanup turn.\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n if (paramRows.length === 0) return;\n await withTransaction(\n conn,\n async () => {\n const shape = rewriteInsert(sql, 1);\n const batchRows = shape ? Math.max(1, Math.floor(INSERT_BIND_BUDGET / shape.width)) : paramRows.length;\n for (let offset = 0; offset < paramRows.length; offset += batchRows) {\n const rows = shape ? paramRows.slice(offset, offset + batchRows) : paramRows;\n const rewritten = shape ? rewriteInsert(sql, rows.length) : null;\n const stmt = await db.prepare(rewritten?.sql ?? sql);\n let failed = false;\n let failure: unknown;\n try {\n if (rewritten) {\n // Pass one array: spreading a wide tuple can exceed the JS argument limit.\n await stmt.run(rows.flat());\n } else {\n for (const row of rows) await stmt.run(row);\n }\n } catch (error) {\n failed = true;\n failure = error;\n throw error;\n } finally {\n await closeStatement(stmt, failed, failure);\n }\n }\n },\n BEGIN_WRITE\n );\n },\n };\n return conn;\n}\n"],"names":["INSERT_BIND_BUDGET","cacheFilePath","checkpointWal","createConnection","fileSize","reclaimSpace","closeStatement","stmt","failed","failure","cleanup","close","AggregateError","setImmediate","TursoStatementWrapper","db","sql","readBigInts","metadata","columns","acquire","retained","error","prepare","safeIntegers","execute","operation","run","params","get","all","iterate","setReadBigInts","enabled","err","exec","console","message","conn","rows","find","r","name","file","path","stat","size","turso","tursoApi","connect","CONNECT_OPTS","experimental","setMeta","String","rewritten","rewriteFunctions","runBatch","paramRows","length","withTransaction","shape","batchRows","offset","row","rewriteInsert","Math","max","floor","width","slice","flat","BEGIN_WRITE"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/open-source/ai/sensemaking/src/store/turso/connection.ts"],"sourcesContent":["import { stat } from 'node:fs/promises';\nimport { setImmediate } from 'node:timers/promises';\nimport type { Database } from '@tursodatabase/database';\nimport { rewriteInsert } from '../batch.ts';\nimport { setMeta } from '../shared.ts';\nimport { BEGIN_WRITE, withTransaction } from '../transaction.ts';\nimport type { Connection, RunResult, Statement } from '../types.ts';\nimport { CONNECT_OPTS, tursoApi } from './native.ts';\nimport { rewriteFunctions } from './sql-functions.ts';\n\n// The client's own Statement class isn't re-exported by name from '@tursodatabase/database',\n// so its type is derived structurally from Database.prepare()'s return type instead.\ntype TursoStatement = Awaited<ReturnType<Database['prepare']>>;\n\n// Bound native multi-row compilation work; this is not Turso's variable-count limit.\nexport const INSERT_BIND_BUDGET = 8192;\n\nasync function closeStatement(stmt: TursoStatement, failed: boolean, failure: unknown): Promise<void> {\n try {\n await stmt.close();\n } catch (cleanup) {\n if (failed) throw new AggregateError([failure, cleanup], 'Turso statement execution and cleanup failed');\n throw cleanup;\n } finally {\n // Native result cleanup can wait on the event loop even after the statement is finalized.\n await setImmediate();\n }\n}\n\n// Native statements are finalized after execution. Reusing the portable statement prepares\n// it again; column metadata remains available after execution without retaining native state.\nclass TursoStatementWrapper implements Statement {\n private stmt: TursoStatement | null;\n private readonly metadata: Array<{ name: string }>;\n private readBigInts = false;\n private readonly db: Database;\n private readonly sql: string;\n\n constructor(db: Database, sql: string, stmt: TursoStatement) {\n this.db = db;\n this.sql = sql;\n this.stmt = stmt;\n this.metadata = stmt.columns();\n }\n\n private async acquire(): Promise<TursoStatement> {\n const retained = this.stmt;\n this.stmt = null;\n const stmt = retained ?? (await this.db.prepare(this.sql));\n try {\n stmt.safeIntegers(this.readBigInts);\n } catch (error) {\n await closeStatement(stmt, true, error);\n throw error;\n }\n return stmt;\n }\n\n private async execute<T>(operation: (stmt: TursoStatement) => Promise<T>): Promise<T> {\n const stmt = await this.acquire();\n let failed = false;\n let failure: unknown;\n try {\n return await operation(stmt);\n } catch (error) {\n failed = true;\n failure = error;\n throw error;\n } finally {\n await closeStatement(stmt, failed, failure);\n }\n }\n\n async run(...params: unknown[]): Promise<RunResult> {\n return this.execute((stmt) => stmt.run(...params));\n }\n\n async get(...params: unknown[]): Promise<unknown> {\n return this.execute((stmt) => stmt.get(...params));\n }\n\n async all(...params: unknown[]): Promise<unknown[]> {\n return this.execute((stmt) => stmt.all(...params));\n }\n\n async *iterate(...params: unknown[]): AsyncIterable<unknown> {\n const stmt = await this.acquire();\n let failed = false;\n let failure: unknown;\n try {\n yield* stmt.iterate(...params);\n } catch (error) {\n failed = true;\n failure = error;\n throw error;\n } finally {\n await closeStatement(stmt, failed, failure);\n }\n }\n\n columns(): Array<{ name: string }> {\n return this.metadata;\n }\n\n setReadBigInts(enabled: boolean): void {\n this.readBigInts = enabled;\n }\n}\n\n// This client leaves the WAL behind for the next opener, where node:sqlite checkpoints on the last\n// close, so a tree reconciled over and over grows one without bound. Best-effort: close must not throw.\nexport async function checkpointWal(db: Database): Promise<void> {\n try {\n await db.exec('PRAGMA wal_checkpoint(TRUNCATE)');\n } catch (err) {\n console.error(`sense: turso WAL checkpoint failed, the -wal file will keep growing until one succeeds: ${(err as Error).message}`);\n }\n}\n\n// The main cache file's path, or null when unresolvable. The store holds a Database and\n// Connection, not a path (PLAN 3.52), so the path is read from the database itself.\nexport async function cacheFilePath(conn: Connection): Promise<string | null> {\n const rows = (await (await conn.prepare('PRAGMA database_list')).all()) as Array<{ name: string; file: string }>;\n return rows.find((r) => r.name === 'main')?.file || null;\n}\n\nexport async function fileSize(path: string): Promise<number | null> {\n try {\n return (await stat(path)).size;\n } catch {\n return null;\n }\n}\n\n// Reclaims turso#8170's FTS space amplification (PLAN 3.41), on a throwaway connection after the\n// store's own has closed: `vacuum` doubles incremental reconcile cost merely by being enabled (3.54).\nexport async function reclaimSpace(path: string): Promise<void> {\n try {\n const turso = await tursoApi();\n const db = await turso.connect(path, { ...CONNECT_OPTS, experimental: [...CONNECT_OPTS.experimental, 'vacuum'] });\n try {\n await db.exec('VACUUM');\n const size = await fileSize(path);\n // Recorded here, not by the caller: this connection is the only one still open on the file.\n if (size !== null) await setMeta(createConnection(db), 'compact_size', String(size));\n await checkpointWal(db);\n } finally {\n await db.close();\n }\n } catch (err) {\n console.error(`sense: turso VACUUM failed, the cache will keep the space until one succeeds: ${(err as Error).message}`);\n }\n}\n\nexport function createConnection(db: Database): Connection {\n const conn: Connection = {\n async exec(sql: string): Promise<void> {\n await db.exec(sql);\n },\n async prepare(sql: string): Promise<Statement> {\n const rewritten = rewriteFunctions(sql);\n const stmt = await db.prepare(rewritten);\n try {\n return new TursoStatementWrapper(db, rewritten, stmt);\n } catch (error) {\n await closeStatement(stmt, true, error);\n throw error;\n }\n },\n // Fold INSERTs into bounded multi-row statements in one transaction. UPDATE/DELETE keep\n // the per-row loop; each native statement owns its finalization and cleanup turn.\n async runBatch(sql: string, paramRows: unknown[][]): Promise<void> {\n if (paramRows.length === 0) return;\n await withTransaction(\n conn,\n async () => {\n const shape = rewriteInsert(sql, 1);\n const batchRows = shape ? Math.max(1, Math.floor(INSERT_BIND_BUDGET / shape.width)) : paramRows.length;\n for (let offset = 0; offset < paramRows.length; offset += batchRows) {\n const rows = shape ? paramRows.slice(offset, offset + batchRows) : paramRows;\n const rewritten = shape ? rewriteInsert(sql, rows.length) : null;\n const stmt = await db.prepare(rewritten?.sql ?? sql);\n let failed = false;\n let failure: unknown;\n try {\n if (rewritten) {\n // Pass one array: spreading a wide tuple can exceed the JS argument limit.\n await stmt.run(rows.flat());\n } else {\n for (const row of rows) await stmt.run(row);\n }\n } catch (error) {\n failed = true;\n failure = error;\n throw error;\n } finally {\n await closeStatement(stmt, failed, failure);\n }\n }\n },\n BEGIN_WRITE\n );\n },\n };\n return conn;\n}\n"],"names":["INSERT_BIND_BUDGET","cacheFilePath","checkpointWal","createConnection","fileSize","reclaimSpace","closeStatement","stmt","failed","failure","cleanup","close","AggregateError","setImmediate","TursoStatementWrapper","db","sql","readBigInts","metadata","columns","acquire","retained","error","prepare","safeIntegers","execute","operation","run","params","get","all","iterate","setReadBigInts","enabled","err","exec","console","message","conn","rows","find","r","name","file","path","stat","size","turso","tursoApi","connect","CONNECT_OPTS","experimental","setMeta","String","rewritten","rewriteFunctions","runBatch","paramRows","length","withTransaction","shape","batchRows","offset","row","rewriteInsert","Math","max","floor","width","slice","flat","BEGIN_WRITE"],"mappings":"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"}