sensemaking 0.9.5 → 0.11.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 (177) hide show
  1. package/README.md +27 -22
  2. package/dist/cjs/cli/download.d.cts +3 -0
  3. package/dist/cjs/cli/download.d.ts +3 -0
  4. package/dist/cjs/cli/download.js +214 -0
  5. package/dist/cjs/cli/download.js.map +1 -0
  6. package/dist/cjs/cli/index.d.cts +6 -5
  7. package/dist/cjs/cli/index.d.ts +6 -5
  8. package/dist/cjs/cli/index.js +20 -14
  9. package/dist/cjs/cli/index.js.map +1 -1
  10. package/dist/cjs/cli/init.js +4 -1
  11. package/dist/cjs/cli/init.js.map +1 -1
  12. package/dist/cjs/cli/map.js +2 -2
  13. package/dist/cjs/cli/map.js.map +1 -1
  14. package/dist/cjs/cli/named.js +13 -19
  15. package/dist/cjs/cli/named.js.map +1 -1
  16. package/dist/cjs/cli/path.d.cts +3 -0
  17. package/dist/cjs/cli/path.d.ts +3 -0
  18. package/dist/cjs/cli/path.js +161 -0
  19. package/dist/cjs/cli/path.js.map +1 -0
  20. package/dist/cjs/cli/peek.js +3 -2
  21. package/dist/cjs/cli/peek.js.map +1 -1
  22. package/dist/cjs/cli/related.d.cts +3 -0
  23. package/dist/cjs/cli/related.d.ts +3 -0
  24. package/dist/cjs/cli/related.js +279 -0
  25. package/dist/cjs/cli/related.js.map +1 -0
  26. package/dist/cjs/cli/search.js +3 -7
  27. package/dist/cjs/cli/search.js.map +1 -1
  28. package/dist/cjs/cli/shared.d.cts +4 -2
  29. package/dist/cjs/cli/shared.d.ts +4 -2
  30. package/dist/cjs/cli/shared.js +49 -6
  31. package/dist/cjs/cli/shared.js.map +1 -1
  32. package/dist/cjs/cli/sql.d.cts +3 -0
  33. package/dist/cjs/cli/sql.d.ts +3 -0
  34. package/dist/cjs/cli/{query.js → sql.js} +33 -5
  35. package/dist/cjs/cli/sql.js.map +1 -0
  36. package/dist/cjs/cli/status.d.cts +1 -0
  37. package/dist/cjs/cli/status.d.ts +1 -0
  38. package/dist/cjs/cli/status.js +80 -10
  39. package/dist/cjs/cli/status.js.map +1 -1
  40. package/dist/cjs/cli.js +14 -15
  41. package/dist/cjs/cli.js.map +1 -1
  42. package/dist/cjs/commands.d.cts +13 -4
  43. package/dist/cjs/commands.d.ts +13 -4
  44. package/dist/cjs/commands.js +161 -61
  45. package/dist/cjs/commands.js.map +1 -1
  46. package/dist/cjs/config.d.cts +6 -4
  47. package/dist/cjs/config.d.ts +6 -4
  48. package/dist/cjs/config.js +137 -58
  49. package/dist/cjs/config.js.map +1 -1
  50. package/dist/cjs/db.d.cts +2 -2
  51. package/dist/cjs/db.d.ts +2 -2
  52. package/dist/cjs/db.js +25 -46
  53. package/dist/cjs/db.js.map +1 -1
  54. package/dist/cjs/errors.d.cts +1 -1
  55. package/dist/cjs/errors.d.ts +1 -1
  56. package/dist/cjs/errors.js.map +1 -1
  57. package/dist/cjs/features/embed.d.cts +15 -0
  58. package/dist/cjs/features/embed.d.ts +15 -0
  59. package/dist/cjs/features/embed.js +277 -61
  60. package/dist/cjs/features/embed.js.map +1 -1
  61. package/dist/cjs/features/links.js +7 -16
  62. package/dist/cjs/features/links.js.map +1 -1
  63. package/dist/cjs/features/rank.js +2 -6
  64. package/dist/cjs/features/rank.js.map +1 -1
  65. package/dist/cjs/index.d.cts +2 -2
  66. package/dist/cjs/index.d.ts +2 -2
  67. package/dist/cjs/index.js +3 -3
  68. package/dist/cjs/index.js.map +1 -1
  69. package/dist/cjs/output.d.cts +3 -0
  70. package/dist/cjs/output.d.ts +3 -0
  71. package/dist/cjs/output.js +17 -15
  72. package/dist/cjs/output.js.map +1 -1
  73. package/dist/cjs/progress.js +2 -4
  74. package/dist/cjs/progress.js.map +1 -1
  75. package/dist/cjs/scan.d.cts +2 -0
  76. package/dist/cjs/scan.d.ts +2 -0
  77. package/dist/cjs/scan.js +150 -44
  78. package/dist/cjs/scan.js.map +1 -1
  79. package/dist/cjs/search-error.js +4 -6
  80. package/dist/cjs/search-error.js.map +1 -1
  81. package/dist/cjs/traverse.d.cts +8 -0
  82. package/dist/cjs/traverse.d.ts +8 -0
  83. package/dist/cjs/traverse.js +97 -0
  84. package/dist/cjs/traverse.js.map +1 -0
  85. package/dist/esm/cli/download.d.ts +3 -0
  86. package/dist/esm/cli/download.js +27 -0
  87. package/dist/esm/cli/download.js.map +1 -0
  88. package/dist/esm/cli/index.d.ts +6 -5
  89. package/dist/esm/cli/index.js +13 -11
  90. package/dist/esm/cli/index.js.map +1 -1
  91. package/dist/esm/cli/init.js +4 -1
  92. package/dist/esm/cli/init.js.map +1 -1
  93. package/dist/esm/cli/map.js +3 -2
  94. package/dist/esm/cli/map.js.map +1 -1
  95. package/dist/esm/cli/named.js +13 -17
  96. package/dist/esm/cli/named.js.map +1 -1
  97. package/dist/esm/cli/path.d.ts +3 -0
  98. package/dist/esm/cli/path.js +51 -0
  99. package/dist/esm/cli/path.js.map +1 -0
  100. package/dist/esm/cli/peek.js +4 -2
  101. package/dist/esm/cli/peek.js.map +1 -1
  102. package/dist/esm/cli/related.d.ts +3 -0
  103. package/dist/esm/cli/related.js +26 -0
  104. package/dist/esm/cli/related.js.map +1 -0
  105. package/dist/esm/cli/search.js +2 -5
  106. package/dist/esm/cli/search.js.map +1 -1
  107. package/dist/esm/cli/shared.d.ts +4 -2
  108. package/dist/esm/cli/shared.js +49 -6
  109. package/dist/esm/cli/shared.js.map +1 -1
  110. package/dist/esm/cli/sql.d.ts +3 -0
  111. package/dist/esm/cli/{query.js → sql.js} +8 -5
  112. package/dist/esm/cli/sql.js.map +1 -0
  113. package/dist/esm/cli/status.d.ts +1 -0
  114. package/dist/esm/cli/status.js +72 -8
  115. package/dist/esm/cli/status.js.map +1 -1
  116. package/dist/esm/cli.js +13 -10
  117. package/dist/esm/cli.js.map +1 -1
  118. package/dist/esm/commands.d.ts +13 -4
  119. package/dist/esm/commands.js +135 -72
  120. package/dist/esm/commands.js.map +1 -1
  121. package/dist/esm/config.d.ts +6 -4
  122. package/dist/esm/config.js +126 -75
  123. package/dist/esm/config.js.map +1 -1
  124. package/dist/esm/db.d.ts +2 -2
  125. package/dist/esm/db.js +28 -48
  126. package/dist/esm/db.js.map +1 -1
  127. package/dist/esm/errors.d.ts +1 -1
  128. package/dist/esm/errors.js.map +1 -1
  129. package/dist/esm/features/embed.d.ts +15 -0
  130. package/dist/esm/features/embed.js +137 -42
  131. package/dist/esm/features/embed.js.map +1 -1
  132. package/dist/esm/features/links.js +8 -17
  133. package/dist/esm/features/links.js.map +1 -1
  134. package/dist/esm/features/rank.js +2 -6
  135. package/dist/esm/features/rank.js.map +1 -1
  136. package/dist/esm/features/types.js.map +1 -1
  137. package/dist/esm/index.d.ts +2 -2
  138. package/dist/esm/index.js +1 -1
  139. package/dist/esm/index.js.map +1 -1
  140. package/dist/esm/output.d.ts +3 -0
  141. package/dist/esm/output.js +19 -17
  142. package/dist/esm/output.js.map +1 -1
  143. package/dist/esm/progress.js +2 -4
  144. package/dist/esm/progress.js.map +1 -1
  145. package/dist/esm/scan.d.ts +2 -0
  146. package/dist/esm/scan.js +123 -47
  147. package/dist/esm/scan.js.map +1 -1
  148. package/dist/esm/search-error.js +4 -6
  149. package/dist/esm/search-error.js.map +1 -1
  150. package/dist/esm/traverse.d.ts +8 -0
  151. package/dist/esm/traverse.js +71 -0
  152. package/dist/esm/traverse.js.map +1 -0
  153. package/package.json +7 -3
  154. package/schema.json +12 -16
  155. package/skills/sense/EXAMPLES.md +8 -8
  156. package/skills/sense/SKILL.md +51 -23
  157. package/skills/sense-setup/EXAMPLES.md +24 -21
  158. package/skills/sense-setup/SKILL.md +9 -9
  159. package/dist/cjs/cli/check.d.cts +0 -3
  160. package/dist/cjs/cli/check.d.ts +0 -3
  161. package/dist/cjs/cli/check.js +0 -398
  162. package/dist/cjs/cli/check.js.map +0 -1
  163. package/dist/cjs/cli/query.d.cts +0 -3
  164. package/dist/cjs/cli/query.d.ts +0 -3
  165. package/dist/cjs/cli/query.js.map +0 -1
  166. package/dist/cjs/cli/rebuild.d.cts +0 -3
  167. package/dist/cjs/cli/rebuild.d.ts +0 -3
  168. package/dist/cjs/cli/rebuild.js +0 -50
  169. package/dist/cjs/cli/rebuild.js.map +0 -1
  170. package/dist/esm/cli/check.d.ts +0 -3
  171. package/dist/esm/cli/check.js +0 -94
  172. package/dist/esm/cli/check.js.map +0 -1
  173. package/dist/esm/cli/query.d.ts +0 -3
  174. package/dist/esm/cli/query.js.map +0 -1
  175. package/dist/esm/cli/rebuild.d.ts +0 -3
  176. package/dist/esm/cli/rebuild.js +0 -13
  177. package/dist/esm/cli/rebuild.js.map +0 -1
@@ -192,13 +192,9 @@ function resolveAll(db, files) {
192
192
  var rows = db.prepare('SELECT src, target, dst FROM links').all();
193
193
  return resolveRows(db, rows, pathSet, byBase);
194
194
  }
195
- // Re-resolve only what this reconcile could have affected: (a) links whose src was just
196
- // re-stored (their rows are fresh, dst reset to NULL by store()), (b) links whose target's
197
- // basename matches a file that appeared or disappeared this reconcile (resolution and
198
- // lexicographic-tie ambiguity hinge on exactly that set), and (c) links whose dst was a
199
- // path that just vanished. All three are indexed lookups (src is the links PK's leading
200
- // column; target_base and dst each have their own index), so this reads only the rows this
201
- // reconcile could plausibly have changed, not the whole table.
195
+ // Re-resolve only what this reconcile could have touched: re-stored sources, links whose
196
+ // target basename matches an added/vanished file, and links whose dst just vanished. All
197
+ // three are indexed lookups, so this never reads the whole table.
202
198
  function resolveIncremental(db, delta) {
203
199
  var pathSet = new Set(delta.files.map(function(f) {
204
200
  return f.relPath;
@@ -294,11 +290,8 @@ function linkEdges(db) {
294
290
  ];
295
291
  });
296
292
  }
297
- // A removed path's outbound link rows are already gone by the time afterReconcile runs
298
- // (remove() below deletes them for vanished files AND for reparsed existing files), so
299
- // afterReconcile can't tell from the links table alone whether deleted rows carried edges.
300
- // remove() records that here, keyed on the reconcile's own delta object -- state dies with
301
- // the reconcile, including on ROLLBACK, and distinct reconciles never share it.
293
+ // remove() has already deleted the rows by the time afterReconcile runs, so it records here
294
+ // whether they carried edges. Keyed on the delta object, so the state dies with the reconcile.
302
295
  var removedWithLinks = new WeakMap();
303
296
  function recordRemoved(delta, path) {
304
297
  var set = removedWithLinks.get(delta);
@@ -382,10 +375,8 @@ var links = {
382
375
  // reparsed-to-zero-links case (no surviving rows to re-resolve).
383
376
  var removeHadLinks = ((_ref = (_removedWithLinks_get = removedWithLinks.get(delta)) === null || _removedWithLinks_get === void 0 ? void 0 : _removedWithLinks_get.size) !== null && _ref !== void 0 ? _ref : 0) > 0;
384
377
  var churn = delta.reparsed.length + delta.vanished.length;
385
- // Fallback rule: correctness over cleverness once too much of the tree moved in one
386
- // reconcile -- a full pass is the one guaranteed to match resolveTarget's ambiguity
387
- // rules exactly. A cold build reparses ~every file, so it clears this threshold on its
388
- // own without a separate check.
378
+ // Past this share of the tree, a full pass is the only one guaranteed to match
379
+ // resolveTarget's ambiguity rules. A cold build clears the threshold on its own.
389
380
  var large = delta.files.length === 0 || churn > 0.2 * delta.files.length;
390
381
  var dstChanged = large ? resolveAll(db, delta.files) : resolveIncremental(db, delta);
391
382
  delta.linksChanged = dstChanged || removeHadLinks;
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/features/links.ts"],"sourcesContent":["import posix from 'node:path/posix';\nimport type { DatabaseSync } from 'node:sqlite';\nimport type { FileStat } from '../scan.ts';\nimport type { Feature, ReconcileDelta } from './types.ts';\n\n// links(src, target, target_base, dst): target as written, target_base its baseKey\n// (indexed, for the incremental resolve below), dst the resolved path or NULL (a\n// queryable dead link).\n\n// Wikilinks ([[target]], [[target#anchor|alias]], embeds) plus relative markdown links to .md files.\nfunction extract(_raw: string, body: string): string[] {\n const targets = new Set<string>();\n for (const m of body.matchAll(/\\[\\[([^\\]|#]+)(?:#[^\\]|]*)?(?:\\|[^\\]]*)?\\]\\]/g)) {\n const target = m[1].trim();\n if (target) targets.add(target);\n }\n for (const m of body.matchAll(/\\]\\(([^)]+\\.md)(?:#[^)]*)?\\)/g)) {\n const target = m[1].trim();\n if (target && !/^[a-z]+:\\/\\//i.test(target)) targets.add(target);\n }\n return [...targets];\n}\n\nfunction cleanTarget(target: string): string {\n return target.replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n}\n\nfunction baseKey(path: string): string {\n return posix.basename(path).replace(/\\.md$/i, '').toLowerCase();\n}\n\n// Obsidian-style: exact relative path (with/without .md), path relative to the linking\n// note's directory, then basename match (lexicographically first on ties).\nfunction resolveTarget(src: string, target: string, pathSet: Set<string>, byBase: Map<string, string[]>): string | null {\n const clean = cleanTarget(target);\n const fromSrc = posix.normalize(posix.join(posix.dirname(src), clean));\n for (const candidate of [clean, `${clean}.md`, fromSrc, `${fromSrc}.md`]) {\n if (pathSet.has(candidate)) return candidate;\n }\n return byBase.get(baseKey(clean))?.[0] ?? null;\n}\n\nfunction buildByBase(files: FileStat[]): Map<string, string[]> {\n const byBase = new Map<string, string[]>();\n for (const path of files.map((f) => f.relPath).sort()) {\n const key = baseKey(path);\n const list = byBase.get(key);\n if (list) list.push(path);\n else byBase.set(key, [path]);\n }\n return byBase;\n}\n\ninterface LinkRow {\n src: string;\n target: string;\n dst: string | null;\n}\n\n// Applies resolveTarget to `rows`, writing only rows whose dst actually changes.\nfunction resolveRows(db: DatabaseSync, rows: LinkRow[], pathSet: Set<string>, byBase: Map<string, string[]>): boolean {\n const update = db.prepare('UPDATE links SET dst = ? WHERE src = ? AND target = ?');\n let changed = false;\n for (const row of rows) {\n const dst = resolveTarget(row.src, row.target, pathSet, byBase);\n if (dst !== row.dst) {\n update.run(dst, row.src, row.target);\n changed = true;\n }\n }\n return changed;\n}\n\n// A new or deleted file can change any note's resolution, so re-resolve the whole table.\n// Fallback for cold builds and large deltas -- see afterReconcile's threshold.\nfunction resolveAll(db: DatabaseSync, files: FileStat[]): boolean {\n const pathSet = new Set(files.map((f) => f.relPath));\n const byBase = buildByBase(files);\n const rows = db.prepare('SELECT src, target, dst FROM links').all() as unknown as LinkRow[];\n return resolveRows(db, rows, pathSet, byBase);\n}\n\n// Re-resolve only what this reconcile could have affected: (a) links whose src was just\n// re-stored (their rows are fresh, dst reset to NULL by store()), (b) links whose target's\n// basename matches a file that appeared or disappeared this reconcile (resolution and\n// lexicographic-tie ambiguity hinge on exactly that set), and (c) links whose dst was a\n// path that just vanished. All three are indexed lookups (src is the links PK's leading\n// column; target_base and dst each have their own index), so this reads only the rows this\n// reconcile could plausibly have changed, not the whole table.\nfunction resolveIncremental(db: DatabaseSync, delta: ReconcileDelta): boolean {\n const pathSet = new Set(delta.files.map((f) => f.relPath));\n const byBase = buildByBase(delta.files);\n\n const changedBasenames = new Set<string>();\n for (const p of delta.added) changedBasenames.add(baseKey(p));\n for (const p of delta.vanished) changedBasenames.add(baseKey(p));\n\n // \\0 can't appear in a path or target, so the key never collides; a space can.\n const candidates = new Map<string, LinkRow>();\n const collect = (rows: LinkRow[]) => {\n for (const row of rows) candidates.set(`${row.src}\\0${row.target}`, row);\n };\n // Chunked so a large-but-under-threshold delta never exceeds SQLite's bound-variable\n // limit (SQLITE_MAX_VARIABLE_NUMBER, 32766).\n const collectIn = (column: string, keys: string[]) => {\n for (let i = 0; i < keys.length; i += 500) {\n const chunk = keys.slice(i, i + 500);\n const placeholders = chunk.map(() => '?').join(', ');\n collect(db.prepare(`SELECT src, target, dst FROM links WHERE ${column} IN (${placeholders})`).all(...chunk) as unknown as LinkRow[]);\n }\n };\n\n collectIn('src', delta.reparsed);\n collectIn('target_base', [...changedBasenames]);\n collectIn('dst', delta.vanished);\n\n return resolveRows(db, [...candidates.values()], pathSet, byBase);\n}\n\n// Resolved edges, for rank and for find's graph expansion.\nexport function linkEdges(db: DatabaseSync): [string, string][] {\n return (db.prepare('SELECT src, dst FROM links WHERE dst IS NOT NULL').all() as Array<{ src: string; dst: string }>).map((r) => [r.src, r.dst]);\n}\n\n// A removed path's outbound link rows are already gone by the time afterReconcile runs\n// (remove() below deletes them for vanished files AND for reparsed existing files), so\n// afterReconcile can't tell from the links table alone whether deleted rows carried edges.\n// remove() records that here, keyed on the reconcile's own delta object -- state dies with\n// the reconcile, including on ROLLBACK, and distinct reconciles never share it.\nconst removedWithLinks = new WeakMap<ReconcileDelta, Set<string>>();\n\nfunction recordRemoved(delta: ReconcileDelta, path: string): void {\n let set = removedWithLinks.get(delta);\n if (!set) {\n set = new Set();\n removedWithLinks.set(delta, set);\n }\n set.add(path);\n}\n\n// remove() runs per path; the vanished list is an array, so cache the Set per delta.\nconst vanishedSets = new WeakMap<ReconcileDelta, Set<string>>();\nfunction vanishedSet(delta: ReconcileDelta): Set<string> {\n let set = vanishedSets.get(delta);\n if (!set) {\n set = new Set(delta.vanished);\n vanishedSets.set(delta, set);\n }\n return set;\n}\n\nexport const links: Feature = {\n name: 'links',\n schema(db) {\n db.exec('CREATE TABLE IF NOT EXISTS links (src TEXT, target TEXT, target_base TEXT, dst TEXT, PRIMARY KEY (src, target))');\n db.exec('CREATE INDEX IF NOT EXISTS links_dst ON links(dst)');\n db.exec('CREATE INDEX IF NOT EXISTS links_target_base ON links(target_base)');\n },\n extract,\n // Reparsed docs are diffed in store() below instead of wiped here: deleting and\n // re-inserting resets dst to NULL, which made every touch-only reparse read as an edge\n // change and recompute PageRank -- measured as most of the remaining update cost.\n remove(db, path, delta) {\n if (!vanishedSet(delta).has(path)) return;\n const result = db.prepare('DELETE FROM links WHERE src = ?').run(path);\n if (Number(result.changes) > 0) recordRemoved(delta, path);\n },\n store(db, path, extracted, delta) {\n const targets = extracted as string[];\n // Stale rows (targets the new parse no longer contains) are real edge removals.\n let stale: ReturnType<ReturnType<DatabaseSync['prepare']>['run']>;\n if (targets.length === 0) {\n stale = db.prepare('DELETE FROM links WHERE src = ?').run(path);\n } else {\n const placeholders = targets.map(() => '?').join(', ');\n stale = db.prepare(`DELETE FROM links WHERE src = ? AND target NOT IN (${placeholders})`).run(path, ...targets);\n }\n if (Number(stale.changes) > 0) recordRemoved(delta, path);\n // Upsert preserves dst on surviving rows, so an unchanged link resolves to the same\n // value and reports no change; only genuinely new rows start at NULL.\n const insert = db.prepare('INSERT INTO links (src, target, target_base, dst) VALUES (?, ?, ?, NULL) ON CONFLICT(src, target) DO UPDATE SET target_base = excluded.target_base');\n for (const target of targets) insert.run(path, target, baseKey(cleanTarget(target)));\n },\n afterReconcile(db, delta) {\n // Any deleted rows that carried edges mean the edge set shrank -- whether the file\n // vanished or was reparsed down to fewer/no links. dstChanged alone misses the\n // reparsed-to-zero-links case (no surviving rows to re-resolve).\n const removeHadLinks = (removedWithLinks.get(delta)?.size ?? 0) > 0;\n\n const churn = delta.reparsed.length + delta.vanished.length;\n // Fallback rule: correctness over cleverness once too much of the tree moved in one\n // reconcile -- a full pass is the one guaranteed to match resolveTarget's ambiguity\n // rules exactly. A cold build reparses ~every file, so it clears this threshold on its\n // own without a separate check.\n const large = delta.files.length === 0 || churn > 0.2 * delta.files.length;\n\n const dstChanged = large ? resolveAll(db, delta.files) : resolveIncremental(db, delta);\n delta.linksChanged = dstChanged || removeHadLinks;\n },\n};\n"],"names":["linkEdges","links","extract","_raw","body","targets","Set","matchAll","m","target","trim","add","test","cleanTarget","replace","baseKey","path","posix","basename","toLowerCase","resolveTarget","src","pathSet","byBase","clean","fromSrc","normalize","join","dirname","candidate","has","get","buildByBase","files","Map","map","f","relPath","sort","key","list","push","set","resolveRows","db","rows","update","prepare","changed","row","dst","run","resolveAll","all","resolveIncremental","delta","changedBasenames","added","p","vanished","candidates","collect","collectIn","column","keys","i","length","chunk","slice","placeholders","reparsed","values","r","removedWithLinks","WeakMap","recordRemoved","vanishedSets","vanishedSet","name","schema","exec","remove","result","Number","changes","store","extracted","stale","insert","afterReconcile","removeHadLinks","size","churn","large","dstChanged","linksChanged"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/features/links.ts"],"sourcesContent":["import posix from 'node:path/posix';\nimport type { DatabaseSync } from 'node:sqlite';\nimport type { FileStat } from '../scan.ts';\nimport type { Feature, ReconcileDelta } from './types.ts';\n\n// links(src, target, target_base, dst): target as written, target_base its baseKey\n// (indexed, for the incremental resolve below), dst the resolved path or NULL (a\n// queryable dead link).\n\n// Wikilinks ([[target]], [[target#anchor|alias]], embeds) plus relative markdown links to .md files.\nfunction extract(_raw: string, body: string): string[] {\n const targets = new Set<string>();\n for (const m of body.matchAll(/\\[\\[([^\\]|#]+)(?:#[^\\]|]*)?(?:\\|[^\\]]*)?\\]\\]/g)) {\n const target = m[1].trim();\n if (target) targets.add(target);\n }\n for (const m of body.matchAll(/\\]\\(([^)]+\\.md)(?:#[^)]*)?\\)/g)) {\n const target = m[1].trim();\n if (target && !/^[a-z]+:\\/\\//i.test(target)) targets.add(target);\n }\n return [...targets];\n}\n\nfunction cleanTarget(target: string): string {\n return target.replace(/\\\\/g, '/').replace(/^\\.\\//, '');\n}\n\nfunction baseKey(path: string): string {\n return posix.basename(path).replace(/\\.md$/i, '').toLowerCase();\n}\n\n// Obsidian-style: exact relative path (with/without .md), path relative to the linking\n// note's directory, then basename match (lexicographically first on ties).\nfunction resolveTarget(src: string, target: string, pathSet: Set<string>, byBase: Map<string, string[]>): string | null {\n const clean = cleanTarget(target);\n const fromSrc = posix.normalize(posix.join(posix.dirname(src), clean));\n for (const candidate of [clean, `${clean}.md`, fromSrc, `${fromSrc}.md`]) {\n if (pathSet.has(candidate)) return candidate;\n }\n return byBase.get(baseKey(clean))?.[0] ?? null;\n}\n\nfunction buildByBase(files: FileStat[]): Map<string, string[]> {\n const byBase = new Map<string, string[]>();\n for (const path of files.map((f) => f.relPath).sort()) {\n const key = baseKey(path);\n const list = byBase.get(key);\n if (list) list.push(path);\n else byBase.set(key, [path]);\n }\n return byBase;\n}\n\ninterface LinkRow {\n src: string;\n target: string;\n dst: string | null;\n}\n\n// Applies resolveTarget to `rows`, writing only rows whose dst actually changes.\nfunction resolveRows(db: DatabaseSync, rows: LinkRow[], pathSet: Set<string>, byBase: Map<string, string[]>): boolean {\n const update = db.prepare('UPDATE links SET dst = ? WHERE src = ? AND target = ?');\n let changed = false;\n for (const row of rows) {\n const dst = resolveTarget(row.src, row.target, pathSet, byBase);\n if (dst !== row.dst) {\n update.run(dst, row.src, row.target);\n changed = true;\n }\n }\n return changed;\n}\n\n// A new or deleted file can change any note's resolution, so re-resolve the whole table.\n// Fallback for cold builds and large deltas -- see afterReconcile's threshold.\nfunction resolveAll(db: DatabaseSync, files: FileStat[]): boolean {\n const pathSet = new Set(files.map((f) => f.relPath));\n const byBase = buildByBase(files);\n const rows = db.prepare('SELECT src, target, dst FROM links').all() as unknown as LinkRow[];\n return resolveRows(db, rows, pathSet, byBase);\n}\n\n// Re-resolve only what this reconcile could have touched: re-stored sources, links whose\n// target basename matches an added/vanished file, and links whose dst just vanished. All\n// three are indexed lookups, so this never reads the whole table.\nfunction resolveIncremental(db: DatabaseSync, delta: ReconcileDelta): boolean {\n const pathSet = new Set(delta.files.map((f) => f.relPath));\n const byBase = buildByBase(delta.files);\n\n const changedBasenames = new Set<string>();\n for (const p of delta.added) changedBasenames.add(baseKey(p));\n for (const p of delta.vanished) changedBasenames.add(baseKey(p));\n\n // \\0 can't appear in a path or target, so the key never collides; a space can.\n const candidates = new Map<string, LinkRow>();\n const collect = (rows: LinkRow[]) => {\n for (const row of rows) candidates.set(`${row.src}\\0${row.target}`, row);\n };\n // Chunked so a large-but-under-threshold delta never exceeds SQLite's bound-variable\n // limit (SQLITE_MAX_VARIABLE_NUMBER, 32766).\n const collectIn = (column: string, keys: string[]) => {\n for (let i = 0; i < keys.length; i += 500) {\n const chunk = keys.slice(i, i + 500);\n const placeholders = chunk.map(() => '?').join(', ');\n collect(db.prepare(`SELECT src, target, dst FROM links WHERE ${column} IN (${placeholders})`).all(...chunk) as unknown as LinkRow[]);\n }\n };\n\n collectIn('src', delta.reparsed);\n collectIn('target_base', [...changedBasenames]);\n collectIn('dst', delta.vanished);\n\n return resolveRows(db, [...candidates.values()], pathSet, byBase);\n}\n\n// Resolved edges, for rank and for search's graph expansion.\nexport function linkEdges(db: DatabaseSync): [string, string][] {\n return (db.prepare('SELECT src, dst FROM links WHERE dst IS NOT NULL').all() as Array<{ src: string; dst: string }>).map((r) => [r.src, r.dst]);\n}\n\n// remove() has already deleted the rows by the time afterReconcile runs, so it records here\n// whether they carried edges. Keyed on the delta object, so the state dies with the reconcile.\nconst removedWithLinks = new WeakMap<ReconcileDelta, Set<string>>();\n\nfunction recordRemoved(delta: ReconcileDelta, path: string): void {\n let set = removedWithLinks.get(delta);\n if (!set) {\n set = new Set();\n removedWithLinks.set(delta, set);\n }\n set.add(path);\n}\n\n// remove() runs per path; the vanished list is an array, so cache the Set per delta.\nconst vanishedSets = new WeakMap<ReconcileDelta, Set<string>>();\nfunction vanishedSet(delta: ReconcileDelta): Set<string> {\n let set = vanishedSets.get(delta);\n if (!set) {\n set = new Set(delta.vanished);\n vanishedSets.set(delta, set);\n }\n return set;\n}\n\nexport const links: Feature = {\n name: 'links',\n schema(db) {\n db.exec('CREATE TABLE IF NOT EXISTS links (src TEXT, target TEXT, target_base TEXT, dst TEXT, PRIMARY KEY (src, target))');\n db.exec('CREATE INDEX IF NOT EXISTS links_dst ON links(dst)');\n db.exec('CREATE INDEX IF NOT EXISTS links_target_base ON links(target_base)');\n },\n extract,\n // Reparsed docs are diffed in store() below instead of wiped here: deleting and\n // re-inserting resets dst to NULL, which made every touch-only reparse read as an edge\n // change and recompute PageRank -- measured as most of the remaining update cost.\n remove(db, path, delta) {\n if (!vanishedSet(delta).has(path)) return;\n const result = db.prepare('DELETE FROM links WHERE src = ?').run(path);\n if (Number(result.changes) > 0) recordRemoved(delta, path);\n },\n store(db, path, extracted, delta) {\n const targets = extracted as string[];\n // Stale rows (targets the new parse no longer contains) are real edge removals.\n let stale: ReturnType<ReturnType<DatabaseSync['prepare']>['run']>;\n if (targets.length === 0) {\n stale = db.prepare('DELETE FROM links WHERE src = ?').run(path);\n } else {\n const placeholders = targets.map(() => '?').join(', ');\n stale = db.prepare(`DELETE FROM links WHERE src = ? AND target NOT IN (${placeholders})`).run(path, ...targets);\n }\n if (Number(stale.changes) > 0) recordRemoved(delta, path);\n // Upsert preserves dst on surviving rows, so an unchanged link resolves to the same\n // value and reports no change; only genuinely new rows start at NULL.\n const insert = db.prepare('INSERT INTO links (src, target, target_base, dst) VALUES (?, ?, ?, NULL) ON CONFLICT(src, target) DO UPDATE SET target_base = excluded.target_base');\n for (const target of targets) insert.run(path, target, baseKey(cleanTarget(target)));\n },\n afterReconcile(db, delta) {\n // Any deleted rows that carried edges mean the edge set shrank -- whether the file\n // vanished or was reparsed down to fewer/no links. dstChanged alone misses the\n // reparsed-to-zero-links case (no surviving rows to re-resolve).\n const removeHadLinks = (removedWithLinks.get(delta)?.size ?? 0) > 0;\n\n const churn = delta.reparsed.length + delta.vanished.length;\n // Past this share of the tree, a full pass is the only one guaranteed to match\n // resolveTarget's ambiguity rules. A cold build clears the threshold on its own.\n const large = delta.files.length === 0 || churn > 0.2 * delta.files.length;\n\n const dstChanged = large ? resolveAll(db, delta.files) : resolveIncremental(db, delta);\n delta.linksChanged = dstChanged || removeHadLinks;\n },\n};\n"],"names":["linkEdges","links","extract","_raw","body","targets","Set","matchAll","m","target","trim","add","test","cleanTarget","replace","baseKey","path","posix","basename","toLowerCase","resolveTarget","src","pathSet","byBase","clean","fromSrc","normalize","join","dirname","candidate","has","get","buildByBase","files","Map","map","f","relPath","sort","key","list","push","set","resolveRows","db","rows","update","prepare","changed","row","dst","run","resolveAll","all","resolveIncremental","delta","changedBasenames","added","p","vanished","candidates","collect","collectIn","column","keys","i","length","chunk","slice","placeholders","reparsed","values","r","removedWithLinks","WeakMap","recordRemoved","vanishedSets","vanishedSet","name","schema","exec","remove","result","Number","changes","store","extracted","stale","insert","afterReconcile","removeHadLinks","size","churn","large","dstChanged","linksChanged"],"mappings":"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"}
@@ -65,12 +65,8 @@ var rank = {
65
65
  })) db.exec('ALTER TABLE frontmatter ADD COLUMN "_rank" REAL');
66
66
  },
67
67
  afterReconcile: function afterReconcile(db, delta) {
68
- // links.afterReconcile runs first (registry order) and sets delta.linksChanged;
69
- // `undefined` (links off, or no opinion) recomputes, same as always -- only an
70
- // explicit `false` allows a skip. Rank also depends on the node set (every note is a
71
- // PageRank node, edges or not), so any add or vanish recomputes even with edges
72
- // untouched -- otherwise a new linkless note keeps _rank NULL and every other rank
73
- // stays normalized over the old count.
68
+ // Only an explicit linksChanged:false skips. Rank also depends on the node set, so any
69
+ // add or vanish recomputes -- otherwise a new linkless note keeps _rank NULL.
74
70
  if (delta.linksChanged === false && delta.added.length === 0 && delta.vanished.length === 0) return;
75
71
  var nodes = db.prepare('SELECT "path" FROM frontmatter').all().map(function(r) {
76
72
  return r.path;
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/features/rank.ts"],"sourcesContent":["import { pagerank } from '../graph.ts';\nimport { linkEdges } from './links.ts';\nimport type { Feature } from './types.ts';\n\n// frontmatter._rank: PageRank over resolved links -- a static \"how load-bearing is this\n// note\" prior. Depends on links (enforced in config.featureEnabled).\n\nexport const rank: Feature = {\n name: 'rank',\n schema(db) {\n const columns = db.prepare('PRAGMA table_info(frontmatter)').all() as Array<{ name: string }>;\n if (!columns.some((c) => c.name === '_rank')) db.exec('ALTER TABLE frontmatter ADD COLUMN \"_rank\" REAL');\n },\n afterReconcile(db, delta) {\n // links.afterReconcile runs first (registry order) and sets delta.linksChanged;\n // `undefined` (links off, or no opinion) recomputes, same as always -- only an\n // explicit `false` allows a skip. Rank also depends on the node set (every note is a\n // PageRank node, edges or not), so any add or vanish recomputes even with edges\n // untouched -- otherwise a new linkless note keeps _rank NULL and every other rank\n // stays normalized over the old count.\n if (delta.linksChanged === false && delta.added.length === 0 && delta.vanished.length === 0) return;\n const nodes = (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n const ranks = pagerank(nodes, linkEdges(db));\n const update = db.prepare('UPDATE frontmatter SET \"_rank\" = ? WHERE \"path\" = ?');\n for (const [path, value] of ranks) update.run(value, path);\n },\n};\n"],"names":["rank","name","schema","db","columns","prepare","all","some","c","exec","afterReconcile","delta","linksChanged","added","length","vanished","nodes","map","r","path","ranks","pagerank","linkEdges","update","value","run"],"mappings":";;;;+BAOaA;;;eAAAA;;;uBAPY;uBACC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMnB,IAAMA,OAAgB;IAC3BC,MAAM;IACNC,QAAAA,SAAAA,OAAOC,EAAE;QACP,IAAMC,UAAUD,GAAGE,OAAO,CAAC,kCAAkCC,GAAG;QAChE,IAAI,CAACF,QAAQG,IAAI,CAAC,SAACC;mBAAMA,EAAEP,IAAI,KAAK;YAAUE,GAAGM,IAAI,CAAC;IACxD;IACAC,gBAAAA,SAAAA,eAAeP,EAAE,EAAEQ,KAAK;QACtB,gFAAgF;QAChF,+EAA+E;QAC/E,qFAAqF;QACrF,gFAAgF;QAChF,mFAAmF;QACnF,uCAAuC;QACvC,IAAIA,MAAMC,YAAY,KAAK,SAASD,MAAME,KAAK,CAACC,MAAM,KAAK,KAAKH,MAAMI,QAAQ,CAACD,MAAM,KAAK,GAAG;QAC7F,IAAME,QAAQ,AAACb,GAAGE,OAAO,CAAC,kCAAkCC,GAAG,GAA+BW,GAAG,CAAC,SAACC;mBAAMA,EAAEC,IAAI;;QAC/G,IAAMC,QAAQC,IAAAA,iBAAQ,EAACL,OAAOM,IAAAA,kBAAS,EAACnB;QACxC,IAAMoB,SAASpB,GAAGE,OAAO,CAAC;YACrB,kCAAA,2BAAA;;YAAL,QAAK,YAAuBe,0BAAvB,SAAA,6BAAA,QAAA,yBAAA;gBAAA,mCAAA,iBAAOD,uBAAMK;gBAAiBD,OAAOE,GAAG,CAACD,OAAOL;;;YAAhD;YAAA;;;qBAAA,6BAAA;oBAAA;;;oBAAA;0BAAA;;;;IACP;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/features/rank.ts"],"sourcesContent":["import { pagerank } from '../graph.ts';\nimport { linkEdges } from './links.ts';\nimport type { Feature } from './types.ts';\n\n// frontmatter._rank: PageRank over resolved links -- a static \"how load-bearing is this\n// note\" prior. Depends on links (enforced in config.featureEnabled).\n\nexport const rank: Feature = {\n name: 'rank',\n schema(db) {\n const columns = db.prepare('PRAGMA table_info(frontmatter)').all() as Array<{ name: string }>;\n if (!columns.some((c) => c.name === '_rank')) db.exec('ALTER TABLE frontmatter ADD COLUMN \"_rank\" REAL');\n },\n afterReconcile(db, delta) {\n // Only an explicit linksChanged:false skips. Rank also depends on the node set, so any\n // add or vanish recomputes -- otherwise a new linkless note keeps _rank NULL.\n if (delta.linksChanged === false && delta.added.length === 0 && delta.vanished.length === 0) return;\n const nodes = (db.prepare('SELECT \"path\" FROM frontmatter').all() as Array<{ path: string }>).map((r) => r.path);\n const ranks = pagerank(nodes, linkEdges(db));\n const update = db.prepare('UPDATE frontmatter SET \"_rank\" = ? WHERE \"path\" = ?');\n for (const [path, value] of ranks) update.run(value, path);\n },\n};\n"],"names":["rank","name","schema","db","columns","prepare","all","some","c","exec","afterReconcile","delta","linksChanged","added","length","vanished","nodes","map","r","path","ranks","pagerank","linkEdges","update","value","run"],"mappings":";;;;+BAOaA;;;eAAAA;;;uBAPY;uBACC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMnB,IAAMA,OAAgB;IAC3BC,MAAM;IACNC,QAAAA,SAAAA,OAAOC,EAAE;QACP,IAAMC,UAAUD,GAAGE,OAAO,CAAC,kCAAkCC,GAAG;QAChE,IAAI,CAACF,QAAQG,IAAI,CAAC,SAACC;mBAAMA,EAAEP,IAAI,KAAK;YAAUE,GAAGM,IAAI,CAAC;IACxD;IACAC,gBAAAA,SAAAA,eAAeP,EAAE,EAAEQ,KAAK;QACtB,uFAAuF;QACvF,8EAA8E;QAC9E,IAAIA,MAAMC,YAAY,KAAK,SAASD,MAAME,KAAK,CAACC,MAAM,KAAK,KAAKH,MAAMI,QAAQ,CAACD,MAAM,KAAK,GAAG;QAC7F,IAAME,QAAQ,AAACb,GAAGE,OAAO,CAAC,kCAAkCC,GAAG,GAA+BW,GAAG,CAAC,SAACC;mBAAMA,EAAEC,IAAI;;QAC/G,IAAMC,QAAQC,IAAAA,iBAAQ,EAACL,OAAOM,IAAAA,kBAAS,EAACnB;QACxC,IAAMoB,SAASpB,GAAGE,OAAO,CAAC;YACrB,kCAAA,2BAAA;;YAAL,QAAK,YAAuBe,0BAAvB,SAAA,6BAAA,QAAA,yBAAA;gBAAA,mCAAA,iBAAOD,uBAAMK;gBAAiBD,OAAOE,GAAG,CAACD,OAAOL;;;YAAhD;YAAA;;;qBAAA,6BAAA;oBAAA;;;oBAAA;0BAAA;;;;IACP;AACF"}
@@ -1,9 +1,9 @@
1
1
  export type { Peek, PresetCoverage, SearchOptions, TreeMap } from './commands.js';
2
2
  export { mapTree, peek, presetCoverage, search } from './commands.js';
3
- export type { Config, EmbedConfig, FeatureName, Preset, ResolvedConfig, SavedQuery, SavedSearch } from './config.js';
3
+ export type { Config, EmbedConfig, FeatureName, Preset, ResolvedConfig, SavedQuery, SavedSearch, SearchOverrides } from './config.js';
4
4
  export { CONFIG_FILENAME, initConfig, loadConfig, migrateConfig, STATE_DIR, SUPPORTED_CONFIG_VERSION } from './config.js';
5
5
  export type { OpenResult } from './db.js';
6
- export { open, rebuild } from './db.js';
6
+ export { clearCache, open } from './db.js';
7
7
  export type { SenseErrorCode } from './errors.js';
8
8
  export { SenseError } from './errors.js';
9
9
  export type { Row } from './output.js';
@@ -1,9 +1,9 @@
1
1
  export type { Peek, PresetCoverage, SearchOptions, TreeMap } from './commands.js';
2
2
  export { mapTree, peek, presetCoverage, search } from './commands.js';
3
- export type { Config, EmbedConfig, FeatureName, Preset, ResolvedConfig, SavedQuery, SavedSearch } from './config.js';
3
+ export type { Config, EmbedConfig, FeatureName, Preset, ResolvedConfig, SavedQuery, SavedSearch, SearchOverrides } from './config.js';
4
4
  export { CONFIG_FILENAME, initConfig, loadConfig, migrateConfig, STATE_DIR, SUPPORTED_CONFIG_VERSION } from './config.js';
5
5
  export type { OpenResult } from './db.js';
6
- export { open, rebuild } from './db.js';
6
+ export { clearCache, open } from './db.js';
7
7
  export type { SenseErrorCode } from './errors.js';
8
8
  export { SenseError } from './errors.js';
9
9
  export type { Row } from './output.js';
package/dist/cjs/index.js CHANGED
@@ -23,6 +23,9 @@ _export(exports, {
23
23
  get SenseError () {
24
24
  return _errorsts.SenseError;
25
25
  },
26
+ get clearCache () {
27
+ return _dbts.clearCache;
28
+ },
26
29
  get initConfig () {
27
30
  return _configts.initConfig;
28
31
  },
@@ -47,9 +50,6 @@ _export(exports, {
47
50
  get printRows () {
48
51
  return _outputts.printRows;
49
52
  },
50
- get rebuild () {
51
- return _dbts.rebuild;
52
- },
53
53
  get runWatch () {
54
54
  return _watchts.runWatch;
55
55
  },
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/index.ts"],"sourcesContent":["// Public library API. Deliberately small: every export is a stability promise;\n// internals (feature registry, graph, scan, meta) stay module-private.\n\nexport type { Peek, PresetCoverage, SearchOptions, TreeMap } from './commands.ts';\nexport { mapTree, peek, presetCoverage, search } from './commands.ts';\nexport type { Config, EmbedConfig, FeatureName, Preset, ResolvedConfig, SavedQuery, SavedSearch } from './config.ts';\nexport { CONFIG_FILENAME, initConfig, loadConfig, migrateConfig, STATE_DIR, SUPPORTED_CONFIG_VERSION } from './config.ts';\nexport type { OpenResult } from './db.ts';\nexport { open, rebuild } from './db.ts';\nexport type { SenseErrorCode } from './errors.ts';\nexport { SenseError } from './errors.ts';\nexport type { Row } from './output.ts';\nexport { printRows } from './output.ts';\n\nexport type { WatchEvent, WatchOptions } from './watch.ts';\nexport { runWatch } from './watch.ts';\n"],"names":["CONFIG_FILENAME","STATE_DIR","SUPPORTED_CONFIG_VERSION","SenseError","initConfig","loadConfig","mapTree","migrateConfig","open","peek","presetCoverage","printRows","rebuild","runWatch","search"],"mappings":"AAAA,+EAA+E;AAC/E,uEAAuE;;;;;;;;;;;;QAK9DA;eAAAA,yBAAe;;QAAyCC;eAAAA,mBAAS;;QAAEC;eAAAA,kCAAwB;;QAI3FC;eAAAA,oBAAU;;QAJOC;eAAAA,oBAAU;;QAAEC;eAAAA,oBAAU;;QAFvCC;eAAAA,mBAAO;;QAEkCC;eAAAA,uBAAa;;QAEtDC;eAAAA,UAAI;;QAJKC;eAAAA,gBAAI;;QAAEC;eAAAA,0BAAc;;QAQ7BC;eAAAA,mBAAS;;QAJHC;eAAAA,aAAO;;QAObC;eAAAA,iBAAQ;;QAXuBC;eAAAA,kBAAM;;;0BAAQ;wBAEsD;oBAE9E;wBAEH;wBAED;uBAGD"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/index.ts"],"sourcesContent":["// Public library API. Deliberately small: every export is a stability promise;\n// internals (feature registry, graph, scan, meta) stay module-private.\n\nexport type { Peek, PresetCoverage, SearchOptions, TreeMap } from './commands.ts';\nexport { mapTree, peek, presetCoverage, search } from './commands.ts';\nexport type { Config, EmbedConfig, FeatureName, Preset, ResolvedConfig, SavedQuery, SavedSearch, SearchOverrides } from './config.ts';\nexport { CONFIG_FILENAME, initConfig, loadConfig, migrateConfig, STATE_DIR, SUPPORTED_CONFIG_VERSION } from './config.ts';\nexport type { OpenResult } from './db.ts';\nexport { clearCache, open } from './db.ts';\nexport type { SenseErrorCode } from './errors.ts';\nexport { SenseError } from './errors.ts';\nexport type { Row } from './output.ts';\nexport { printRows } from './output.ts';\n\nexport type { WatchEvent, WatchOptions } from './watch.ts';\nexport { runWatch } from './watch.ts';\n"],"names":["CONFIG_FILENAME","STATE_DIR","SUPPORTED_CONFIG_VERSION","SenseError","clearCache","initConfig","loadConfig","mapTree","migrateConfig","open","peek","presetCoverage","printRows","runWatch","search"],"mappings":"AAAA,+EAA+E;AAC/E,uEAAuE;;;;;;;;;;;;QAK9DA;eAAAA,yBAAe;;QAAyCC;eAAAA,mBAAS;;QAAEC;eAAAA,kCAAwB;;QAI3FC;eAAAA,oBAAU;;QAFVC;eAAAA,gBAAU;;QAFOC;eAAAA,oBAAU;;QAAEC;eAAAA,oBAAU;;QAFvCC;eAAAA,mBAAO;;QAEkCC;eAAAA,uBAAa;;QAE1CC;eAAAA,UAAI;;QAJPC;eAAAA,gBAAI;;QAAEC;eAAAA,0BAAc;;QAQ7BC;eAAAA,mBAAS;;QAGTC;eAAAA,iBAAQ;;QAXuBC;eAAAA,kBAAM;;;0BAAQ;wBAEsD;oBAE3E;wBAEN;wBAED;uBAGD"}
@@ -9,6 +9,7 @@ export declare function presetsLines(presets: Array<{
9
9
  name: string;
10
10
  files: number;
11
11
  embedded: number;
12
+ semantic?: boolean;
12
13
  }>): string[];
13
14
  export declare function renderMap(result: {
14
15
  docs: {
@@ -25,6 +26,7 @@ export declare function renderMap(result: {
25
26
  name: string;
26
27
  files: number;
27
28
  embedded: number;
29
+ semantic?: boolean;
28
30
  }>;
29
31
  hubs: Row[];
30
32
  recent: Row[];
@@ -33,6 +35,7 @@ export declare function renderPeek(result: {
33
35
  path: string;
34
36
  tokens: number;
35
37
  frontmatter: Row;
38
+ parseError?: string | null;
36
39
  sections: Row[];
37
40
  outbound: string[];
38
41
  backlinks: string[];
@@ -9,6 +9,7 @@ export declare function presetsLines(presets: Array<{
9
9
  name: string;
10
10
  files: number;
11
11
  embedded: number;
12
+ semantic?: boolean;
12
13
  }>): string[];
13
14
  export declare function renderMap(result: {
14
15
  docs: {
@@ -25,6 +26,7 @@ export declare function renderMap(result: {
25
26
  name: string;
26
27
  files: number;
27
28
  embedded: number;
29
+ semantic?: boolean;
28
30
  }>;
29
31
  hubs: Row[];
30
32
  recent: Row[];
@@ -33,6 +35,7 @@ export declare function renderPeek(result: {
33
35
  path: string;
34
36
  tokens: number;
35
37
  frontmatter: Row;
38
+ parseError?: string | null;
36
39
  sections: Row[];
37
40
  outbound: string[];
38
41
  backlinks: string[];
@@ -100,11 +100,8 @@ function printRows(rows, format) {
100
100
  console.warn("warning: result is ".concat(Math.round(rendered.length / 1000), " KB across ").concat(rows.length, " row(s); consider a LIMIT, fewer columns, or snippet() instead of whole values"));
101
101
  }
102
102
  }
103
- // Table output is for reading; a row wider than the terminal wraps into an unreadable
104
- // block (a `find` header measured 330 chars once `summary` is present, which drove one
105
- // user to pipe --format json through a script for every interactive query). Widest
106
- // columns give up space first, down to a floor, and only as far as the terminal needs.
107
- // --format json is never truncated: it is the machine-readable surface.
103
+ // Tables are for reading, and a row wider than the terminal wraps unreadably: widest columns
104
+ // give up space first, down to a floor. --format json is never truncated.
108
105
  var MIN_COLUMN = 12;
109
106
  var TRUNCATED = '…';
110
107
  function fitWidths(widths, limit) {
@@ -156,7 +153,7 @@ function renderRows(rows, format) {
156
153
  ].concat(_to_consumable_array(cells.map(formatRow))).join('\n');
157
154
  }
158
155
  function featureOffHint(name) {
159
- return name === 'embed' ? 'no preset has semantic on' : "features.".concat(name);
156
+ return "features.".concat(name);
160
157
  }
161
158
  function featuresLine(features) {
162
159
  var off = features.off.length > 0 ? " \xb7 off: ".concat(features.off.map(function(name) {
@@ -165,10 +162,12 @@ function featuresLine(features) {
165
162
  return "features: ".concat(features.on.join(', ')).concat(off);
166
163
  }
167
164
  function presetsLines(presets) {
165
+ // "0 embedded" is ambiguous between a scope that declined vectors and one that has not built
166
+ // them yet, so a semantic-off preset says which.
168
167
  return [
169
168
  'presets:'
170
169
  ].concat(_to_consumable_array(presets.map(function(p) {
171
- return " ".concat(p.name, ": ").concat(p.files, " file(s), ").concat(p.embedded, " embedded");
170
+ return " ".concat(p.name, ": ").concat(p.files, " file(s), ").concat(p.embedded, " embedded").concat(p.semantic === false ? ' (semantic: false)' : '');
172
171
  })));
173
172
  }
174
173
  function renderMap(result) {
@@ -190,6 +189,9 @@ function renderPeek(result) {
190
189
  var lines = [
191
190
  "".concat(result.path, " (~").concat(result.tokens, " tokens)")
192
191
  ];
192
+ // Otherwise a refused parse is indistinguishable from a note that has no frontmatter, which
193
+ // is the confusion the whole quarantine design exists to remove.
194
+ if (result.parseError) lines.push(" frontmatter: did not parse, so none of it is indexed (".concat(result.parseError, ")"));
193
195
  var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
194
196
  try {
195
197
  for(var _iterator = Object.entries(result.frontmatter)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
@@ -236,15 +238,15 @@ function renderPeek(result) {
236
238
  } else if (result.off.includes('sections')) lines.push('', 'sections: off (features.sections)');
237
239
  if (result.off.includes('links')) {
238
240
  lines.push('', 'links: off (features.links)');
239
- return lines.join('\n');
241
+ } else {
242
+ var linkLine = function linkLine(label, shown, total) {
243
+ if (total > 0) lines.push("".concat(label, " (").concat(total, "): ").concat(shown.join(', ')).concat(total > shown.length ? ", +".concat(total - shown.length, " more") : ''));
244
+ };
245
+ if (result.outboundTotal + result.unresolvedTotal + result.backlinksTotal > 0) lines.push('');
246
+ linkLine('links out', result.outbound, result.outboundTotal);
247
+ linkLine('unresolved', result.unresolved, result.unresolvedTotal);
248
+ linkLine('backlinks', result.backlinks, result.backlinksTotal);
240
249
  }
241
- var linkLine = function linkLine(label, shown, total) {
242
- if (total > 0) lines.push("".concat(label, " (").concat(total, "): ").concat(shown.join(', ')).concat(total > shown.length ? ", +".concat(total - shown.length, " more") : ''));
243
- };
244
- if (result.outboundTotal + result.unresolvedTotal + result.backlinksTotal > 0) lines.push('');
245
- linkLine('links out', result.outbound, result.outboundTotal);
246
- linkLine('unresolved', result.unresolved, result.unresolvedTotal);
247
- linkLine('backlinks', result.backlinks, result.backlinksTotal);
248
250
  return lines.join('\n');
249
251
  }
250
252
  /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/output.ts"],"sourcesContent":["// rows -> table (default) | json\n\nexport type Row = Record<string, unknown>;\n\n// Warned about on stderr (keeps --format json stdout machine-readable), never truncated.\nconst OVERSIZE_BYTES = 50_000;\n\n// Flatten embedded newlines so they can't break table column alignment; JSON output is left alone.\nfunction cell(value: unknown): string {\n return String(value ?? '').replace(/\\s*\\n\\s*/g, ' ');\n}\n\nexport function printRows(rows: Row[], format: 'table' | 'json'): void {\n const rendered = renderRows(rows, format);\n console.log(rendered);\n if (rendered.length > OVERSIZE_BYTES) {\n console.warn(`warning: result is ${Math.round(rendered.length / 1000)} KB across ${rows.length} row(s); consider a LIMIT, fewer columns, or snippet() instead of whole values`);\n }\n}\n\n// Table output is for reading; a row wider than the terminal wraps into an unreadable\n// block (a `find` header measured 330 chars once `summary` is present, which drove one\n// user to pipe --format json through a script for every interactive query). Widest\n// columns give up space first, down to a floor, and only as far as the terminal needs.\n// --format json is never truncated: it is the machine-readable surface.\nconst MIN_COLUMN = 12;\nconst TRUNCATED = '…';\n\nfunction fitWidths(widths: number[], limit: number): number[] {\n const gaps = (widths.length - 1) * 2;\n const fitted = [...widths];\n for (;;) {\n const total = fitted.reduce((a, b) => a + b, 0) + gaps;\n if (total <= limit) return fitted;\n const widest = fitted.indexOf(Math.max(...fitted));\n if (fitted[widest] <= MIN_COLUMN) return fitted;\n fitted[widest] = Math.max(MIN_COLUMN, fitted[widest] - Math.max(1, total - limit));\n }\n}\n\nfunction renderRows(rows: Row[], format: 'table' | 'json', width = process.stdout.columns): string {\n if (format === 'json') return JSON.stringify(rows, null, 2);\n if (rows.length === 0) return '(0 rows)';\n\n const columns = Object.keys(rows[0]);\n const cells = rows.map((row) => columns.map((col) => cell(row[col])));\n const natural = columns.map((col, i) => Math.max(col.length, ...cells.map((row) => row[i].length)));\n const widths = width && width > MIN_COLUMN ? fitWidths(natural, width) : natural;\n\n const clip = (value: string, w: number) => (value.length <= w ? value.padEnd(w) : `${value.slice(0, w - 1)}${TRUNCATED}`);\n const formatRow = (values: string[]) =>\n values\n .map((value, i) => clip(value, widths[i]))\n .join(' ')\n .trimEnd();\n\n return [formatRow(columns), widths.map((w) => '-'.repeat(w)).join(' '), ...cells.map(formatRow)].join('\\n');\n}\n\n// Text renderers for the top-level commands; cli.ts prints what these return.\n\n// `embed` is not a features-block key (it's derived from presets), so its off hint reads\n// differently from links/sections/rank's plain `features.<name>`.\nexport function featureOffHint(name: string): string {\n return name === 'embed' ? 'no preset has semantic on' : `features.${name}`;\n}\n\nexport function featuresLine(features: { on: string[]; off: string[] }): string {\n const off = features.off.length > 0 ? ` · off: ${features.off.map((name) => `${name} (${featureOffHint(name)})`).join(', ')}` : '';\n return `features: ${features.on.join(', ')}${off}`;\n}\n\nexport function presetsLines(presets: Array<{ name: string; files: number; embedded: number }>): string[] {\n return ['presets:', ...presets.map((p) => ` ${p.name}: ${p.files} file(s), ${p.embedded} embedded`)];\n}\n\nexport function renderMap(result: { docs: { count: number; bytes: number }; fields: Row[]; fieldsTotal: number; features: { on: string[]; off: string[] }; presets: Array<{ name: string; files: number; embedded: number }>; hubs: Row[]; recent: Row[] }): string {\n const parts = [`docs: ${result.docs.count} (${Math.round(result.docs.bytes / 1024)} KB)`, featuresLine(result.features), '', ...presetsLines(result.presets), '', renderRows(result.fields, 'table')];\n if (result.fieldsTotal > result.fields.length) parts.push(`(+${result.fieldsTotal - result.fields.length} more fields)`);\n if (result.hubs.length > 0) parts.push('\\nhubs (by link rank):', renderRows(result.hubs, 'table'));\n else if (result.features.off.includes('rank')) parts.push(`\\nhubs: off (${featureOffHint('rank')})`);\n parts.push('\\nrecent:', renderRows(result.recent, 'table'));\n return parts.join('\\n');\n}\n\nexport function renderPeek(result: { path: string; tokens: number; frontmatter: Row; sections: Row[]; outbound: string[]; backlinks: string[]; unresolved: string[]; sectionsTotal: number; outboundTotal: number; backlinksTotal: number; unresolvedTotal: number; off: string[] }): string {\n const lines = [`${result.path} (~${result.tokens} tokens)`];\n for (const [key, value] of Object.entries(result.frontmatter)) lines.push(` ${key}: ${value}`);\n if (result.sections.length > 0) {\n lines.push('', 'sections:');\n for (const s of result.sections) lines.push(` ${'#'.repeat(s.level as number)} ${s.heading} [L${s.start_line}-${s.end_line}, ~${s.tokens}t]`);\n if (result.sectionsTotal > result.sections.length) lines.push(` (+${result.sectionsTotal - result.sections.length} more sections -- sections table has all of them)`);\n } else if (result.off.includes('sections')) lines.push('', 'sections: off (features.sections)');\n if (result.off.includes('links')) {\n lines.push('', 'links: off (features.links)');\n return lines.join('\\n');\n }\n const linkLine = (label: string, shown: string[], total: number) => {\n if (total > 0) lines.push(`${label} (${total}): ${shown.join(', ')}${total > shown.length ? `, +${total - shown.length} more` : ''}`);\n };\n if (result.outboundTotal + result.unresolvedTotal + result.backlinksTotal > 0) lines.push('');\n linkLine('links out', result.outbound, result.outboundTotal);\n linkLine('unresolved', result.unresolved, result.unresolvedTotal);\n linkLine('backlinks', result.backlinks, result.backlinksTotal);\n return lines.join('\\n');\n}\n"],"names":["featureOffHint","featuresLine","presetsLines","printRows","renderMap","renderPeek","OVERSIZE_BYTES","cell","value","String","replace","rows","format","rendered","renderRows","console","log","length","warn","Math","round","MIN_COLUMN","TRUNCATED","fitWidths","widths","limit","gaps","fitted","total","reduce","a","b","widest","indexOf","max","width","process","stdout","columns","JSON","stringify","Object","keys","cells","map","row","col","natural","i","clip","w","padEnd","slice","formatRow","values","join","trimEnd","repeat","name","features","off","on","presets","p","files","embedded","result","parts","docs","count","bytes","fields","fieldsTotal","push","hubs","includes","recent","lines","path","tokens","entries","frontmatter","key","sections","s","level","heading","start_line","end_line","sectionsTotal","linkLine","label","shown","outboundTotal","unresolvedTotal","backlinksTotal","outbound","unresolved","backlinks"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/output.ts"],"sourcesContent":["// rows -> table (default) | json\n\nexport type Row = Record<string, unknown>;\n\n// Warned about on stderr (keeps --format json stdout machine-readable), never truncated.\nconst OVERSIZE_BYTES = 50_000;\n\n// Flatten embedded newlines so they can't break table column alignment; JSON output is left alone.\nfunction cell(value: unknown): string {\n return String(value ?? '').replace(/\\s*\\n\\s*/g, ' ');\n}\n\nexport function printRows(rows: Row[], format: 'table' | 'json'): void {\n const rendered = renderRows(rows, format);\n console.log(rendered);\n if (rendered.length > OVERSIZE_BYTES) {\n console.warn(`warning: result is ${Math.round(rendered.length / 1000)} KB across ${rows.length} row(s); consider a LIMIT, fewer columns, or snippet() instead of whole values`);\n }\n}\n\n// Tables are for reading, and a row wider than the terminal wraps unreadably: widest columns\n// give up space first, down to a floor. --format json is never truncated.\nconst MIN_COLUMN = 12;\nconst TRUNCATED = '…';\n\nfunction fitWidths(widths: number[], limit: number): number[] {\n const gaps = (widths.length - 1) * 2;\n const fitted = [...widths];\n for (;;) {\n const total = fitted.reduce((a, b) => a + b, 0) + gaps;\n if (total <= limit) return fitted;\n const widest = fitted.indexOf(Math.max(...fitted));\n if (fitted[widest] <= MIN_COLUMN) return fitted;\n fitted[widest] = Math.max(MIN_COLUMN, fitted[widest] - Math.max(1, total - limit));\n }\n}\n\nfunction renderRows(rows: Row[], format: 'table' | 'json', width = process.stdout.columns): string {\n if (format === 'json') return JSON.stringify(rows, null, 2);\n if (rows.length === 0) return '(0 rows)';\n\n const columns = Object.keys(rows[0]);\n const cells = rows.map((row) => columns.map((col) => cell(row[col])));\n const natural = columns.map((col, i) => Math.max(col.length, ...cells.map((row) => row[i].length)));\n const widths = width && width > MIN_COLUMN ? fitWidths(natural, width) : natural;\n\n const clip = (value: string, w: number) => (value.length <= w ? value.padEnd(w) : `${value.slice(0, w - 1)}${TRUNCATED}`);\n const formatRow = (values: string[]) =>\n values\n .map((value, i) => clip(value, widths[i]))\n .join(' ')\n .trimEnd();\n\n return [formatRow(columns), widths.map((w) => '-'.repeat(w)).join(' '), ...cells.map(formatRow)].join('\\n');\n}\n\n// Text renderers for the top-level commands; cli.ts prints what these return.\n\n// Names the config key that turns a feature back on. Only the three features-block toggles\n// reach here; `embed` has its own status line.\nexport function featureOffHint(name: string): string {\n return `features.${name}`;\n}\n\nexport function featuresLine(features: { on: string[]; off: string[] }): string {\n const off = features.off.length > 0 ? ` · off: ${features.off.map((name) => `${name} (${featureOffHint(name)})`).join(', ')}` : '';\n return `features: ${features.on.join(', ')}${off}`;\n}\n\nexport function presetsLines(presets: Array<{ name: string; files: number; embedded: number; semantic?: boolean }>): string[] {\n // \"0 embedded\" is ambiguous between a scope that declined vectors and one that has not built\n // them yet, so a semantic-off preset says which.\n return ['presets:', ...presets.map((p) => ` ${p.name}: ${p.files} file(s), ${p.embedded} embedded${p.semantic === false ? ' (semantic: false)' : ''}`)];\n}\n\nexport function renderMap(result: { docs: { count: number; bytes: number }; fields: Row[]; fieldsTotal: number; features: { on: string[]; off: string[] }; presets: Array<{ name: string; files: number; embedded: number; semantic?: boolean }>; hubs: Row[]; recent: Row[] }): string {\n const parts = [`docs: ${result.docs.count} (${Math.round(result.docs.bytes / 1024)} KB)`, featuresLine(result.features), '', ...presetsLines(result.presets), '', renderRows(result.fields, 'table')];\n if (result.fieldsTotal > result.fields.length) parts.push(`(+${result.fieldsTotal - result.fields.length} more fields)`);\n if (result.hubs.length > 0) parts.push('\\nhubs (by link rank):', renderRows(result.hubs, 'table'));\n else if (result.features.off.includes('rank')) parts.push(`\\nhubs: off (${featureOffHint('rank')})`);\n parts.push('\\nrecent:', renderRows(result.recent, 'table'));\n return parts.join('\\n');\n}\n\nexport function renderPeek(result: { path: string; tokens: number; frontmatter: Row; parseError?: string | null; sections: Row[]; outbound: string[]; backlinks: string[]; unresolved: string[]; sectionsTotal: number; outboundTotal: number; backlinksTotal: number; unresolvedTotal: number; off: string[] }): string {\n const lines = [`${result.path} (~${result.tokens} tokens)`];\n // Otherwise a refused parse is indistinguishable from a note that has no frontmatter, which\n // is the confusion the whole quarantine design exists to remove.\n if (result.parseError) lines.push(` frontmatter: did not parse, so none of it is indexed (${result.parseError})`);\n for (const [key, value] of Object.entries(result.frontmatter)) lines.push(` ${key}: ${value}`);\n if (result.sections.length > 0) {\n lines.push('', 'sections:');\n for (const s of result.sections) lines.push(` ${'#'.repeat(s.level as number)} ${s.heading} [L${s.start_line}-${s.end_line}, ~${s.tokens}t]`);\n if (result.sectionsTotal > result.sections.length) lines.push(` (+${result.sectionsTotal - result.sections.length} more sections -- sections table has all of them)`);\n } else if (result.off.includes('sections')) lines.push('', 'sections: off (features.sections)');\n if (result.off.includes('links')) {\n lines.push('', 'links: off (features.links)');\n } else {\n const linkLine = (label: string, shown: string[], total: number) => {\n if (total > 0) lines.push(`${label} (${total}): ${shown.join(', ')}${total > shown.length ? `, +${total - shown.length} more` : ''}`);\n };\n if (result.outboundTotal + result.unresolvedTotal + result.backlinksTotal > 0) lines.push('');\n linkLine('links out', result.outbound, result.outboundTotal);\n linkLine('unresolved', result.unresolved, result.unresolvedTotal);\n linkLine('backlinks', result.backlinks, result.backlinksTotal);\n }\n return lines.join('\\n');\n}\n"],"names":["featureOffHint","featuresLine","presetsLines","printRows","renderMap","renderPeek","OVERSIZE_BYTES","cell","value","String","replace","rows","format","rendered","renderRows","console","log","length","warn","Math","round","MIN_COLUMN","TRUNCATED","fitWidths","widths","limit","gaps","fitted","total","reduce","a","b","widest","indexOf","max","width","process","stdout","columns","JSON","stringify","Object","keys","cells","map","row","col","natural","i","clip","w","padEnd","slice","formatRow","values","join","trimEnd","repeat","name","features","off","on","presets","p","files","embedded","semantic","result","parts","docs","count","bytes","fields","fieldsTotal","push","hubs","includes","recent","lines","path","tokens","parseError","entries","frontmatter","key","sections","s","level","heading","start_line","end_line","sectionsTotal","linkLine","label","shown","outboundTotal","unresolvedTotal","backlinksTotal","outbound","unresolved","backlinks"],"mappings":"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"}
@@ -8,10 +8,8 @@ Object.defineProperty(exports, "progress", {
8
8
  return progress;
9
9
  }
10
10
  });
11
- // Long-work progress on stderr only: stdout stays the parseable answer, so progress can
12
- // never corrupt --format json (the same channel warnings already use). TTY-aware: a human
13
- // terminal gets one self-overwriting line; a non-TTY consumer (agent, pipe, CI) gets at
14
- // most a few append-only lines -- an agent transcript gains lines, not redraw frames.
11
+ // Progress on stderr only, so it can never corrupt --format json. A TTY gets one
12
+ // self-overwriting line; a pipe gets a few append-only ones, not redraw frames.
15
13
  var NON_TTY_MILESTONES = 4;
16
14
  function progress(label, total) {
17
15
  var threshold = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 200;
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/progress.ts"],"sourcesContent":["// Long-work progress on stderr only: stdout stays the parseable answer, so progress can\n// never corrupt --format json (the same channel warnings already use). TTY-aware: a human\n// terminal gets one self-overwriting line; a non-TTY consumer (agent, pipe, CI) gets at\n// most a few append-only lines -- an agent transcript gains lines, not redraw frames.\n\nconst NON_TTY_MILESTONES = 4;\n\nexport interface Progress {\n tick(done: number): void;\n finish(): void;\n}\n\n// `total` known upfront; `label` names the work (\"embedding notes\", \"reparsing files\").\n// Silent entirely below `threshold` -- short work needs no narration.\nexport function progress(label: string, total: number, threshold = 200): Progress {\n if (total < threshold) return { tick() {}, finish() {} };\n\n const started = Date.now();\n const isTTY = process.stderr.isTTY === true;\n let lastShown = 0;\n let wrote = false;\n\n const line = (done: number) => {\n const elapsed = (Date.now() - started) / 1000;\n // Estimate from observed rate, only once there is a rate to observe.\n const eta = done > 0 && done < total ? `, ~${Math.max(1, Math.round((elapsed / done) * (total - done)))}s left` : '';\n return `${label}: ${done}/${total}${eta}`;\n };\n\n return {\n tick(done: number) {\n if (isTTY) {\n process.stderr.write(`\\r${line(done)}`);\n wrote = true;\n return;\n }\n // Sparse milestones: first tick, then every 1/NON_TTY_MILESTONES of the total.\n if (done === lastShown) return;\n if (lastShown === 0 || done - lastShown >= total / NON_TTY_MILESTONES) {\n process.stderr.write(`${line(done)}\\n`);\n lastShown = done;\n wrote = true;\n }\n },\n finish() {\n if (!wrote) return;\n if (isTTY) process.stderr.write(`\\r${line(total)}\\n`);\n else if (lastShown < total) process.stderr.write(`${line(total)}\\n`);\n },\n };\n}\n"],"names":["progress","NON_TTY_MILESTONES","label","total","threshold","tick","finish","started","Date","now","isTTY","process","stderr","lastShown","wrote","line","done","elapsed","eta","Math","max","round","write"],"mappings":";;;;+BAcgBA;;;eAAAA;;;AAdhB,wFAAwF;AACxF,0FAA0F;AAC1F,wFAAwF;AACxF,sFAAsF;AAEtF,IAAMC,qBAAqB;AASpB,SAASD,SAASE,KAAa,EAAEC,KAAa;QAAEC,YAAAA,iEAAY;IACjE,IAAID,QAAQC,WAAW,OAAO;QAAEC,MAAAA,SAAAA,QAAQ;QAAGC,QAAAA,SAAAA,UAAU;IAAE;IAEvD,IAAMC,UAAUC,KAAKC,GAAG;IACxB,IAAMC,QAAQC,QAAQC,MAAM,CAACF,KAAK,KAAK;IACvC,IAAIG,YAAY;IAChB,IAAIC,QAAQ;IAEZ,IAAMC,OAAO,cAACC;QACZ,IAAMC,UAAU,AAACT,CAAAA,KAAKC,GAAG,KAAKF,OAAM,IAAK;QACzC,qEAAqE;QACrE,IAAMW,MAAMF,OAAO,KAAKA,OAAOb,QAAQ,AAAC,MAAgE,OAA3DgB,KAAKC,GAAG,CAAC,GAAGD,KAAKE,KAAK,CAAC,AAACJ,UAAUD,OAASb,CAAAA,QAAQa,IAAG,KAAK,YAAU;QAClH,OAAO,AAAC,GAAYA,OAAVd,OAAM,MAAYC,OAARa,MAAK,KAAWE,OAARf,OAAY,OAAJe;IACtC;IAEA,OAAO;QACLb,MAAAA,SAAAA,KAAKW,IAAY;YACf,IAAIN,OAAO;gBACTC,QAAQC,MAAM,CAACU,KAAK,CAAC,AAAC,KAAe,OAAXP,KAAKC;gBAC/BF,QAAQ;gBACR;YACF;YACA,+EAA+E;YAC/E,IAAIE,SAASH,WAAW;YACxB,IAAIA,cAAc,KAAKG,OAAOH,aAAaV,QAAQF,oBAAoB;gBACrEU,QAAQC,MAAM,CAACU,KAAK,CAAC,AAAC,GAAa,OAAXP,KAAKC,OAAM;gBACnCH,YAAYG;gBACZF,QAAQ;YACV;QACF;QACAR,QAAAA,SAAAA;YACE,IAAI,CAACQ,OAAO;YACZ,IAAIJ,OAAOC,QAAQC,MAAM,CAACU,KAAK,CAAC,AAAC,KAAgB,OAAZP,KAAKZ,QAAO;iBAC5C,IAAIU,YAAYV,OAAOQ,QAAQC,MAAM,CAACU,KAAK,CAAC,AAAC,GAAc,OAAZP,KAAKZ,QAAO;QAClE;IACF;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/progress.ts"],"sourcesContent":["// Progress on stderr only, so it can never corrupt --format json. A TTY gets one\n// self-overwriting line; a pipe gets a few append-only ones, not redraw frames.\n\nconst NON_TTY_MILESTONES = 4;\n\nexport interface Progress {\n tick(done: number): void;\n finish(): void;\n}\n\n// `total` known upfront; `label` names the work (\"embedding notes\", \"reparsing files\").\n// Silent entirely below `threshold` -- short work needs no narration.\nexport function progress(label: string, total: number, threshold = 200): Progress {\n if (total < threshold) return { tick() {}, finish() {} };\n\n const started = Date.now();\n const isTTY = process.stderr.isTTY === true;\n let lastShown = 0;\n let wrote = false;\n\n const line = (done: number) => {\n const elapsed = (Date.now() - started) / 1000;\n // Estimate from observed rate, only once there is a rate to observe.\n const eta = done > 0 && done < total ? `, ~${Math.max(1, Math.round((elapsed / done) * (total - done)))}s left` : '';\n return `${label}: ${done}/${total}${eta}`;\n };\n\n return {\n tick(done: number) {\n if (isTTY) {\n process.stderr.write(`\\r${line(done)}`);\n wrote = true;\n return;\n }\n // Sparse milestones: first tick, then every 1/NON_TTY_MILESTONES of the total.\n if (done === lastShown) return;\n if (lastShown === 0 || done - lastShown >= total / NON_TTY_MILESTONES) {\n process.stderr.write(`${line(done)}\\n`);\n lastShown = done;\n wrote = true;\n }\n },\n finish() {\n if (!wrote) return;\n if (isTTY) process.stderr.write(`\\r${line(total)}\\n`);\n else if (lastShown < total) process.stderr.write(`${line(total)}\\n`);\n },\n };\n}\n"],"names":["progress","NON_TTY_MILESTONES","label","total","threshold","tick","finish","started","Date","now","isTTY","process","stderr","lastShown","wrote","line","done","elapsed","eta","Math","max","round","write"],"mappings":";;;;+BAYgBA;;;eAAAA;;;AAZhB,iFAAiF;AACjF,gFAAgF;AAEhF,IAAMC,qBAAqB;AASpB,SAASD,SAASE,KAAa,EAAEC,KAAa;QAAEC,YAAAA,iEAAY;IACjE,IAAID,QAAQC,WAAW,OAAO;QAAEC,MAAAA,SAAAA,QAAQ;QAAGC,QAAAA,SAAAA,UAAU;IAAE;IAEvD,IAAMC,UAAUC,KAAKC,GAAG;IACxB,IAAMC,QAAQC,QAAQC,MAAM,CAACF,KAAK,KAAK;IACvC,IAAIG,YAAY;IAChB,IAAIC,QAAQ;IAEZ,IAAMC,OAAO,cAACC;QACZ,IAAMC,UAAU,AAACT,CAAAA,KAAKC,GAAG,KAAKF,OAAM,IAAK;QACzC,qEAAqE;QACrE,IAAMW,MAAMF,OAAO,KAAKA,OAAOb,QAAQ,AAAC,MAAgE,OAA3DgB,KAAKC,GAAG,CAAC,GAAGD,KAAKE,KAAK,CAAC,AAACJ,UAAUD,OAASb,CAAAA,QAAQa,IAAG,KAAK,YAAU;QAClH,OAAO,AAAC,GAAYA,OAAVd,OAAM,MAAYC,OAARa,MAAK,KAAWE,OAARf,OAAY,OAAJe;IACtC;IAEA,OAAO;QACLb,MAAAA,SAAAA,KAAKW,IAAY;YACf,IAAIN,OAAO;gBACTC,QAAQC,MAAM,CAACU,KAAK,CAAC,AAAC,KAAe,OAAXP,KAAKC;gBAC/BF,QAAQ;gBACR;YACF;YACA,+EAA+E;YAC/E,IAAIE,SAASH,WAAW;YACxB,IAAIA,cAAc,KAAKG,OAAOH,aAAaV,QAAQF,oBAAoB;gBACrEU,QAAQC,MAAM,CAACU,KAAK,CAAC,AAAC,GAAa,OAAXP,KAAKC,OAAM;gBACnCH,YAAYG;gBACZF,QAAQ;YACV;QACF;QACAR,QAAAA,SAAAA;YACE,IAAI,CAACQ,OAAO;YACZ,IAAIJ,OAAOC,QAAQC,MAAM,CAACU,KAAK,CAAC,AAAC,KAAgB,OAAZP,KAAKZ,QAAO;iBAC5C,IAAIU,YAAYV,OAAOQ,QAAQC,MAAM,CAACU,KAAK,CAAC,AAAC,GAAc,OAAZP,KAAKZ,QAAO;QAClE;IACF;AACF"}
@@ -9,6 +9,7 @@ export interface FileStat {
9
9
  presets: string[];
10
10
  embed: boolean;
11
11
  }
12
+ export declare function toPosixPath(relPath: string, separator?: string): string;
12
13
  export declare function listFiles(cfg: Config, baseDir: string): FileStat[];
13
14
  export interface ParsedDoc {
14
15
  relPath: string;
@@ -16,6 +17,7 @@ export interface ParsedDoc {
16
17
  size: number;
17
18
  presets: string[];
18
19
  data: Record<string, string | number | bigint | null>;
20
+ parseError: string | null;
19
21
  search: {
20
22
  title: string;
21
23
  summary: string;
@@ -9,6 +9,7 @@ export interface FileStat {
9
9
  presets: string[];
10
10
  embed: boolean;
11
11
  }
12
+ export declare function toPosixPath(relPath: string, separator?: string): string;
12
13
  export declare function listFiles(cfg: Config, baseDir: string): FileStat[];
13
14
  export interface ParsedDoc {
14
15
  relPath: string;
@@ -16,6 +17,7 @@ export interface ParsedDoc {
16
17
  size: number;
17
18
  presets: string[];
18
19
  data: Record<string, string | number | bigint | null>;
20
+ parseError: string | null;
19
21
  search: {
20
22
  title: string;
21
23
  summary: string;