sensemaking 0.25.0 → 0.26.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.
- package/README.md +14 -10
- package/dist/cjs/cli/index.d.cts +1 -1
- package/dist/cjs/cli/index.d.ts +1 -1
- package/dist/cjs/cli/index.js +1 -1
- package/dist/cjs/cli/index.js.map +1 -1
- package/dist/cjs/cli/path.js +5 -29
- package/dist/cjs/cli/path.js.map +1 -1
- package/dist/cjs/cli/related.js +4 -3
- package/dist/cjs/cli/related.js.map +1 -1
- package/dist/cjs/commands/index.d.cts +6 -3
- package/dist/cjs/commands/index.d.ts +6 -3
- package/dist/cjs/commands/index.js +4 -0
- package/dist/cjs/commands/index.js.map +1 -1
- package/dist/cjs/commands/map.d.cts +14 -5
- package/dist/cjs/commands/map.d.ts +14 -5
- package/dist/cjs/commands/map.js +42 -35
- package/dist/cjs/commands/map.js.map +1 -1
- package/dist/cjs/commands/path.d.cts +14 -0
- package/dist/cjs/commands/path.d.ts +14 -0
- package/dist/cjs/commands/path.js +209 -0
- package/dist/cjs/commands/path.js.map +1 -0
- package/dist/cjs/commands/peek.d.cts +16 -1
- package/dist/cjs/commands/peek.d.ts +16 -1
- package/dist/cjs/commands/peek.js +71 -33
- package/dist/cjs/commands/peek.js.map +1 -1
- package/dist/cjs/commands/related.d.cts +16 -3
- package/dist/cjs/commands/related.d.ts +16 -3
- package/dist/cjs/commands/related.js +131 -98
- package/dist/cjs/commands/related.js.map +1 -1
- package/dist/cjs/commands/scope.d.cts +1 -0
- package/dist/cjs/commands/scope.d.ts +1 -0
- package/dist/cjs/commands/scope.js +149 -0
- package/dist/cjs/commands/scope.js.map +1 -1
- package/dist/cjs/commands/search.d.cts +26 -3
- package/dist/cjs/commands/search.d.ts +26 -3
- package/dist/cjs/commands/search.js +211 -71
- package/dist/cjs/commands/search.js.map +1 -1
- package/dist/cjs/commands/signals.d.cts +4 -3
- package/dist/cjs/commands/signals.d.ts +4 -3
- package/dist/cjs/commands/signals.js +13 -4
- package/dist/cjs/commands/signals.js.map +1 -1
- package/dist/cjs/commands/snapshot.d.cts +3 -0
- package/dist/cjs/commands/snapshot.d.ts +3 -0
- package/dist/cjs/commands/snapshot.js +180 -0
- package/dist/cjs/commands/snapshot.js.map +1 -0
- package/dist/cjs/embed/cohere.js +41 -16
- package/dist/cjs/embed/cohere.js.map +1 -1
- package/dist/cjs/embed/endpoint.d.cts +2 -0
- package/dist/cjs/embed/endpoint.d.ts +2 -0
- package/dist/cjs/embed/endpoint.js +30 -0
- package/dist/cjs/embed/endpoint.js.map +1 -0
- package/dist/cjs/embed/handoff.d.cts +7 -2
- package/dist/cjs/embed/handoff.d.ts +7 -2
- package/dist/cjs/embed/handoff.js +10 -0
- package/dist/cjs/embed/handoff.js.map +1 -1
- package/dist/cjs/embed/http.d.cts +18 -1
- package/dist/cjs/embed/http.d.ts +18 -1
- package/dist/cjs/embed/http.js +239 -40
- package/dist/cjs/embed/http.js.map +1 -1
- package/dist/cjs/embed/openai.js +39 -17
- package/dist/cjs/embed/openai.js.map +1 -1
- package/dist/cjs/embed/query.d.cts +9 -3
- package/dist/cjs/embed/query.d.ts +9 -3
- package/dist/cjs/embed/query.js +257 -90
- package/dist/cjs/embed/query.js.map +1 -1
- package/dist/cjs/embed/registry.d.cts +2 -2
- package/dist/cjs/embed/registry.d.ts +2 -2
- package/dist/cjs/embed/registry.js +36 -4
- package/dist/cjs/embed/registry.js.map +1 -1
- package/dist/cjs/embed/static.js +6 -2
- package/dist/cjs/embed/static.js.map +1 -1
- package/dist/cjs/embed/store.js +42 -77
- package/dist/cjs/embed/store.js.map +1 -1
- package/dist/cjs/embed/types.d.cts +5 -2
- package/dist/cjs/embed/types.d.ts +5 -2
- package/dist/cjs/embed/types.js.map +1 -1
- package/dist/cjs/features/embed.js +290 -43
- package/dist/cjs/features/embed.js.map +1 -1
- package/dist/cjs/graph/traverse.d.cts +2 -2
- package/dist/cjs/graph/traverse.d.ts +2 -2
- package/dist/cjs/graph/traverse.js +15 -5
- package/dist/cjs/graph/traverse.js.map +1 -1
- package/dist/cjs/index.d.cts +2 -2
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.js +6 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/output/output.d.cts +4 -36
- package/dist/cjs/output/output.d.ts +4 -36
- package/dist/cjs/output/output.js +1 -2
- package/dist/cjs/output/output.js.map +1 -1
- package/dist/cjs/scan/pool.d.cts +2 -1
- package/dist/cjs/scan/pool.d.ts +2 -1
- package/dist/cjs/scan/pool.js +116 -27
- package/dist/cjs/scan/pool.js.map +1 -1
- package/dist/cjs/scan/reparse.d.cts +1 -0
- package/dist/cjs/scan/reparse.d.ts +1 -0
- package/dist/cjs/scan/reparse.js +75 -21
- package/dist/cjs/scan/reparse.js.map +1 -1
- package/dist/cjs/store/builder.d.cts +11 -21
- package/dist/cjs/store/builder.d.ts +11 -21
- package/dist/cjs/store/builder.js +1077 -438
- package/dist/cjs/store/builder.js.map +1 -1
- package/dist/cjs/store/duckdb/connection.js +16 -2
- package/dist/cjs/store/duckdb/connection.js.map +1 -1
- package/dist/cjs/store/duckdb/open.d.cts +1 -1
- package/dist/cjs/store/duckdb/open.d.ts +1 -1
- package/dist/cjs/store/duckdb/open.js +73 -65
- package/dist/cjs/store/duckdb/open.js.map +1 -1
- package/dist/cjs/store/duckdb/reconcile.js +533 -15
- package/dist/cjs/store/duckdb/reconcile.js.map +1 -1
- package/dist/cjs/store/embed-scope.js +19 -9
- package/dist/cjs/store/embed-scope.js.map +1 -1
- package/dist/cjs/store/index.d.cts +6 -0
- package/dist/cjs/store/index.d.ts +6 -0
- package/dist/cjs/store/index.js +8 -4
- package/dist/cjs/store/index.js.map +1 -1
- package/dist/cjs/store/open.d.cts +6 -1
- package/dist/cjs/store/open.d.ts +6 -1
- package/dist/cjs/store/open.js +230 -307
- package/dist/cjs/store/open.js.map +1 -1
- package/dist/cjs/store/readiness.d.cts +5 -0
- package/dist/cjs/store/readiness.d.ts +5 -0
- package/dist/cjs/store/readiness.js +39 -0
- package/dist/cjs/store/readiness.js.map +1 -0
- package/dist/cjs/store/reconcile.d.cts +26 -1
- package/dist/cjs/store/reconcile.d.ts +26 -1
- package/dist/cjs/store/reconcile.js +670 -576
- package/dist/cjs/store/reconcile.js.map +1 -1
- package/dist/cjs/store/signature.d.cts +1 -0
- package/dist/cjs/store/signature.d.ts +1 -0
- package/dist/cjs/store/signature.js +9 -0
- package/dist/cjs/store/signature.js.map +1 -1
- package/dist/cjs/store/sqlite/open.d.cts +1 -1
- package/dist/cjs/store/sqlite/open.d.ts +1 -1
- package/dist/cjs/store/sqlite/open.js +84 -90
- package/dist/cjs/store/sqlite/open.js.map +1 -1
- package/dist/cjs/store/sqlite/reconcile.js.map +1 -1
- package/dist/cjs/store/sqlite/store.js +63 -60
- package/dist/cjs/store/sqlite/store.js.map +1 -1
- package/dist/cjs/store/sqlite/vectors.d.cts +2 -2
- package/dist/cjs/store/sqlite/vectors.d.ts +2 -2
- package/dist/cjs/store/sqlite/vectors.js +8 -4
- package/dist/cjs/store/sqlite/vectors.js.map +1 -1
- package/dist/cjs/store/stages.js.map +1 -1
- package/dist/cjs/store/turso/connection.d.cts +1 -0
- package/dist/cjs/store/turso/connection.d.ts +1 -0
- package/dist/cjs/store/turso/connection.js +319 -94
- package/dist/cjs/store/turso/connection.js.map +1 -1
- package/dist/cjs/store/turso/open.d.cts +1 -1
- package/dist/cjs/store/turso/open.d.ts +1 -1
- package/dist/cjs/store/turso/open.js +70 -74
- package/dist/cjs/store/turso/open.js.map +1 -1
- package/dist/cjs/store/turso/store.js +25 -23
- package/dist/cjs/store/turso/store.js.map +1 -1
- package/dist/cjs/store/turso/vectors.d.cts +2 -2
- package/dist/cjs/store/turso/vectors.d.ts +2 -2
- package/dist/cjs/store/turso/vectors.js +26 -16
- package/dist/cjs/store/turso/vectors.js.map +1 -1
- package/dist/cjs/store/types.d.cts +4 -1
- package/dist/cjs/store/types.d.ts +4 -1
- package/dist/cjs/store/types.js.map +1 -1
- package/dist/cjs/store/vectors.d.cts +14 -1
- package/dist/cjs/store/vectors.d.ts +14 -1
- package/dist/cjs/store/vectors.js +61 -0
- package/dist/cjs/store/vectors.js.map +1 -1
- package/dist/cjs/watch.d.cts +6 -0
- package/dist/cjs/watch.d.ts +6 -0
- package/dist/cjs/watch.js +42 -10
- package/dist/cjs/watch.js.map +1 -1
- package/dist/cjs/workers/parse.d.cts +4 -3
- package/dist/cjs/workers/parse.d.ts +4 -3
- package/dist/cjs/workers/parse.js +19 -17
- package/dist/cjs/workers/parse.js.map +1 -1
- package/dist/esm/cli/index.d.ts +1 -1
- package/dist/esm/cli/index.js +1 -1
- package/dist/esm/cli/index.js.map +1 -1
- package/dist/esm/cli/path.js +4 -10
- package/dist/esm/cli/path.js.map +1 -1
- package/dist/esm/cli/related.js +5 -3
- package/dist/esm/cli/related.js.map +1 -1
- package/dist/esm/commands/index.d.ts +6 -3
- package/dist/esm/commands/index.js +1 -0
- package/dist/esm/commands/index.js.map +1 -1
- package/dist/esm/commands/map.d.ts +14 -5
- package/dist/esm/commands/map.js +2 -0
- package/dist/esm/commands/map.js.map +1 -1
- package/dist/esm/commands/path.d.ts +14 -0
- package/dist/esm/commands/path.js +33 -0
- package/dist/esm/commands/path.js.map +1 -0
- package/dist/esm/commands/peek.d.ts +16 -1
- package/dist/esm/commands/peek.js +35 -9
- package/dist/esm/commands/peek.js.map +1 -1
- package/dist/esm/commands/related.d.ts +16 -3
- package/dist/esm/commands/related.js +45 -28
- package/dist/esm/commands/related.js.map +1 -1
- package/dist/esm/commands/scope.d.ts +1 -0
- package/dist/esm/commands/scope.js +58 -0
- package/dist/esm/commands/scope.js.map +1 -1
- package/dist/esm/commands/search.d.ts +26 -3
- package/dist/esm/commands/search.js +85 -18
- package/dist/esm/commands/search.js.map +1 -1
- package/dist/esm/commands/signals.d.ts +4 -3
- package/dist/esm/commands/signals.js +11 -4
- package/dist/esm/commands/signals.js.map +1 -1
- package/dist/esm/commands/snapshot.d.ts +3 -0
- package/dist/esm/commands/snapshot.js +25 -0
- package/dist/esm/commands/snapshot.js.map +1 -0
- package/dist/esm/embed/cohere.js +35 -10
- package/dist/esm/embed/cohere.js.map +1 -1
- package/dist/esm/embed/endpoint.d.ts +2 -0
- package/dist/esm/embed/endpoint.js +11 -0
- package/dist/esm/embed/endpoint.js.map +1 -0
- package/dist/esm/embed/handoff.d.ts +7 -2
- package/dist/esm/embed/handoff.js +7 -0
- package/dist/esm/embed/handoff.js.map +1 -1
- package/dist/esm/embed/http.d.ts +18 -1
- package/dist/esm/embed/http.js +137 -17
- package/dist/esm/embed/http.js.map +1 -1
- package/dist/esm/embed/openai.js +34 -12
- package/dist/esm/embed/openai.js.map +1 -1
- package/dist/esm/embed/query.d.ts +9 -3
- package/dist/esm/embed/query.js +98 -26
- package/dist/esm/embed/query.js.map +1 -1
- package/dist/esm/embed/registry.d.ts +2 -2
- package/dist/esm/embed/registry.js +34 -5
- package/dist/esm/embed/registry.js.map +1 -1
- package/dist/esm/embed/static.js +10 -2
- package/dist/esm/embed/static.js.map +1 -1
- package/dist/esm/embed/store.js +30 -21
- package/dist/esm/embed/store.js.map +1 -1
- package/dist/esm/embed/types.d.ts +5 -2
- package/dist/esm/embed/types.js.map +1 -1
- package/dist/esm/features/embed.js +82 -21
- package/dist/esm/features/embed.js.map +1 -1
- package/dist/esm/graph/traverse.d.ts +2 -2
- package/dist/esm/graph/traverse.js +4 -2
- package/dist/esm/graph/traverse.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/output/output.d.ts +4 -36
- package/dist/esm/output/output.js +1 -2
- package/dist/esm/output/output.js.map +1 -1
- package/dist/esm/scan/pool.d.ts +2 -1
- package/dist/esm/scan/pool.js +80 -23
- package/dist/esm/scan/pool.js.map +1 -1
- package/dist/esm/scan/reparse.d.ts +1 -0
- package/dist/esm/scan/reparse.js +40 -12
- package/dist/esm/scan/reparse.js.map +1 -1
- package/dist/esm/store/builder.d.ts +11 -21
- package/dist/esm/store/builder.js +337 -133
- package/dist/esm/store/builder.js.map +1 -1
- package/dist/esm/store/duckdb/connection.js +9 -1
- package/dist/esm/store/duckdb/connection.js.map +1 -1
- package/dist/esm/store/duckdb/open.d.ts +1 -1
- package/dist/esm/store/duckdb/open.js +13 -9
- package/dist/esm/store/duckdb/open.js.map +1 -1
- package/dist/esm/store/duckdb/reconcile.js +145 -10
- package/dist/esm/store/duckdb/reconcile.js.map +1 -1
- package/dist/esm/store/embed-scope.js +16 -6
- package/dist/esm/store/embed-scope.js.map +1 -1
- package/dist/esm/store/index.d.ts +6 -0
- package/dist/esm/store/index.js +10 -4
- package/dist/esm/store/index.js.map +1 -1
- package/dist/esm/store/open.d.ts +6 -1
- package/dist/esm/store/open.js +77 -87
- package/dist/esm/store/open.js.map +1 -1
- package/dist/esm/store/readiness.d.ts +5 -0
- package/dist/esm/store/readiness.js +11 -0
- package/dist/esm/store/readiness.js.map +1 -0
- package/dist/esm/store/reconcile.d.ts +26 -1
- package/dist/esm/store/reconcile.js +142 -120
- package/dist/esm/store/reconcile.js.map +1 -1
- package/dist/esm/store/signature.d.ts +1 -0
- package/dist/esm/store/signature.js +8 -0
- package/dist/esm/store/signature.js.map +1 -1
- package/dist/esm/store/sqlite/open.d.ts +1 -1
- package/dist/esm/store/sqlite/open.js +12 -12
- package/dist/esm/store/sqlite/open.js.map +1 -1
- package/dist/esm/store/sqlite/reconcile.js +2 -2
- package/dist/esm/store/sqlite/reconcile.js.map +1 -1
- package/dist/esm/store/sqlite/store.js +21 -18
- package/dist/esm/store/sqlite/store.js.map +1 -1
- package/dist/esm/store/sqlite/vectors.d.ts +2 -2
- package/dist/esm/store/sqlite/vectors.js +7 -5
- package/dist/esm/store/sqlite/vectors.js.map +1 -1
- package/dist/esm/store/stages.js.map +1 -1
- package/dist/esm/store/turso/connection.d.ts +1 -0
- package/dist/esm/store/turso/connection.js +97 -28
- package/dist/esm/store/turso/connection.js.map +1 -1
- package/dist/esm/store/turso/open.d.ts +1 -1
- package/dist/esm/store/turso/open.js +9 -8
- package/dist/esm/store/turso/open.js.map +1 -1
- package/dist/esm/store/turso/store.js +16 -14
- package/dist/esm/store/turso/store.js.map +1 -1
- package/dist/esm/store/turso/vectors.d.ts +2 -2
- package/dist/esm/store/turso/vectors.js +27 -17
- package/dist/esm/store/turso/vectors.js.map +1 -1
- package/dist/esm/store/types.d.ts +4 -1
- package/dist/esm/store/types.js.map +1 -1
- package/dist/esm/store/vectors.d.ts +14 -1
- package/dist/esm/store/vectors.js +55 -0
- package/dist/esm/store/vectors.js.map +1 -1
- package/dist/esm/watch.d.ts +6 -0
- package/dist/esm/watch.js +40 -14
- package/dist/esm/watch.js.map +1 -1
- package/dist/esm/workers/parse.d.ts +4 -3
- package/dist/esm/workers/parse.js +19 -17
- package/dist/esm/workers/parse.js.map +1 -1
- package/package.json +1 -1
- package/skills/sense/SKILL.md +4 -2
- package/skills/sense/references/stores/duckdb.md +1 -1
- package/skills/sense-setup/SKILL.md +2 -2
- package/skills/sense-setup/references/embeddings.md +1 -1
- package/skills/sense-setup/references/store-benchmarks.md +5 -5
- package/skills/sense-setup/references/stores/duckdb.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 { recordLockWaitMs } from './lock-wait.ts';\nimport { appendRows, 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 interface ReconcilePaths {\n rootDir: string;\n configDir: string;\n}\n\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 { rootDir, configDir } = paths;\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, rootDir));\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; the rest\n // genuinely can, and keep the upsert.\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) await conn.runBatch(insertSql, updateDocs.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 stages.time('text-index', () => dialect.reconcileContent(conn, contentTouched, parsedDocs, delta, cfg));\n\n // Exact source text belongs to the same indexed generation as content and section ranges.\n // The upsert also covers an added path another writer committed while this build waited.\n if (contentTouched.length > 0)\n await conn.runBatch(\n 'DELETE FROM indexed_sources WHERE \"path\" = ?',\n contentTouched.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 // 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 await appendRows(conn, 'preset_files', ['path', 'preset'], '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(configDir, 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","paths","dialect","pool","forcedPaths","rootDir","configDir","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","appendRows","runBatch","reconcileContent","source","presetRows","presetName","presets","push","feature","featureStage","remove","docsForFeature","extracted","store","afterReconcile","beginMode","recordLockWaitMs","recordDuration"],"mappings":";;;;;;;;;;;QAqBaA;eAAAA;;QAOSC;eAAAA;;;uBA3BS;0BAEN;wBACmB;yBAEf;0BACI;wBACkB;wBACM;6BACzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWzB,IAAMD,2BAA2B,IAAIE,IAAI;IAAC;IAAQ;IAAU;IAAU;IAAS;CAAe;AAO9F,SAAeD,UAAUE,IAAgB,EAAEC,GAAW,EAAEC,KAAqB,EAAEC,OAAyB,EAAEC,IAAgB,EAAEC,WAAiC;;YAC1JC,SAASC,WACXC,OACAC,UACAC,QACAC,SACAC,OACAC,YAEAC,cAIAC,UAIAC,UAIAC,WAOAC,aAIAC,QAE4D,MAApDC,YAAYC,UAAUC,YAAYC,eAE3C,2BAAA,mBAAA,gBAAA,WAAA,OAAMC,KAELC,YAMAC,iBAGAC,WAKAC,OACAC,OACAC,UACAC,kBAGAC,SAEAC,SAsGAC;;;;oBAjKE5B,UAAuBJ,MAAvBI,SAASC,YAAcL,MAAdK;oBACXC,QAAQ2B,QAAQC,MAAM,CAACC,MAAM;oBAC7B5B,WAAW6B,IAAAA,uBAAc,EAACrC;oBAC1BS,SAAS6B,IAAAA,uBAAa,EAAC9B,SAAS+B,GAAG,CAAC,SAACC;+BAAMA,EAAEC,IAAI;;oBACjD/B,UAAU;+BAAMgC,OAAOR,QAAQC,MAAM,CAACC,MAAM,KAAK7B,SAAS;;oBAClD;;wBAAME,OAAOkC,IAAI,CAAC,QAAQ;mCAAMC,IAAAA,mBAAS,EAAC5C,KAAKK;;;;oBAAvDM,QAAQ;oBACRC,aAAa,IAAId,IAAIa,MAAM4B,GAAG,CAAC,SAACC;+BAAMA,EAAEK,OAAO;;oBAEhC;;wBAAMpC,OAAOkC,IAAI,CAAC,YAAY;;oCAC3CG;;;;4CAAe;;gDAAM/C,KAAKgD,OAAO,CAAC;;;4CAAlCD,eAAe;4CACb;;gDAAMA,aAAaE,GAAG;;;4CAA9B;;gDAAQ;;;;4BACV;;;;oBAHMnC,eAAe;oBAIfC,WAAW,IAAImC,IAAIpC,aAAa0B,GAAG,CAAC,SAACW;+BAAM;4BAACA,EAAEC,IAAI;4BAAED;yBAAE;;oBAC5D,+FAA+F;oBAC/F,+FAA+F;oBAC/F,gFAAgF;oBAC1EnC,WAAWF,aAAauC,MAAM,CAAC,SAACF;+BAAM,CAACtC,WAAWyC,GAAG,CAACH,EAAEC,IAAI;uBAAGZ,GAAG,CAAC,SAACW;+BAAMA,EAAEC,IAAI;;oBAEtF,6FAA6F;oBAC7F,0FAA0F;oBACpFnC,YAAYL,MAAMyC,MAAM,CAAC,SAACZ;;wBAC9B,IAAMc,MAAMxC,SAASyC,GAAG,CAACf,EAAEK,OAAO;wBAClC,OAAO,CAACS,OAAOA,IAAIE,MAAM,KAAKhB,EAAEiB,OAAO,IAAIH,IAAII,KAAK,KAAKlB,EAAEmB,IAAI,aAAKvD,wBAAAA,kCAAAA,YAAaiD,GAAG,CAACb,EAAEK,OAAO,wCAAK;oBACrG;oBAEA,IAAI9B,SAAS6C,MAAM,KAAK,KAAK5C,UAAU4C,MAAM,KAAK,GAAG;;wBAAO;4BAAEC,QAAQ;4BAAGzC,QAAQ;4BAAMX,QAAQA,OAAOqD,IAAI,CAACpD,WAAW;wBAAG;;oBAErG;;wBAAMqD,IAAAA,oBAAU,EAAChE;;;oBAA/BkB,cAAc;oBAEpB,oFAAoF;oBACpF,uDAAuD;oBACjDC,SAAS8C,IAAAA,oBAAQ,EAAC,mBAAmBhD,UAAU4C,MAAM;oBAEO;;wBAAMnD,OAAOkC,IAAI,CAAC,SAAS;mCAAMsB,IAAAA,uBAAY,EAACjD,WAAWR,UAAUR,KAAKiB,aAAaC,OAAOgD,IAAI,EAAE;gCAAE/D,MAAAA;4BAAK;;;;oBAAzG,OAAA,eAApDgB,aAAoD,KAA1DgD,MAAkB/C,WAAwC,KAAxCA,UAAUC,aAA8B,KAA9BA,YAAYC,gBAAkB,KAAlBA;oBAChDJ,OAAOkD,MAAM;oBACR,kCAAA,2BAAA;;wBAAL,IAAK,YAAa/C,iCAAb,6BAAA,QAAA,yBAAA;4BAAME,MAAN;4BAAyBN,YAAYoD,GAAG,CAAC9C;;;wBAAzC;wBAAA;;;iCAAA,6BAAA;gCAAA;;;gCAAA;sCAAA;;;;oBAECC,aAAc,qBAAGP;oBACvB,yFAAyF;oBACzF,iGAAiG;oBACjGf,QAAQoE,gBAAgB,CAAC9C,WAAWoC,MAAM;oBAC1C,0FAA0F;oBAC1F,sEAAsE;oBAChEnC,kBAAkBD,WAAW4B,MAAM,CAAC,SAACmB;+BAAM3E,yBAAyByD,GAAG,CAACkB,MAAM,CAACC,0BAAgB,CAACnB,GAAG,CAACkB;;oBAC1G,yFAAyF;oBACzF,mDAAmD;oBAC7C7C,YAAY,AAAC,4BAAkFD,OAAvDA,gBAAgBc,GAAG,CAACkC,oBAAU,EAAEC,IAAI,CAAC,OAAM,cAA4FjD,OAAhFA,gBAAgBc,GAAG,CAAC;+BAAM;uBAAKmC,IAAI,CAAC,OAAM,wCAGjI,OAHuKjD,gBAClL2B,MAAM,CAAC,SAACmB;+BAAMA,MAAM;uBACpBhC,GAAG,CAAC,SAACgC;+BAAM,AAAC,GAA8BE,OAA5BA,IAAAA,oBAAU,EAACF,IAAG,gBAA4B,OAAdE,IAAAA,oBAAU,EAACF;uBACrDG,IAAI,CAAC;oBAEF/C,QAAQX,UAAUoC,MAAM,CAAC,SAACZ;+BAAM,CAAC1B,SAASuC,GAAG,CAACb,EAAEK,OAAO;uBAAGN,GAAG,CAAC,SAACC;+BAAMA,EAAEK,OAAO;;oBAC9EjB,QAAwB;wBAAEjB,OAAAA;wBAAOgE,UAAUxD,WAAWoB,GAAG,CAAC,SAACqC;mCAAMA,EAAE/B,OAAO;;wBAAGlB,OAAAA;wBAAOZ,UAAAA;oBAAS;oBAC7Fc,WAAW,IAAI/B,IAAI6B;oBACnBG,mBAAmBX,WAAWoB,GAAG,CAAC,SAACqC;+BAAMA,EAAE/B,OAAO;uBAAEO,MAAM,CAAC,SAACyB;+BAAM,CAAChD,SAASwB,GAAG,CAACwB;;oBACtF,+FAA+F;oBAC/F,0EAA0E;oBACpE9C,UAAU,AAAC,qBAAGhB,iBAAU,qBAAGe;oBAE3BE,UAAU8C,KAAKC,GAAG;oBACxB;;wBAAMC,IAAAA,8BAAe,EACnBjF,MACA;;oCAGQkF,SACAC,gBAQFC,gBAUIC,OAmEqB,2BAAA,mBAAA,uBAAA,WAAA,YACxB,4BAAA,oBAAA,yBAAA,YAAA,aAIA,4BAAA,oBAAA,yBAAA,YAAA;;;;4CA3FW;;gDAAMrB,IAAAA,oBAAU,EAAChE;;;4CAA3BkF,UAAU;4CACVC,iBAAiB7D,WAAW+B,MAAM,CAAC,SAAC7B;uDAAQ,CAAC0D,QAAQ5B,GAAG,CAAC9B;;iDAC3D2D,CAAAA,eAAetB,MAAM,GAAG,CAAA,GAAxBsB;;;;4CAA2B;;gDAAMzE,OAAOkC,IAAI,CAAC,SAAS;2DAAMzC,QAAQmF,UAAU,CAACtF,MAAMmF;;;;4CAA1D;;;4CAE/B,yFAAyF;4CACzF,sFAAsF;4CACtF,sFAAsF;4CACtF,sFAAsF;4CACtF,4FAA4F;4CACxFC,iBAAiBpD;iDACjBJ,CAAAA,MAAMiC,MAAM,GAAG,CAAA,GAAfjC;;;;4CACe;;gDAAMlB,OAAOkC,IAAI,CAAC,iBAAiB;;4DAC5C2C,kBACAC,iBACAC;;;;oEAFmB;;wEAAMzF,KAAKgD,OAAO,CAAC;;;oEAAtCuC,mBAAmB;wEACAxF;oEAAM;;wEAAMwF,iBAAiBtC,GAAG;;;oEAAnDuC,eAAe,IAAA,CAAA,EAAA,MAAIzF;;wEAAM,cAA0DyC,GAAG,CAAC,SAACW;mFAAMA,EAAEC,IAAI;;sEAAC;oEACrGqC,aAAa7D,MAAMyB,MAAM,CAAC,SAACyB;+EAAMU,aAAalC,GAAG,CAACwB;;oEACxD;;wEAAOW,WAAW5B,MAAM,GAAG,IAAI,AAAC,qBAAG7B,gBAAS,qBAAGyD,eAAczD;;;;oDAC/D;;;;4CALAoD,iBAAiB;;;iDAOfhE,CAAAA,WAAWyC,MAAM,GAAG,CAAA,GAApBzC;;;;4CACIiE,QAAQ,eAACK;uDACbhE,gBAAgBc,GAAG,CAAC,SAAChB;wDAOZkE;oDANP,IAAIlE,QAAQ,QAAQ,OAAOkE,IAAI5C,OAAO;oDACtC,IAAItB,QAAQ,UAAU,OAAOkE,IAAIhC,OAAO;oDACxC,IAAIlC,QAAQ,UAAU,OAAOkE,IAAIC,OAAO;oDACxC,IAAInE,QAAQ,SAAS,OAAOkE,IAAI9B,IAAI;oDACpC,mFAAmF;oDACnF,IAAIpC,QAAQ,gBAAgB,OAAOkE,IAAIE,UAAU;oDACjD,QAAOF,gBAAAA,IAAIG,IAAI,CAACrE,IAAI,cAAbkE,2BAAAA,gBAAiB;gDAC1B;;4CACF,wFAAwF;4CACxF,sCAAsC;4CACtC;;gDAAMhF,OAAOkC,IAAI,CAAC,aAAa;;4DACvBkD,SACAC;;;;oEADAD,UAAU1E,WAAWiC,MAAM,CAAC,SAACwB;+EAAM/C,SAASwB,GAAG,CAACuB,EAAE/B,OAAO;;oEACzDiD,aAAa3E,WAAWiC,MAAM,CAAC,SAACwB;+EAAM,CAAC/C,SAASwB,GAAG,CAACuB,EAAE/B,OAAO;;oEACnE;;wEAAMkD,IAAAA,oBAAU,EAAChG,MAAM,eAAe0B,iBAAiBC,WAAWmE,QAAQtD,GAAG,CAAC6C;;;oEAA9E;yEACIU,CAAAA,WAAWlC,MAAM,GAAG,CAAA,GAApBkC;;;;oEAAuB;;wEAAM/F,KAAKiG,QAAQ,CAACtE,WAAWoE,WAAWvD,GAAG,CAAC6C;;;oEAA9C;;;;;;;;oDAC7B;;;;4CALA;;;4CAQF,wFAAwF;4CACxF,2FAA2F;4CAC3F;;gDAAM3E,OAAOkC,IAAI,CAAC,cAAc;2DAAMzC,QAAQ+F,gBAAgB,CAAClG,MAAMoF,gBAAgBhE,YAAYS,OAAO5B;;;;4CAAxG;iDAIImF,CAAAA,eAAevB,MAAM,GAAG,CAAA,GAAxBuB;;;;4CACF;;gDAAMpF,KAAKiG,QAAQ,CACjB,gDACAb,eAAe5C,GAAG,CAAC,SAACsC;2DAAM;wDAACA;qDAAE;;;;4CAF/B;;;4CAIF;;gDAAMkB,IAAAA,oBAAU,EACdhG,MACA;oDACC;oDAAQ;mDACT,mHACAoB,WAAWoB,GAAG,CAAC,SAACkD;2DAAQ;wDAACA,IAAI5C,OAAO;wDAAE4C,IAAIS,MAAM;qDAAC;;;;4CALnD;4CAQA,0FAA0F;4CAC1F,kEAAkE;4CAClE;;gDAAMzF,OAAOkC,IAAI,CAAC,WAAW;;4DAMrBwD,YAC6B,2BAAA,mBAAA,gBAA9B,4BAAA,oBAAA,iBAAA,WAAA,OAAMV,KAAwB,YAAA,QAAMW;;;;yEANrCrE,CAAAA,QAAQ6B,MAAM,GAAG,CAAA,GAAjB7B;;;;oEACF;;wEAAMhC,KAAKiG,QAAQ,CACjB,6CACAjE,QAAQQ,GAAG,CAAC,SAACsC;mFAAM;gFAACA;6EAAE;;;;oEAFxB;;;oEAIIsB;oEAC6B,kCAAA,2BAAA,4BAA9B,mCAAA,4BAAA;;wEAAL,IAAK,YAAahF,iCAAb,8BAAA,QAAA,yBAAA;4EAAMsE,MAAN;;gFAAyB,IAAK,aAAoBA,IAAIY,OAAO,uBAA/B,6BAAA,SAAA,0BAAA;oFAAMD,aAAN;oFAAiCD,WAAWG,IAAI;wFAAEb,IAAI5C,OAAO;wFAAEuD;;;;gFAA/D;gFAAA;;;yFAAA,6BAAA;wFAAA;;;wFAAA;8FAAA;;;;;;wEAA9B;wEAAA;;;iFAAA,8BAAA;gFAAA;;;gFAAA;sFAAA;;;;oEACL,uFAAuF;oEACvF,wFAAwF;oEACxF,uGAAuG;oEACvG;;wEAAML,IAAAA,oBAAU,EAAChG,MAAM;4EAAiB;4EAAQ;2EAAW,kGAAkGoG;;;oEAA7J;;;;;;oDACF;;;;4CAZA;iDAgBIpF,CAAAA,SAAS6C,MAAM,GAAG,CAAA,GAAlB7C;;;;4CACF;;gDAAMN,OAAOkC,IAAI,CAAC,YAAY;2DAC5B5C,KAAKiG,QAAQ,CACX,4CACAjF,SAASwB,GAAG,CAAC,SAACsC;+DAAM;4DAACA;yDAAE;;;;;4CAH3B;;;4CAS2B,kCAAA,2BAAA;iDAAzB9C,CAAAA,QAAQ6B,MAAM,GAAG,CAAA,GAAjB7B;;;;;;;;;;;;;oDAA+BwE;;;;4DAAAA,UAAN;4DAA2B;;gEAAM9F,OAAOkC,IAAI,CAAC6D,IAAAA,sBAAY,EAACD,QAAQ9D,IAAI,EAAE,WAAW;wEAAM8D;4EAAAA,kBAAAA,QAAQE,MAAM,cAAdF,sCAAAA,qBAAAA,SAAiBxG,MAAMgC,SAASH;;;;4DAA9F;;;;;;;4CAA3B,YAAiBpB;;;mDAAjB,6BAAA,QAAA;;;;;;;;;;;;4CAAA;;;;;;;;;;;;4CAAA;4CAAA;;;;;;;qDAAA,6BAAA;oDAAA;;;oDAAA;0DAAA;;;;;;;4CACxB,mCAAA,4BAAA;;;;;;;;;;oDAAM+F,SACHG;;;;4DADGH,UAAN;4DACGG,iBAAiCvF,WAAWoB,GAAG,CAAC,SAACkD;uEAAS;oEAAEtC,MAAMsC,IAAI5C,OAAO;oEAAE8D,WAAWlB,IAAIkB,SAAS,CAACJ,QAAQ9D,IAAI,CAAC;gEAAC;;4DAC5H;;gEAAMhC,OAAOkC,IAAI,CAAC6D,IAAAA,sBAAY,EAACD,QAAQ9D,IAAI,EAAE,UAAU;wEAAM8D;4EAAAA,iBAAAA,QAAQK,KAAK,cAAbL,qCAAAA,oBAAAA,SAAgBxG,MAAM2G,gBAAgB9E;;;;4DAAnG;;;;;;4CACF;4CAHK,aAAiBpB;;;mDAAjB,8BAAA,SAAA;;;;;;;;;;;;4CAAA;;;;;;;;;;;;4CAAA;4CAAA;;;;;;;qDAAA,8BAAA;oDAAA;;;oDAAA;0DAAA;;;;;;;4CAIA,mCAAA,4BAAA;;;;;;;;;;oDAAM+F;;;;4DAAAA,UAAN;4DAA2B;;gEAAM9F,OAAOkC,IAAI,CAAC6D,IAAAA,sBAAY,EAACD,QAAQ9D,IAAI,EAAE,UAAU;wEAAM8D;4EAAAA,0BAAAA,QAAQM,cAAc,cAAtBN,8CAAAA,6BAAAA,SAAyBxG,MAAM6B;;;;4DAA5F;;;;;;;4CAA3B,aAAiBpB;;;mDAAjB,8BAAA,SAAA;;;;;;;;;;;;4CAAA;;;;;;;;;;;;4CAAA;4CAAA;;;;;;;qDAAA,8BAAA;oDAAA;;;oDAAA;0DAAA;;;;;;;;;;;;4BACP;2BACAN,QAAQ4G,SAAS;;;oBAlGnB;oBAqGM7E,aAAa6C,KAAKC,GAAG,KAAK/C;oBAChC,2GAA2G;oBAC3G+E,IAAAA,4BAAgB,EAACzG,WAAW2B;yBACxB/B,QAAQ8G,cAAc,EAAtB9G;;;;oBAAwB;;wBAAMO,OAAOkC,IAAI,CAAC,QAAQ;gCAAMzC;oCAAAA,0BAAAA,QAAQ8G,cAAc,cAAtB9G,8CAAAA,6BAAAA,SAAyBH,MAAMkC;;;;oBAA/D;;;oBAE5B;;wBAAO;4BAAE4B,QAAQ1C,WAAWyC,MAAM;4BAAExC,UAAAA;4BAAUX,QAAQA,OAAOqD,IAAI,CAACpD,WAAWuB,YAAYX;wBAAe;;;;IAC1G"}
|
|
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":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare function changedSignatureKeys(before: string, after: string): Set<string>;
|
|
2
2
|
export declare function embedIdentityAdopted(before: string, after: string): boolean;
|
|
3
|
+
export declare function embeddingSignatureCompatible(expected: string | null, actual: string): boolean;
|
|
3
4
|
export declare function signatureDiff(before: string, after: string): string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare function changedSignatureKeys(before: string, after: string): Set<string>;
|
|
2
2
|
export declare function embedIdentityAdopted(before: string, after: string): boolean;
|
|
3
|
+
export declare function embeddingSignatureCompatible(expected: string | null, actual: string): boolean;
|
|
3
4
|
export declare function signatureDiff(before: string, after: string): string;
|
|
@@ -21,6 +21,9 @@ _export(exports, {
|
|
|
21
21
|
get embedIdentityAdopted () {
|
|
22
22
|
return embedIdentityAdopted;
|
|
23
23
|
},
|
|
24
|
+
get embeddingSignatureCompatible () {
|
|
25
|
+
return embeddingSignatureCompatible;
|
|
26
|
+
},
|
|
24
27
|
get signatureDiff () {
|
|
25
28
|
return signatureDiff;
|
|
26
29
|
}
|
|
@@ -154,6 +157,12 @@ function embedIdentityAdopted(before, after) {
|
|
|
154
157
|
var at = a.indexOf('@');
|
|
155
158
|
return b.indexOf('@') === -1 && at !== -1 && a.slice(0, at) === b;
|
|
156
159
|
}
|
|
160
|
+
function embeddingSignatureCompatible(expected, actual) {
|
|
161
|
+
if (expected === actual) return true;
|
|
162
|
+
if (expected === null) return false;
|
|
163
|
+
var changed = changedSignatureKeys(expected, actual);
|
|
164
|
+
return changed.size === 1 && changed.has('embed') && embedIdentityAdopted(expected, actual);
|
|
165
|
+
}
|
|
157
166
|
function signatureDiff(before, after) {
|
|
158
167
|
var changed = changedSignatureKeys(before, after);
|
|
159
168
|
var label = function label(key) {
|
|
@@ -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// 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","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","
|
|
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"}
|
|
@@ -3,7 +3,7 @@ import type { ResolvedConfig } from '../../config/index.js';
|
|
|
3
3
|
import type { InternalOpenOptions, OpenResult } from '../open.js';
|
|
4
4
|
import type { OpenDialect } from '../types.js';
|
|
5
5
|
export declare const DB_FILENAME = "cache.db";
|
|
6
|
-
export declare const SCHEMA_VERSION = "
|
|
6
|
+
export declare const SCHEMA_VERSION = "22";
|
|
7
7
|
export type { OpenResult };
|
|
8
8
|
interface SqliteHandle {
|
|
9
9
|
db: DatabaseSync;
|
|
@@ -3,7 +3,7 @@ import type { ResolvedConfig } from '../../config/index.js';
|
|
|
3
3
|
import type { InternalOpenOptions, OpenResult } from '../open.js';
|
|
4
4
|
import type { OpenDialect } from '../types.js';
|
|
5
5
|
export declare const DB_FILENAME = "cache.db";
|
|
6
|
-
export declare const SCHEMA_VERSION = "
|
|
6
|
+
export declare const SCHEMA_VERSION = "22";
|
|
7
7
|
export type { OpenResult };
|
|
8
8
|
interface SqliteHandle {
|
|
9
9
|
db: DatabaseSync;
|
|
@@ -25,8 +25,7 @@ _export(exports, {
|
|
|
25
25
|
}
|
|
26
26
|
});
|
|
27
27
|
var _nodesqlite = require("node:sqlite");
|
|
28
|
-
var _indexts = require("../../
|
|
29
|
-
var _indexts1 = require("../../features/index.js");
|
|
28
|
+
var _indexts = require("../../features/index.js");
|
|
30
29
|
var _opents = require("../open.js");
|
|
31
30
|
var _sharedts = require("../shared.js");
|
|
32
31
|
var _transactionts = require("../transaction.js");
|
|
@@ -160,7 +159,7 @@ function _ts_generator(thisArg, body) {
|
|
|
160
159
|
}
|
|
161
160
|
}
|
|
162
161
|
var DB_FILENAME = 'cache.db';
|
|
163
|
-
var SCHEMA_VERSION = '
|
|
162
|
+
var SCHEMA_VERSION = '22';
|
|
164
163
|
// unicode61 splits on spaces, so a language written without them indexes a whole run as one
|
|
165
164
|
// token and word search finds nothing; the `_seg` sidecars (always populated) cover that case.
|
|
166
165
|
var TOKENIZE = 'porter unicode61';
|
|
@@ -185,10 +184,9 @@ function createContentTable(conn) {
|
|
|
185
184
|
})();
|
|
186
185
|
}
|
|
187
186
|
// Content is a separate table (not a column on frontmatter) so `SELECT * FROM frontmatter`
|
|
188
|
-
// can't dump file text into context.
|
|
189
|
-
function
|
|
187
|
+
// can't dump file text into context. Feature schema is published later with its generation.
|
|
188
|
+
function ensureCoreSchemaTables(conn) {
|
|
190
189
|
return _async_to_generator(function() {
|
|
191
|
-
var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, feature, err;
|
|
192
190
|
return _ts_generator(this, function(_state) {
|
|
193
191
|
switch(_state.label){
|
|
194
192
|
case 0:
|
|
@@ -224,97 +222,23 @@ function ensureSchemaTables(conn, cfg) {
|
|
|
224
222
|
];
|
|
225
223
|
case 5:
|
|
226
224
|
_state.sent();
|
|
227
|
-
_iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
228
|
-
_state.label = 6;
|
|
229
|
-
case 6:
|
|
230
|
-
_state.trys.push([
|
|
231
|
-
6,
|
|
232
|
-
11,
|
|
233
|
-
12,
|
|
234
|
-
13
|
|
235
|
-
]);
|
|
236
|
-
_iterator = (0, _indexts1.activeFeatures)(cfg)[Symbol.iterator]();
|
|
237
|
-
_state.label = 7;
|
|
238
|
-
case 7:
|
|
239
|
-
if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
|
|
240
|
-
3,
|
|
241
|
-
10
|
|
242
|
-
];
|
|
243
|
-
feature = _step.value;
|
|
244
|
-
return [
|
|
245
|
-
4,
|
|
246
|
-
feature.schema(conn)
|
|
247
|
-
];
|
|
248
|
-
case 8:
|
|
249
|
-
_state.sent();
|
|
250
|
-
_state.label = 9;
|
|
251
|
-
case 9:
|
|
252
|
-
_iteratorNormalCompletion = true;
|
|
253
|
-
return [
|
|
254
|
-
3,
|
|
255
|
-
7
|
|
256
|
-
];
|
|
257
|
-
case 10:
|
|
258
|
-
return [
|
|
259
|
-
3,
|
|
260
|
-
13
|
|
261
|
-
];
|
|
262
|
-
case 11:
|
|
263
|
-
err = _state.sent();
|
|
264
|
-
_didIteratorError = true;
|
|
265
|
-
_iteratorError = err;
|
|
266
|
-
return [
|
|
267
|
-
3,
|
|
268
|
-
13
|
|
269
|
-
];
|
|
270
|
-
case 12:
|
|
271
|
-
try {
|
|
272
|
-
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
273
|
-
_iterator.return();
|
|
274
|
-
}
|
|
275
|
-
} finally{
|
|
276
|
-
if (_didIteratorError) {
|
|
277
|
-
throw _iteratorError;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
return [
|
|
281
|
-
7
|
|
282
|
-
];
|
|
283
|
-
case 13:
|
|
284
225
|
return [
|
|
285
226
|
4,
|
|
286
227
|
(0, _sharedts.getMeta)(conn, 'schema_version')
|
|
287
228
|
];
|
|
288
|
-
case
|
|
229
|
+
case 6:
|
|
289
230
|
if (!(_state.sent() === null)) return [
|
|
290
231
|
3,
|
|
291
|
-
|
|
232
|
+
8
|
|
292
233
|
];
|
|
293
234
|
return [
|
|
294
235
|
4,
|
|
295
236
|
(0, _sharedts.setMeta)(conn, 'schema_version', SCHEMA_VERSION)
|
|
296
237
|
];
|
|
297
|
-
case
|
|
298
|
-
_state.sent();
|
|
299
|
-
_state.label = 16;
|
|
300
|
-
case 16:
|
|
301
|
-
return [
|
|
302
|
-
4,
|
|
303
|
-
(0, _sharedts.getMeta)(conn, 'features')
|
|
304
|
-
];
|
|
305
|
-
case 17:
|
|
306
|
-
if (!(_state.sent() === null)) return [
|
|
307
|
-
3,
|
|
308
|
-
19
|
|
309
|
-
];
|
|
310
|
-
return [
|
|
311
|
-
4,
|
|
312
|
-
(0, _sharedts.setMeta)(conn, 'features', (0, _indexts.featureSignature)(cfg, _indexts1.FEATURES))
|
|
313
|
-
];
|
|
314
|
-
case 18:
|
|
238
|
+
case 7:
|
|
315
239
|
_state.sent();
|
|
316
|
-
_state.label =
|
|
317
|
-
case
|
|
240
|
+
_state.label = 8;
|
|
241
|
+
case 8:
|
|
318
242
|
return [
|
|
319
243
|
2
|
|
320
244
|
];
|
|
@@ -383,17 +307,16 @@ function close(handle) {
|
|
|
383
307
|
});
|
|
384
308
|
})();
|
|
385
309
|
}
|
|
386
|
-
function
|
|
310
|
+
function ensureCoreSchema(_handle, conn) {
|
|
387
311
|
return _async_to_generator(function() {
|
|
388
312
|
return _ts_generator(this, function(_state) {
|
|
389
313
|
switch(_state.label){
|
|
390
314
|
case 0:
|
|
391
|
-
// One writer at a time:
|
|
392
|
-
// here both see it missing and the second ALTER fails with a duplicate column.
|
|
315
|
+
// One writer at a time: two cold opens can bootstrap the same database concurrently.
|
|
393
316
|
return [
|
|
394
317
|
4,
|
|
395
318
|
(0, _transactionts.withTransaction)(conn, function() {
|
|
396
|
-
return
|
|
319
|
+
return ensureCoreSchemaTables(conn);
|
|
397
320
|
}, _transactionts.BEGIN_WRITE)
|
|
398
321
|
];
|
|
399
322
|
case 1:
|
|
@@ -405,6 +328,76 @@ function ensureSchema(_handle, conn, cfg) {
|
|
|
405
328
|
});
|
|
406
329
|
})();
|
|
407
330
|
}
|
|
331
|
+
function ensureFeatureSchema(_handle, conn, cfg) {
|
|
332
|
+
return _async_to_generator(function() {
|
|
333
|
+
var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, feature, err;
|
|
334
|
+
return _ts_generator(this, function(_state) {
|
|
335
|
+
switch(_state.label){
|
|
336
|
+
case 0:
|
|
337
|
+
_iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
338
|
+
_state.label = 1;
|
|
339
|
+
case 1:
|
|
340
|
+
_state.trys.push([
|
|
341
|
+
1,
|
|
342
|
+
6,
|
|
343
|
+
7,
|
|
344
|
+
8
|
|
345
|
+
]);
|
|
346
|
+
_iterator = (0, _indexts.activeFeatures)(cfg)[Symbol.iterator]();
|
|
347
|
+
_state.label = 2;
|
|
348
|
+
case 2:
|
|
349
|
+
if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
|
|
350
|
+
3,
|
|
351
|
+
5
|
|
352
|
+
];
|
|
353
|
+
feature = _step.value;
|
|
354
|
+
return [
|
|
355
|
+
4,
|
|
356
|
+
feature.schema(conn)
|
|
357
|
+
];
|
|
358
|
+
case 3:
|
|
359
|
+
_state.sent();
|
|
360
|
+
_state.label = 4;
|
|
361
|
+
case 4:
|
|
362
|
+
_iteratorNormalCompletion = true;
|
|
363
|
+
return [
|
|
364
|
+
3,
|
|
365
|
+
2
|
|
366
|
+
];
|
|
367
|
+
case 5:
|
|
368
|
+
return [
|
|
369
|
+
3,
|
|
370
|
+
8
|
|
371
|
+
];
|
|
372
|
+
case 6:
|
|
373
|
+
err = _state.sent();
|
|
374
|
+
_didIteratorError = true;
|
|
375
|
+
_iteratorError = err;
|
|
376
|
+
return [
|
|
377
|
+
3,
|
|
378
|
+
8
|
|
379
|
+
];
|
|
380
|
+
case 7:
|
|
381
|
+
try {
|
|
382
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
383
|
+
_iterator.return();
|
|
384
|
+
}
|
|
385
|
+
} finally{
|
|
386
|
+
if (_didIteratorError) {
|
|
387
|
+
throw _iteratorError;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return [
|
|
391
|
+
7
|
|
392
|
+
];
|
|
393
|
+
case 8:
|
|
394
|
+
return [
|
|
395
|
+
2
|
|
396
|
+
];
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
})();
|
|
400
|
+
}
|
|
408
401
|
function setDerivedBusyTimeout(handle, _conn, ms) {
|
|
409
402
|
return _async_to_generator(function() {
|
|
410
403
|
return _ts_generator(this, function(_state) {
|
|
@@ -421,7 +414,8 @@ var sqliteOpenDialect = {
|
|
|
421
414
|
reconcileDialect: _reconcilets.sqliteDialect,
|
|
422
415
|
connect: connect,
|
|
423
416
|
close: close,
|
|
424
|
-
|
|
417
|
+
ensureCoreSchema: ensureCoreSchema,
|
|
418
|
+
ensureFeatureSchema: ensureFeatureSchema,
|
|
425
419
|
setDerivedBusyTimeout: setDerivedBusyTimeout,
|
|
426
420
|
createStore: function createStore(handle, conn) {
|
|
427
421
|
return (0, _storets.createStore)(handle.db, conn);
|
|
@@ -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 {
|
|
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 +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 //
|
|
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"}
|