sensemaking 0.21.1 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/chunk/group.js +13 -9
  3. package/dist/cjs/chunk/group.js.map +1 -1
  4. package/dist/cjs/commands/search.js +1 -1
  5. package/dist/cjs/commands/search.js.map +1 -1
  6. package/dist/cjs/index.d.cts +1 -1
  7. package/dist/cjs/index.d.ts +1 -1
  8. package/dist/cjs/index.js.map +1 -1
  9. package/dist/cjs/scan/pool.d.cts +1 -0
  10. package/dist/cjs/scan/pool.d.ts +1 -0
  11. package/dist/cjs/scan/pool.js +2 -1
  12. package/dist/cjs/scan/pool.js.map +1 -1
  13. package/dist/cjs/scan/reparse.d.cts +1 -0
  14. package/dist/cjs/scan/reparse.d.ts +1 -0
  15. package/dist/cjs/scan/reparse.js +6 -3
  16. package/dist/cjs/scan/reparse.js.map +1 -1
  17. package/dist/cjs/store/builder.d.cts +2 -0
  18. package/dist/cjs/store/builder.d.ts +2 -0
  19. package/dist/cjs/store/builder.js.map +1 -1
  20. package/dist/cjs/store/index.d.cts +1 -5
  21. package/dist/cjs/store/index.d.ts +1 -5
  22. package/dist/cjs/store/index.js +9 -46
  23. package/dist/cjs/store/index.js.map +1 -1
  24. package/dist/cjs/store/lock-wait.d.cts +2 -0
  25. package/dist/cjs/store/lock-wait.d.ts +2 -0
  26. package/dist/cjs/store/lock-wait.js +51 -0
  27. package/dist/cjs/store/lock-wait.js.map +1 -0
  28. package/dist/cjs/store/open.d.cts +2 -4
  29. package/dist/cjs/store/open.d.ts +2 -4
  30. package/dist/cjs/store/open.js +29 -66
  31. package/dist/cjs/store/open.js.map +1 -1
  32. package/dist/cjs/store/reconcile.d.cts +2 -0
  33. package/dist/cjs/store/reconcile.d.ts +2 -0
  34. package/dist/cjs/store/reconcile.js +407 -255
  35. package/dist/cjs/store/reconcile.js.map +1 -1
  36. package/dist/cjs/store/sqlite/lexical.js +1 -1
  37. package/dist/cjs/store/sqlite/lexical.js.map +1 -1
  38. package/dist/cjs/store/sqlite/store.js +0 -1
  39. package/dist/cjs/store/sqlite/store.js.map +1 -1
  40. package/dist/cjs/store/stages.d.cts +18 -0
  41. package/dist/cjs/store/stages.d.ts +18 -0
  42. package/dist/cjs/store/stages.js +372 -0
  43. package/dist/cjs/store/stages.js.map +1 -0
  44. package/dist/cjs/store/turso/store.js.map +1 -1
  45. package/dist/cjs/store/types.d.cts +1 -1
  46. package/dist/cjs/store/types.d.ts +1 -1
  47. package/dist/cjs/store/types.js +0 -1
  48. package/dist/cjs/store/types.js.map +1 -1
  49. package/dist/cjs/text/segment.js +7 -5
  50. package/dist/cjs/text/segment.js.map +1 -1
  51. package/dist/cjs/watch.js +162 -107
  52. package/dist/cjs/watch.js.map +1 -1
  53. package/dist/cjs/workers/parse.d.cts +1 -0
  54. package/dist/cjs/workers/parse.d.ts +1 -0
  55. package/dist/cjs/workers/parse.js +4 -1
  56. package/dist/cjs/workers/parse.js.map +1 -1
  57. package/dist/esm/chunk/group.js +13 -9
  58. package/dist/esm/chunk/group.js.map +1 -1
  59. package/dist/esm/commands/search.js +1 -1
  60. package/dist/esm/commands/search.js.map +1 -1
  61. package/dist/esm/index.d.ts +1 -1
  62. package/dist/esm/index.js.map +1 -1
  63. package/dist/esm/scan/pool.d.ts +1 -0
  64. package/dist/esm/scan/pool.js +2 -1
  65. package/dist/esm/scan/pool.js.map +1 -1
  66. package/dist/esm/scan/reparse.d.ts +1 -0
  67. package/dist/esm/scan/reparse.js +5 -2
  68. package/dist/esm/scan/reparse.js.map +1 -1
  69. package/dist/esm/store/builder.d.ts +2 -0
  70. package/dist/esm/store/builder.js.map +1 -1
  71. package/dist/esm/store/index.d.ts +1 -5
  72. package/dist/esm/store/index.js +6 -28
  73. package/dist/esm/store/index.js.map +1 -1
  74. package/dist/esm/store/lock-wait.d.ts +2 -0
  75. package/dist/esm/store/lock-wait.js +36 -0
  76. package/dist/esm/store/lock-wait.js.map +1 -0
  77. package/dist/esm/store/open.d.ts +2 -4
  78. package/dist/esm/store/open.js +17 -32
  79. package/dist/esm/store/open.js.map +1 -1
  80. package/dist/esm/store/reconcile.d.ts +2 -0
  81. package/dist/esm/store/reconcile.js +72 -44
  82. package/dist/esm/store/reconcile.js.map +1 -1
  83. package/dist/esm/store/sqlite/lexical.js +1 -1
  84. package/dist/esm/store/sqlite/lexical.js.map +1 -1
  85. package/dist/esm/store/sqlite/store.js +0 -1
  86. package/dist/esm/store/sqlite/store.js.map +1 -1
  87. package/dist/esm/store/stages.d.ts +18 -0
  88. package/dist/esm/store/stages.js +63 -0
  89. package/dist/esm/store/stages.js.map +1 -0
  90. package/dist/esm/store/turso/store.js +1 -1
  91. package/dist/esm/store/turso/store.js.map +1 -1
  92. package/dist/esm/store/types.d.ts +1 -1
  93. package/dist/esm/store/types.js +0 -1
  94. package/dist/esm/store/types.js.map +1 -1
  95. package/dist/esm/text/segment.js +7 -5
  96. package/dist/esm/text/segment.js.map +1 -1
  97. package/dist/esm/watch.js +63 -38
  98. package/dist/esm/watch.js.map +1 -1
  99. package/dist/esm/workers/parse.d.ts +1 -0
  100. package/dist/esm/workers/parse.js +4 -1
  101. package/dist/esm/workers/parse.js.map +1 -1
  102. package/package.json +1 -1
  103. package/skills/sense/SKILL.md +1 -1
  104. package/skills/sense-setup/SKILL.md +1 -1
@@ -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 { getColumns, quoteIdent } from './shared.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 async function reconcile(conn: Connection, cfg: Config, baseDir: string, dialect: ReconcileDialect, pool?: ParsePool, forcedPaths?: ReadonlySet<string>): Promise<{ parsed: number; warnings: string[] }> {\n const files = listFiles(cfg, baseDir);\n const currentSet = new Set(files.map((f) => f.relPath));\n\n const existingStmt = await conn.prepare('SELECT \"path\", \"_mtime\", \"_size\" FROM frontmatter');\n const existingRows = (await existingStmt.all()) as Array<{ path: string; _mtime: number; _size: number }>;\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) return { parsed: 0, warnings: [] };\n\n const features = activeFeatures(cfg);\n const seenColumns = await getColumns(conn);\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 const { docs: parsedDocs, warnings, newColumns } = await reparseFiles(toReparse, features, cfg, seenColumns, report.tick, { pool });\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 const txStart = Date.now();\n await withTransaction(\n conn,\n async () => {\n // Re-read inside the write transaction: newColumns came from a read taken before it opened, so a\n // concurrent reconcile may have added some of them since. ALTER has no IF NOT EXISTS.\n const present = await getColumns(conn);\n const missingColumns = newColumns.filter((col) => !present.has(col));\n if (missingColumns.length > 0) await dialect.addColumns(conn, missingColumns);\n\n // Revalidated once the lock is held, before this process's own frontmatter upsert below:\n // `added` came from a path read taken before this transaction's lock, so a path still\n // called \"added\" here may already have a content row from a concurrent reconcile that\n // committed while this one waited. One SELECT, not a DELETE per added file -- with no\n // contention it returns the same set `existing` already ruled out, so nothing extra clears.\n let contentTouched = touched;\n if (added.length > 0) {\n const currentPathsStmt = await conn.prepare('SELECT \"path\" FROM frontmatter');\n const currentPaths = new Set(((await currentPathsStmt.all()) as Array<{ path: string }>).map((r) => r.path));\n const staleAdded = added.filter((p) => currentPaths.has(p));\n if (staleAdded.length > 0) contentTouched = [...touched, ...staleAdded];\n }\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 // Written per parse, unlike _rank, which a feature pass owns and the upsert skips.\n if (col === '_parse_error') return doc.parseError;\n return doc.data[col] ?? null;\n });\n // A path in `added` has no existing frontmatter row, so it can never conflict: where a\n // dialect offers a faster append-only path (insertNew), only the rest go through the upsert.\n if (dialect.insertNew) {\n const newDocs = parsedDocs.filter((d) => addedSet.has(d.relPath));\n const updateDocs = parsedDocs.filter((d) => !addedSet.has(d.relPath));\n if (newDocs.length > 0) await dialect.insertNew(conn, 'frontmatter', writableColumns, newDocs.map(toRow));\n if (updateDocs.length > 0) await conn.runBatch(insertSql, updateDocs.map(toRow));\n } else {\n await conn.runBatch(insertSql, parsedDocs.map(toRow));\n }\n }\n\n // After the upsert, so every doc already has the frontmatter row sqlite's content rowid\n // couples to. ON CONFLICT DO UPDATE preserves that rowid, so a reparse keeps its identity.\n await dialect.reconcileContent(conn, contentTouched, parsedDocs, delta, cfg);\n\n // A preset edit forces a full rebuild, so an unchanged doc's coverage is already correct;\n // new docs have nothing to clear, which keeps cold builds linear.\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 // DO NOTHING, not a bare INSERT: the added/touched split above comes from a read taken\n // before this transaction's lock, so a path this process calls \"added\" can already have\n // its (path, preset) row committed by a concurrent reconcile -- the row would be identical either way.\n if (presetRows.length > 0) await conn.runBatch('INSERT INTO preset_files (\"path\", preset) VALUES (?, ?) ON CONFLICT(\"path\", preset) DO NOTHING', presetRows);\n\n // Before the feature hooks, never after: rank's afterReconcile reads frontmatter as PageRank's\n // node set, so a lingering vanished row would dilute rank mass across every surviving note.\n if (vanished.length > 0)\n await conn.runBatch(\n 'DELETE FROM frontmatter WHERE \"path\" = ?',\n vanished.map((p) => [p])\n );\n\n if (touched.length > 0) for (const feature of features) await 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 feature.store?.(conn, docsForFeature, delta);\n }\n for (const feature of features) await feature.afterReconcile?.(conn, delta);\n },\n dialect.beginMode()\n );\n\n const durationMs = Date.now() - txStart;\n if (dialect.recordDuration) await dialect.recordDuration(conn, durationMs);\n\n return { parsed: parsedDocs.length, warnings };\n}\n"],"names":["CORE_FRONTMATTER_COLUMNS","reconcile","Set","conn","cfg","baseDir","dialect","pool","forcedPaths","files","currentSet","existingStmt","existingRows","existing","vanished","toReparse","features","seenColumns","report","parsedDocs","warnings","newColumns","col","allColumns","writableColumns","insertSql","added","delta","addedSet","reparsedExisting","touched","txStart","durationMs","listFiles","map","f","relPath","prepare","all","Map","r","path","filter","has","row","get","_mtime","mtimeMs","_size","size","length","parsed","activeFeatures","getColumns","progress","reparseFiles","tick","docs","finish","add","checkColumnLimit","c","RESERVED_COLUMNS","quoteIdent","join","reparsed","d","p","Date","now","withTransaction","feature","present","missingColumns","contentTouched","currentPathsStmt","currentPaths","staleAdded","toRow","newDocs","updateDocs","presetRows","doc","presetName","addColumns","ctimeMs","parseError","data","insertNew","runBatch","reconcileContent","presets","push","remove","docsForFeature","extracted","name","store","afterReconcile","beginMode","recordDuration"],"mappings":"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"}
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 { getColumns, quoteIdent } from './shared.ts';\nimport { featureStage, 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 async function reconcile(conn: Connection, cfg: Config, baseDir: string, dialect: ReconcileDialect, pool?: ParsePool, forcedPaths?: ReadonlySet<string>): Promise<{ parsed: number; warnings: string[]; stages: Stages }> {\n const start = process.hrtime.bigint();\n const features = activeFeatures(cfg);\n const stages = stageRecorder(features.map((f) => f.name));\n const elapsed = () => Number(process.hrtime.bigint() - start) / 1e6;\n const files = await stages.time('list', () => listFiles(cfg, baseDir));\n const currentSet = new Set(files.map((f) => f.relPath));\n\n const existingRows = await stages.time('existing', async () => {\n const existingStmt = await conn.prepare('SELECT \"path\", \"_mtime\", \"_size\" FROM frontmatter');\n return (await existingStmt.all()) as Array<{ path: string; _mtime: number; _size: number }>;\n });\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) return { parsed: 0, warnings: [], stages: stages.take(elapsed(), 0) };\n\n const seenColumns = await getColumns(conn);\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 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 const txStart = Date.now();\n await withTransaction(\n conn,\n async () => {\n // Re-read inside the write transaction: newColumns came from a read taken before it opened, so a\n // concurrent reconcile may have added some of them since. ALTER has no IF NOT EXISTS.\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 // Revalidated once the lock is held, before this process's own frontmatter upsert below:\n // `added` came from a path read taken before this transaction's lock, so a path still\n // called \"added\" here may already have a content row from a concurrent reconcile that\n // committed while this one waited. One SELECT, not a DELETE per added file -- with no\n // contention it returns the same set `existing` already ruled out, so nothing extra clears.\n let contentTouched = touched;\n if (added.length > 0)\n contentTouched = await stages.time('added-recheck', async () => {\n const currentPathsStmt = await conn.prepare('SELECT \"path\" FROM frontmatter');\n const currentPaths = new Set(((await currentPathsStmt.all()) as Array<{ path: string }>).map((r) => r.path));\n const staleAdded = added.filter((p) => currentPaths.has(p));\n return staleAdded.length > 0 ? [...touched, ...staleAdded] : touched;\n });\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 // Written per parse, unlike _rank, which a feature pass owns and the upsert skips.\n if (col === '_parse_error') return doc.parseError;\n return doc.data[col] ?? null;\n });\n // A path in `added` has no existing frontmatter row, so it can never conflict: where a\n // dialect offers a faster append-only path (insertNew), only the rest go through the upsert.\n await stages.time('fm-upsert', async () => {\n if (dialect.insertNew) {\n const newDocs = parsedDocs.filter((d) => addedSet.has(d.relPath));\n const updateDocs = parsedDocs.filter((d) => !addedSet.has(d.relPath));\n if (newDocs.length > 0) await dialect.insertNew(conn, 'frontmatter', writableColumns, newDocs.map(toRow));\n if (updateDocs.length > 0) await conn.runBatch(insertSql, updateDocs.map(toRow));\n } else {\n await conn.runBatch(insertSql, parsedDocs.map(toRow));\n }\n });\n }\n\n // After the upsert, so every doc already has the frontmatter row sqlite's content rowid\n // couples to. ON CONFLICT DO UPDATE preserves that rowid, so a reparse keeps its identity.\n await stages.time('text-index', () => dialect.reconcileContent(conn, contentTouched, parsedDocs, delta, cfg));\n\n // A preset edit forces a full rebuild, so an unchanged doc's coverage is already correct;\n // new docs have nothing to clear, which keeps cold builds linear.\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 // DO NOTHING, not a bare INSERT: the added/touched split above comes from a read taken\n // before this transaction's lock, so a path this process calls \"added\" can already have\n // its (path, preset) row committed by a concurrent reconcile -- the row would be identical either way.\n if (presetRows.length > 0) await conn.runBatch('INSERT INTO preset_files (\"path\", preset) VALUES (?, ?) ON CONFLICT(\"path\", preset) DO NOTHING', presetRows);\n });\n\n // Before the feature hooks, never after: rank's afterReconcile reads frontmatter as PageRank's\n // node set, so a lingering vanished row would dilute rank mass across every surviving note.\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 // Timed per feature per hook, so link resolution and PageRank are named stages without\n // links.ts or rank.ts knowing anything about this, and a new feature is visible for free.\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 dialect.beginMode()\n );\n\n const durationMs = Date.now() - txStart;\n // Every store, not just the ones with a PRAGMA to derive: connectUnlocked's lock-wait budget needs it too.\n recordLockWaitMs(baseDir, durationMs);\n if (dialect.recordDuration) await stages.time('meta', () => dialect.recordDuration?.(conn, durationMs));\n\n return { parsed: parsedDocs.length, warnings, stages: stages.take(elapsed(), durationMs, workerParseMs) };\n}\n"],"names":["CORE_FRONTMATTER_COLUMNS","reconcile","Set","conn","cfg","baseDir","dialect","pool","forcedPaths","start","features","stages","elapsed","files","currentSet","existingRows","existing","vanished","toReparse","seenColumns","report","parsedDocs","warnings","newColumns","workerParseMs","col","allColumns","writableColumns","insertSql","added","delta","addedSet","reparsedExisting","touched","txStart","durationMs","process","hrtime","bigint","activeFeatures","stageRecorder","map","f","name","Number","time","listFiles","relPath","existingStmt","prepare","all","Map","r","path","filter","has","row","get","_mtime","mtimeMs","_size","size","length","parsed","take","getColumns","progress","reparseFiles","tick","docs","finish","add","checkColumnLimit","c","RESERVED_COLUMNS","quoteIdent","join","reparsed","d","p","Date","now","withTransaction","present","missingColumns","contentTouched","toRow","addColumns","currentPathsStmt","currentPaths","staleAdded","doc","ctimeMs","parseError","data","newDocs","updateDocs","insertNew","runBatch","reconcileContent","presetRows","presetName","presets","push","feature","featureStage","remove","docsForFeature","extracted","store","afterReconcile","beginMode","recordLockWaitMs","recordDuration"],"mappings":"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"}
@@ -135,7 +135,7 @@ function _ts_generator(thisArg, body) {
135
135
  }
136
136
  }
137
137
  // snippet() re-tokenizes each candidate doc, superlinearly: ~10s for one 1MB doc
138
- // (benchmark/reports/2026-08-23-hub-release-battery.md); past this bound, hit stays NULL for the caller's JS excerpt fallback.
138
+ // (benchmark/reports/2026-08-23-0.13.2-hub-release-battery.md); past this bound, hit stays NULL for the caller's JS excerpt fallback.
139
139
  var SNIPPET_BOUND = 16384;
140
140
  var WEIGHTED_BM25 = 'bm25(content, 10.0, 5.0, 1.0, 0, 10.0, 5.0, 1.0)';
141
141
  function queryLexical(conn, terms, opts) {
@@ -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\n// snippet() re-tokenizes each candidate doc, superlinearly: ~10s for one 1MB doc\n// (benchmark/reports/2026-08-23-hub-release-battery.md); past this bound, hit stays NULL for the caller's JS excerpt fallback.\nconst SNIPPET_BOUND = 16_384;\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 with excerpt, 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, CASE WHEN length(content.text) <= ${SNIPPET_BOUND} THEN snippet(content, 2, '«', '»', '…', 10) ELSE NULL END AS hit 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","SNIPPET_BOUND","WEIGHTED_BM25","conn","terms","opts","whereJoin","whereCond","scopeCond","limit","query","sql","stmt","segmentMatch","trim","prepare","all"],"mappings":";;;;+BAUsBA;;;eAAAA;;;yBAVO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG7B,iFAAiF;AACjF,+HAA+H;AAC/H,IAAMC,gBAAgB;AACtB,IAAMC,gBAAgB;AAIf,SAAeF,aAAaG,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,kEAAgKL,OAA/FL,eAAc,yFAAoHM,OAAnCD,WAAU,2BAAsCE,OAAbD,WAAU,KAAyBL,OAAtBM,WAAU,cAAmCC,OAAvBP,eAAc,WAAe,OAANO;oBAC7P;;wBAAMN,KAAKY,OAAO,CAACJ;;;oBAA1BC,OAAO;oBACL;;wBAAMA,KAAKI,GAAG,CAACN;;;oBAAvB;;wBAAQ;;;;IACV"}
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\n// snippet() re-tokenizes each candidate doc, superlinearly: ~10s for one 1MB doc\n// (benchmark/reports/2026-08-23-0.13.2-hub-release-battery.md); past this bound, hit stays NULL for the caller's JS excerpt fallback.\nconst SNIPPET_BOUND = 16_384;\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 with excerpt, 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, CASE WHEN length(content.text) <= ${SNIPPET_BOUND} THEN snippet(content, 2, '«', '»', '…', 10) ELSE NULL END AS hit 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","SNIPPET_BOUND","WEIGHTED_BM25","conn","terms","opts","whereJoin","whereCond","scopeCond","limit","query","sql","stmt","segmentMatch","trim","prepare","all"],"mappings":";;;;+BAUsBA;;;eAAAA;;;yBAVO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG7B,iFAAiF;AACjF,sIAAsI;AACtI,IAAMC,gBAAgB;AACtB,IAAMC,gBAAgB;AAIf,SAAeF,aAAaG,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,kEAAgKL,OAA/FL,eAAc,yFAAoHM,OAAnCD,WAAU,2BAAsCE,OAAbD,WAAU,KAAyBL,OAAtBM,WAAU,cAAmCC,OAAvBP,eAAc,WAAe,OAANO;oBAC7P;;wBAAMN,KAAKY,OAAO,CAACJ;;;oBAA1BC,OAAO;oBACL;;wBAAMA,KAAKI,GAAG,CAACN;;;oBAAvB;;wBAAQ;;;;IACV"}
@@ -363,7 +363,6 @@ function _wrap_async_generator(fn) {
363
363
  var CAPABILITIES = new Set([
364
364
  'phrases',
365
365
  'snippets',
366
- 'watch-concurrency',
367
366
  'lexical',
368
367
  'vectors',
369
368
  'sql-functions'
@@ -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, VectorWriteRow } from '../types.ts';\nimport { 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(['phrases', 'snippets', 'watch-concurrency', 'lexical', 'vectors', 'sql-functions']);\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 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 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);\n },\n async similar(path, opts) {\n return scanSimilar(conn, path, opts);\n },\n async hasVector(path) {\n return hasVectorRow(conn, path);\n },\n },\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","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","docs","columns","getColumns","fieldStats","scopeWhere","lexical","query","terms","opts","queryLexical","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","candidates","qv","storeDims","fetch","allowed","scanCandidates","similar","path","scanSimilar","hasVector","hasVectorRow","engineStatus","row","get","busy_timeout","timeout","raw","stmt","setReadBigInts","iterate","params","close"],"mappings":"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"}
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, VectorWriteRow } from '../types.ts';\nimport { 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(['phrases', 'snippets', 'lexical', 'vectors', 'sql-functions']);\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 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 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);\n },\n async similar(path, opts) {\n return scanSimilar(conn, path, opts);\n },\n async hasVector(path) {\n return hasVectorRow(conn, path);\n },\n },\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","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","docs","columns","getColumns","fieldStats","scopeWhere","lexical","query","terms","opts","queryLexical","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","candidates","qv","storeDims","fetch","allowed","scanCandidates","similar","path","scanSimilar","hasVector","hasVectorRow","engineStatus","row","get","busy_timeout","timeout","raw","stmt","setReadBigInts","iterate","params","close"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ export declare const STAGES_VERSION = "s1";
2
+ export declare const FIXED_STAGES: readonly ["list", "existing", "parse", "alter", "added-recheck", "fm-upsert", "text-index", "presets", "vanished", "meta"];
3
+ export declare const FEATURE_HOOKS: readonly ["remove", "store", "after"];
4
+ export type FeatureHook = (typeof FEATURE_HOOKS)[number];
5
+ export interface Stages {
6
+ version: string;
7
+ totalMs: number;
8
+ txMs: number;
9
+ parseWorkerMs: number;
10
+ spans: Record<string, number>;
11
+ }
12
+ export interface StageRecorder {
13
+ time<T>(stage: string, fn: () => T | Promise<T>): Promise<T>;
14
+ take(totalMs: number, txMs: number, parseWorkerMs?: number): Stages;
15
+ }
16
+ export declare function featureStage(name: string, hook: FeatureHook): string;
17
+ export declare function stageRecorder(featureNames?: readonly string[]): StageRecorder;
18
+ export declare function unaccountedMs(stages: Stages): number;
@@ -0,0 +1,18 @@
1
+ export declare const STAGES_VERSION = "s1";
2
+ export declare const FIXED_STAGES: readonly ["list", "existing", "parse", "alter", "added-recheck", "fm-upsert", "text-index", "presets", "vanished", "meta"];
3
+ export declare const FEATURE_HOOKS: readonly ["remove", "store", "after"];
4
+ export type FeatureHook = (typeof FEATURE_HOOKS)[number];
5
+ export interface Stages {
6
+ version: string;
7
+ totalMs: number;
8
+ txMs: number;
9
+ parseWorkerMs: number;
10
+ spans: Record<string, number>;
11
+ }
12
+ export interface StageRecorder {
13
+ time<T>(stage: string, fn: () => T | Promise<T>): Promise<T>;
14
+ take(totalMs: number, txMs: number, parseWorkerMs?: number): Stages;
15
+ }
16
+ export declare function featureStage(name: string, hook: FeatureHook): string;
17
+ export declare function stageRecorder(featureNames?: readonly string[]): StageRecorder;
18
+ export declare function unaccountedMs(stages: Stages): number;
@@ -0,0 +1,372 @@
1
+ // Per-stage wall time for one reconcile, all on this thread's clock. Stages name work a build has
2
+ // to do, never the function or file doing it, so the vocabulary outlives a pipeline refactor.
3
+ "use strict";
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ function _export(target, all) {
8
+ for(var name in all)Object.defineProperty(target, name, {
9
+ enumerable: true,
10
+ get: Object.getOwnPropertyDescriptor(all, name).get
11
+ });
12
+ }
13
+ _export(exports, {
14
+ get FEATURE_HOOKS () {
15
+ return FEATURE_HOOKS;
16
+ },
17
+ get FIXED_STAGES () {
18
+ return FIXED_STAGES;
19
+ },
20
+ get STAGES_VERSION () {
21
+ return STAGES_VERSION;
22
+ },
23
+ get featureStage () {
24
+ return featureStage;
25
+ },
26
+ get stageRecorder () {
27
+ return stageRecorder;
28
+ },
29
+ get unaccountedMs () {
30
+ return unaccountedMs;
31
+ }
32
+ });
33
+ function _array_like_to_array(arr, len) {
34
+ if (len == null || len > arr.length) len = arr.length;
35
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
36
+ return arr2;
37
+ }
38
+ function _array_with_holes(arr) {
39
+ if (Array.isArray(arr)) return arr;
40
+ }
41
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
42
+ try {
43
+ var info = gen[key](arg);
44
+ var value = info.value;
45
+ } catch (error) {
46
+ reject(error);
47
+ return;
48
+ }
49
+ if (info.done) resolve(value);
50
+ else Promise.resolve(value).then(_next, _throw);
51
+ }
52
+ function _async_to_generator(fn) {
53
+ return function() {
54
+ var self = this, args = arguments;
55
+ return new Promise(function(resolve, reject) {
56
+ var gen = fn.apply(self, args);
57
+ function _next(value) {
58
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
59
+ }
60
+ function _throw(err) {
61
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
62
+ }
63
+ _next(undefined);
64
+ });
65
+ };
66
+ }
67
+ function _iterable_to_array_limit(arr, i) {
68
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
69
+ if (_i == null) return;
70
+ var _arr = [];
71
+ var _n = true;
72
+ var _d = false;
73
+ var _s, _e;
74
+ try {
75
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
76
+ _arr.push(_s.value);
77
+ if (i && _arr.length === i) break;
78
+ }
79
+ } catch (err) {
80
+ _d = true;
81
+ _e = err;
82
+ } finally{
83
+ try {
84
+ if (!_n && _i["return"] != null) _i["return"]();
85
+ } finally{
86
+ if (_d) throw _e;
87
+ }
88
+ }
89
+ return _arr;
90
+ }
91
+ function _non_iterable_rest() {
92
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
93
+ }
94
+ function _sliced_to_array(arr, i) {
95
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
96
+ }
97
+ function _ts_generator(thisArg, body) {
98
+ var f, y, t, _ = {
99
+ label: 0,
100
+ sent: function() {
101
+ if (t[0] & 1) throw t[1];
102
+ return t[1];
103
+ },
104
+ trys: [],
105
+ ops: []
106
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
107
+ return d(g, "next", {
108
+ value: verb(0)
109
+ }), d(g, "throw", {
110
+ value: verb(1)
111
+ }), d(g, "return", {
112
+ value: verb(2)
113
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
114
+ value: function() {
115
+ return this;
116
+ }
117
+ }), g;
118
+ function verb(n) {
119
+ return function(v) {
120
+ return step([
121
+ n,
122
+ v
123
+ ]);
124
+ };
125
+ }
126
+ function step(op) {
127
+ if (f) throw new TypeError("Generator is already executing.");
128
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
129
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
130
+ if (y = 0, t) op = [
131
+ op[0] & 2,
132
+ t.value
133
+ ];
134
+ switch(op[0]){
135
+ case 0:
136
+ case 1:
137
+ t = op;
138
+ break;
139
+ case 4:
140
+ _.label++;
141
+ return {
142
+ value: op[1],
143
+ done: false
144
+ };
145
+ case 5:
146
+ _.label++;
147
+ y = op[1];
148
+ op = [
149
+ 0
150
+ ];
151
+ continue;
152
+ case 7:
153
+ op = _.ops.pop();
154
+ _.trys.pop();
155
+ continue;
156
+ default:
157
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
158
+ _ = 0;
159
+ continue;
160
+ }
161
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
162
+ _.label = op[1];
163
+ break;
164
+ }
165
+ if (op[0] === 6 && _.label < t[1]) {
166
+ _.label = t[1];
167
+ t = op;
168
+ break;
169
+ }
170
+ if (t && _.label < t[2]) {
171
+ _.label = t[2];
172
+ _.ops.push(op);
173
+ break;
174
+ }
175
+ if (t[2]) _.ops.pop();
176
+ _.trys.pop();
177
+ continue;
178
+ }
179
+ op = body.call(thisArg, _);
180
+ } catch (e) {
181
+ op = [
182
+ 6,
183
+ e
184
+ ];
185
+ y = 0;
186
+ } finally{
187
+ f = t = 0;
188
+ }
189
+ if (op[0] & 5) throw op[1];
190
+ return {
191
+ value: op[0] ? op[1] : void 0,
192
+ done: true
193
+ };
194
+ }
195
+ }
196
+ function _unsupported_iterable_to_array(o, minLen) {
197
+ if (!o) return;
198
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
199
+ var n = Object.prototype.toString.call(o).slice(8, -1);
200
+ if (n === "Object" && o.constructor) n = o.constructor.name;
201
+ if (n === "Map" || n === "Set") return Array.from(n);
202
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
203
+ }
204
+ var STAGES_VERSION = 's1';
205
+ var FIXED_STAGES = [
206
+ 'list',
207
+ 'existing',
208
+ 'parse',
209
+ 'alter',
210
+ 'added-recheck',
211
+ 'fm-upsert',
212
+ 'text-index',
213
+ 'presets',
214
+ 'vanished',
215
+ 'meta'
216
+ ];
217
+ var FEATURE_HOOKS = [
218
+ 'remove',
219
+ 'store',
220
+ 'after'
221
+ ];
222
+ function featureStage(name, hook) {
223
+ return "feature:".concat(name, ":").concat(hook);
224
+ }
225
+ var round = function round(ms) {
226
+ return Math.round(ms * 10) / 10;
227
+ };
228
+ function stageRecorder() {
229
+ var featureNames = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : [];
230
+ var spans = new Map();
231
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
232
+ try {
233
+ for(var _iterator = FIXED_STAGES[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
234
+ var stage = _step.value;
235
+ spans.set(stage, 0);
236
+ }
237
+ } catch (err) {
238
+ _didIteratorError = true;
239
+ _iteratorError = err;
240
+ } finally{
241
+ try {
242
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
243
+ _iterator.return();
244
+ }
245
+ } finally{
246
+ if (_didIteratorError) {
247
+ throw _iteratorError;
248
+ }
249
+ }
250
+ }
251
+ var _iteratorNormalCompletion1 = true, _didIteratorError1 = false, _iteratorError1 = undefined, _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = undefined;
252
+ try {
253
+ for(var _iterator1 = featureNames[Symbol.iterator](), _step1; !(_iteratorNormalCompletion2 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion2 = true){
254
+ var name = _step1.value;
255
+ try {
256
+ for(var _iterator2 = FEATURE_HOOKS[Symbol.iterator](), _step2; !(_iteratorNormalCompletion1 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion1 = true){
257
+ var hook = _step2.value;
258
+ spans.set(featureStage(name, hook), 0);
259
+ }
260
+ } catch (err) {
261
+ _didIteratorError1 = true;
262
+ _iteratorError1 = err;
263
+ } finally{
264
+ try {
265
+ if (!_iteratorNormalCompletion1 && _iterator2.return != null) {
266
+ _iterator2.return();
267
+ }
268
+ } finally{
269
+ if (_didIteratorError1) {
270
+ throw _iteratorError1;
271
+ }
272
+ }
273
+ }
274
+ }
275
+ } catch (err) {
276
+ _didIteratorError2 = true;
277
+ _iteratorError2 = err;
278
+ } finally{
279
+ try {
280
+ if (!_iteratorNormalCompletion2 && _iterator1.return != null) {
281
+ _iterator1.return();
282
+ }
283
+ } finally{
284
+ if (_didIteratorError2) {
285
+ throw _iteratorError2;
286
+ }
287
+ }
288
+ }
289
+ return {
290
+ time: // A throw records nothing: an aborted reconcile must not report a partial stage as a complete one.
291
+ function time(stage, fn) {
292
+ return _async_to_generator(function() {
293
+ var _spans_get, at, value;
294
+ return _ts_generator(this, function(_state) {
295
+ switch(_state.label){
296
+ case 0:
297
+ at = process.hrtime.bigint();
298
+ return [
299
+ 4,
300
+ fn()
301
+ ];
302
+ case 1:
303
+ value = _state.sent();
304
+ spans.set(stage, ((_spans_get = spans.get(stage)) !== null && _spans_get !== void 0 ? _spans_get : 0) + Number(process.hrtime.bigint() - at) / 1e6);
305
+ return [
306
+ 2,
307
+ value
308
+ ];
309
+ }
310
+ });
311
+ })();
312
+ },
313
+ // Every declared stage reports, 0 included, so a store that skips some work and a store that
314
+ // does it cheaply read alike across a timeline. An absent `stages` is a build with no timers.
315
+ take: function take(totalMs, txMs) {
316
+ var parseWorkerMs = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 0;
317
+ var out = {};
318
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
319
+ try {
320
+ for(var _iterator = spans[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
321
+ var _step_value = _sliced_to_array(_step.value, 2), stage = _step_value[0], ms = _step_value[1];
322
+ out[stage] = round(ms);
323
+ }
324
+ } catch (err) {
325
+ _didIteratorError = true;
326
+ _iteratorError = err;
327
+ } finally{
328
+ try {
329
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
330
+ _iterator.return();
331
+ }
332
+ } finally{
333
+ if (_didIteratorError) {
334
+ throw _iteratorError;
335
+ }
336
+ }
337
+ }
338
+ return {
339
+ version: STAGES_VERSION,
340
+ totalMs: round(totalMs),
341
+ txMs: round(txMs),
342
+ parseWorkerMs: round(parseWorkerMs),
343
+ spans: out
344
+ };
345
+ }
346
+ };
347
+ }
348
+ function unaccountedMs(stages) {
349
+ var sum = 0;
350
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
351
+ try {
352
+ for(var _iterator = Object.values(stages.spans)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
353
+ var ms = _step.value;
354
+ sum += ms;
355
+ }
356
+ } catch (err) {
357
+ _didIteratorError = true;
358
+ _iteratorError = err;
359
+ } finally{
360
+ try {
361
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
362
+ _iterator.return();
363
+ }
364
+ } finally{
365
+ if (_didIteratorError) {
366
+ throw _iteratorError;
367
+ }
368
+ }
369
+ }
370
+ return round(stages.totalMs - sum);
371
+ }
372
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -0,0 +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 time inside `parse`: CPU across workers, not a wall span, so it\n // sits beside the spans like txMs and never counts toward the sum. 0 on the serial path.\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/turso/store.ts"],"sourcesContent":["import type { Database } from '@tursodatabase/database';\nimport { STORE_DIMS } from '../../embed/types.ts';\nimport { getColumns } from '../shared.ts';\nimport { withTransaction } from '../transaction.ts';\nimport type { Capability, Connection, Statement, Store } from '../types.ts';\nimport { hasVectorRow, pendingRows } from '../vectors.ts';\nimport { fieldStats } from './fieldStats.ts';\nimport { queryLexical } from './lexical.ts';\nimport { scanCandidates, scanSimilar, writeVectorBatch } from './vectors.ts';\n\n// No 'snippets': fts_highlight returns the whole column, not a bounded window, so hits use\n// the caller's JS excerpt. No 'watch-concurrency': single-process by default, as on duckdb.\nexport const CAPABILITIES: ReadonlySet<Capability> = new Set(['lexical', 'phrases', 'vectors']);\n\n// Shares one Connection instance (conn) with the builder's own reconcile call so transaction depth\n// (see transaction.ts) is tracked against the same object everywhere.\nexport function createStore(db: Database, conn: Connection): Store {\n return {\n name: 'turso',\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 fieldStats: (columns, scopeWhere) => fieldStats(conn, columns, scopeWhere),\n },\n lexical: {\n query: (terms, opts) => queryLexical(conn, terms, opts),\n },\n // The column's fixed DDL width (STORE_DIMS) is what every scan binds against, not the\n // interface's per-call storeDims -- see vectors.ts's padded() for why a shorter vector is still correct against a wider column.\n vectors: {\n pending: () => pendingRows(conn),\n writeVectors: (rows) => writeVectorBatch(conn, STORE_DIMS, rows),\n candidates: (qv, _storeDims, fetch, allowed) => scanCandidates(conn, qv, STORE_DIMS, fetch, allowed),\n similar: (path, opts) => scanSimilar(conn, STORE_DIMS, path, opts),\n hasVector: (path) => hasVectorRow(conn, path),\n },\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). Turso's PRAGMA busy_timeout names its column \"busy_timeout\" (spike-verified), not \"timeout\" like real SQLite.\n const row = (await (await db.prepare('PRAGMA busy_timeout')).get()) as { busy_timeout: number };\n return { busy_timeout: `${row.busy_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 = await db.prepare(sql);\n stmt.safeIntegers(true); // int64 past 2^53 arrives as BigInt instead of losing precision\n return {\n columns: () => stmt.columns(),\n // sense sql streams through the client's own async generator.\n iterate: async function* (...params: unknown[]) {\n yield* stmt.iterate(...params);\n },\n };\n },\n },\n async close() {\n await db.close();\n },\n };\n}\n"],"names":["CAPABILITIES","createStore","Set","db","conn","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","docs","columns","getColumns","fieldStats","scopeWhere","lexical","query","terms","opts","queryLexical","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","STORE_DIMS","candidates","qv","_storeDims","fetch","allowed","scanCandidates","similar","path","scanSimilar","hasVector","hasVectorRow","engineStatus","row","get","busy_timeout","raw","stmt","safeIntegers","iterate","params","close"],"mappings":";;;;;;;;;;;QAYaA;eAAAA;;QAIGC;eAAAA;;;uBAfW;wBACA;6BACK;yBAEU;4BACf;yBACE;0BACiC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIvD,IAAMD,eAAwC,IAAIE,IAAI;IAAC;IAAW;IAAW;CAAU;AAIvF,SAASD,YAAYE,EAAY,EAAEC,IAAgB;IACxD,OAAO;QACLC,MAAM;QACNC,cAAcN;QACRO,MAAN,SAAMA,KAAKC,GAAW;;;;;4BACpB;;gCAAMJ,KAAKG,IAAI,CAACC;;;4BAAhB;;;;;;YACF;;QACMC,SAAN,SAAMA,QAAQD,GAAW;;;oBACvB;;wBAAOJ,KAAKK,OAAO,CAACD;;;YACtB;;QACME,UAAN,SAAMA,SAASF,GAAW,EAAEG,SAAsB;;;;;4BAChD;;gCAAMP,KAAKM,QAAQ,CAACF,KAAKG;;;4BAAzB;;;;;;YACF;;QACMC,aAAN,SAAMA,YAAeC,EAAoB;;;oBACvC;;wBAAOC,IAAAA,8BAAe,EAACV,MAAMS;;;YAC/B;;QACAE,MAAM;YACEC,SAAN,SAAMA;;;;;gCACQ;;oCAAMC,IAAAA,oBAAU,EAACb;;;gCAA7B;;oCAAQ;wCAAI;;;;;gBACd;;YACAc,YAAY,SAAZA,WAAaF,SAASG;uBAAeD,IAAAA,wBAAU,EAACd,MAAMY,SAASG;;QACjE;QACAC,SAAS;YACPC,OAAO,SAAPA,MAAQC,OAAOC;uBAASC,IAAAA,uBAAY,EAACpB,MAAMkB,OAAOC;;QACpD;QACA,sFAAsF;QACtF,gIAAgI;QAChIE,SAAS;YACPC,SAAS,SAATA;uBAAeC,IAAAA,sBAAW,EAACvB;;YAC3BwB,cAAc,SAAdA,aAAeC;uBAASC,IAAAA,4BAAgB,EAAC1B,MAAM2B,mBAAU,EAAEF;;YAC3DG,YAAY,SAAZA,WAAaC,IAAIC,YAAYC,OAAOC;uBAAYC,IAAAA,0BAAc,EAACjC,MAAM6B,IAAIF,mBAAU,EAAEI,OAAOC;;YAC5FE,SAAS,SAATA,QAAUC,MAAMhB;uBAASiB,IAAAA,uBAAW,EAACpC,MAAM2B,mBAAU,EAAEQ,MAAMhB;;YAC7DkB,WAAW,SAAXA,UAAYF;uBAASG,IAAAA,uBAAY,EAACtC,MAAMmC;;QAC1C;QACMI,cAAN,SAAMA;;oBAGEC;;;;4BAAc;;gCAAMzC,GAAGM,OAAO,CAAC;;;4BAAxB;;gCAAO,cAAyCoC,GAAG;;;4BAA1DD,MAAO;4BACb;;gCAAO;oCAAEE,cAAc,AAAC,GAAmB,OAAjBF,IAAIE,YAAY,EAAC;gCAAoF;;;;YACjI;;QACAC,KAAK;YACGtC,SAAN,SAAMA,QAAQD,GAAW;;wBACjBwC;;;;gCAAO;;oCAAM7C,GAAGM,OAAO,CAACD;;;gCAAxBwC,OAAO;gCACbA,KAAKC,YAAY,CAAC,OAAO,gEAAgE;gCACzF;;oCAAO;wCACLjC,SAAS,SAATA;mDAAegC,KAAKhC,OAAO;;wCAC3B,8DAA8D;wCAC9DkC,SAAS,SAATA;4CAA0B,IAAA,IAAA,OAAA,UAAA,QAAA,AAAGC,SAAH,UAAA,OAAA,OAAA,GAAA,OAAA,MAAA;gDAAGA,OAAH,QAAA,SAAA,CAAA,KAAoB;;;oDACrCH;;;;4DAAP;;2EAAA,0CAAOA,CAAAA,QAAAA,MAAKE,OAAO,OAAZF,OAAa,qBAAGG;;;4DAAvB;;;;;;4CACF;;oCACF;;;;gBACF;;QACF;QACMC,OAAN,SAAMA;;;;;4BACJ;;gCAAMjD,GAAGiD,KAAK;;;4BAAd;;;;;;YACF;;IACF;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/store/turso/store.ts"],"sourcesContent":["import type { Database } from '@tursodatabase/database';\nimport { STORE_DIMS } from '../../embed/types.ts';\nimport { getColumns } from '../shared.ts';\nimport { withTransaction } from '../transaction.ts';\nimport type { Capability, Connection, Statement, Store } from '../types.ts';\nimport { hasVectorRow, pendingRows } from '../vectors.ts';\nimport { fieldStats } from './fieldStats.ts';\nimport { queryLexical } from './lexical.ts';\nimport { scanCandidates, scanSimilar, writeVectorBatch } from './vectors.ts';\n\n// No 'snippets': fts_highlight returns the whole column, not a bounded window, so hits use\n// the caller's JS excerpt.\nexport const CAPABILITIES: ReadonlySet<Capability> = new Set(['lexical', 'phrases', 'vectors']);\n\n// Shares one Connection instance (conn) with the builder's own reconcile call so transaction depth\n// (see transaction.ts) is tracked against the same object everywhere.\nexport function createStore(db: Database, conn: Connection): Store {\n return {\n name: 'turso',\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 fieldStats: (columns, scopeWhere) => fieldStats(conn, columns, scopeWhere),\n },\n lexical: {\n query: (terms, opts) => queryLexical(conn, terms, opts),\n },\n // The column's fixed DDL width (STORE_DIMS) is what every scan binds against, not the\n // interface's per-call storeDims -- see vectors.ts's padded() for why a shorter vector is still correct against a wider column.\n vectors: {\n pending: () => pendingRows(conn),\n writeVectors: (rows) => writeVectorBatch(conn, STORE_DIMS, rows),\n candidates: (qv, _storeDims, fetch, allowed) => scanCandidates(conn, qv, STORE_DIMS, fetch, allowed),\n similar: (path, opts) => scanSimilar(conn, STORE_DIMS, path, opts),\n hasVector: (path) => hasVectorRow(conn, path),\n },\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). Turso's PRAGMA busy_timeout names its column \"busy_timeout\" (spike-verified), not \"timeout\" like real SQLite.\n const row = (await (await db.prepare('PRAGMA busy_timeout')).get()) as { busy_timeout: number };\n return { busy_timeout: `${row.busy_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 = await db.prepare(sql);\n stmt.safeIntegers(true); // int64 past 2^53 arrives as BigInt instead of losing precision\n return {\n columns: () => stmt.columns(),\n // sense sql streams through the client's own async generator.\n iterate: async function* (...params: unknown[]) {\n yield* stmt.iterate(...params);\n },\n };\n },\n },\n async close() {\n await db.close();\n },\n };\n}\n"],"names":["CAPABILITIES","createStore","Set","db","conn","name","capabilities","exec","sql","prepare","runBatch","paramRows","transaction","fn","withTransaction","docs","columns","getColumns","fieldStats","scopeWhere","lexical","query","terms","opts","queryLexical","vectors","pending","pendingRows","writeVectors","rows","writeVectorBatch","STORE_DIMS","candidates","qv","_storeDims","fetch","allowed","scanCandidates","similar","path","scanSimilar","hasVector","hasVectorRow","engineStatus","row","get","busy_timeout","raw","stmt","safeIntegers","iterate","params","close"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import type { Config, ResolvedConfig, StoreName } from '../config/index.js';
2
2
  import type { ReconcileDelta } from '../features/types.js';
3
3
  import type { ParsedDoc } from '../scan/index.js';
4
- export declare const CAPABILITY_NAMES: readonly ["phrases", "snippets", "watch-concurrency", "lexical", "vectors", "sql-functions"];
4
+ export declare const CAPABILITY_NAMES: readonly ["phrases", "snippets", "lexical", "vectors", "sql-functions"];
5
5
  export type Capability = (typeof CAPABILITY_NAMES)[number];
6
6
  export interface RunResult {
7
7
  changes: number | bigint;