sensemaking 0.24.6 → 0.25.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 (249) hide show
  1. package/README.md +20 -11
  2. package/dist/cjs/cli/build.d.cts +3 -0
  3. package/dist/cjs/cli/build.d.ts +3 -0
  4. package/dist/cjs/cli/build.js +195 -0
  5. package/dist/cjs/cli/build.js.map +1 -0
  6. package/dist/cjs/cli/index.d.cts +7 -6
  7. package/dist/cjs/cli/index.d.ts +7 -6
  8. package/dist/cjs/cli/index.js +12 -6
  9. package/dist/cjs/cli/index.js.map +1 -1
  10. package/dist/cjs/cli/init.js +2 -2
  11. package/dist/cjs/cli/init.js.map +1 -1
  12. package/dist/cjs/cli/map.js +7 -2
  13. package/dist/cjs/cli/map.js.map +1 -1
  14. package/dist/cjs/cli/named.js +63 -21
  15. package/dist/cjs/cli/named.js.map +1 -1
  16. package/dist/cjs/cli/path.js +7 -2
  17. package/dist/cjs/cli/path.js.map +1 -1
  18. package/dist/cjs/cli/peek.js +7 -2
  19. package/dist/cjs/cli/peek.js.map +1 -1
  20. package/dist/cjs/cli/related.js +55 -6
  21. package/dist/cjs/cli/related.js.map +1 -1
  22. package/dist/cjs/cli/search.js +54 -15
  23. package/dist/cjs/cli/search.js.map +1 -1
  24. package/dist/cjs/cli/shared.d.cts +9 -3
  25. package/dist/cjs/cli/shared.d.ts +9 -3
  26. package/dist/cjs/cli/shared.js +109 -74
  27. package/dist/cjs/cli/shared.js.map +1 -1
  28. package/dist/cjs/cli/sql.js +8 -3
  29. package/dist/cjs/cli/sql.js.map +1 -1
  30. package/dist/cjs/cli/status.js +142 -50
  31. package/dist/cjs/cli/status.js.map +1 -1
  32. package/dist/cjs/cli/types.d.cts +4 -2
  33. package/dist/cjs/cli/types.d.ts +4 -2
  34. package/dist/cjs/cli.js +10 -4
  35. package/dist/cjs/cli.js.map +1 -1
  36. package/dist/cjs/commands/map.js +10 -6
  37. package/dist/cjs/commands/map.js.map +1 -1
  38. package/dist/cjs/commands/peek.js +10 -6
  39. package/dist/cjs/commands/peek.js.map +1 -1
  40. package/dist/cjs/commands/related.d.cts +1 -0
  41. package/dist/cjs/commands/related.d.ts +1 -0
  42. package/dist/cjs/commands/related.js +56 -21
  43. package/dist/cjs/commands/related.js.map +1 -1
  44. package/dist/cjs/commands/scope.js +1 -1
  45. package/dist/cjs/commands/scope.js.map +1 -1
  46. package/dist/cjs/commands/search.js +102 -84
  47. package/dist/cjs/commands/search.js.map +1 -1
  48. package/dist/cjs/config/index.d.cts +1 -1
  49. package/dist/cjs/config/index.d.ts +1 -1
  50. package/dist/cjs/config/index.js.map +1 -1
  51. package/dist/cjs/config/load.d.cts +6 -1
  52. package/dist/cjs/config/load.d.ts +6 -1
  53. package/dist/cjs/config/load.js +38 -1
  54. package/dist/cjs/config/load.js.map +1 -1
  55. package/dist/cjs/config/types.d.cts +2 -1
  56. package/dist/cjs/config/types.d.ts +2 -1
  57. package/dist/cjs/config/types.js +1 -1
  58. package/dist/cjs/config/types.js.map +1 -1
  59. package/dist/cjs/config/validate.js +20 -0
  60. package/dist/cjs/config/validate.js.map +1 -1
  61. package/dist/cjs/embed/query.d.cts +2 -1
  62. package/dist/cjs/embed/query.d.ts +2 -1
  63. package/dist/cjs/embed/query.js +186 -109
  64. package/dist/cjs/embed/query.js.map +1 -1
  65. package/dist/cjs/errors.d.cts +1 -1
  66. package/dist/cjs/errors.d.ts +1 -1
  67. package/dist/cjs/errors.js.map +1 -1
  68. package/dist/cjs/features/embed.js.map +1 -1
  69. package/dist/cjs/graph/traverse.js +11 -6
  70. package/dist/cjs/graph/traverse.js.map +1 -1
  71. package/dist/cjs/index.d.cts +3 -3
  72. package/dist/cjs/index.d.ts +3 -3
  73. package/dist/cjs/index.js +3 -0
  74. package/dist/cjs/index.js.map +1 -1
  75. package/dist/cjs/lib/atomic-write.js +20 -6
  76. package/dist/cjs/lib/atomic-write.js.map +1 -1
  77. package/dist/cjs/lib/serial-query.d.cts +1 -0
  78. package/dist/cjs/lib/serial-query.d.ts +1 -0
  79. package/dist/cjs/lib/serial-query.js +22 -0
  80. package/dist/cjs/lib/serial-query.js.map +1 -0
  81. package/dist/cjs/scan/index.d.cts +5 -0
  82. package/dist/cjs/scan/index.d.ts +5 -0
  83. package/dist/cjs/scan/index.js +12 -4
  84. package/dist/cjs/scan/index.js.map +1 -1
  85. package/dist/cjs/scan/pool.d.cts +5 -0
  86. package/dist/cjs/scan/pool.d.ts +5 -0
  87. package/dist/cjs/scan/pool.js +167 -55
  88. package/dist/cjs/scan/pool.js.map +1 -1
  89. package/dist/cjs/store/builder.d.cts +6 -1
  90. package/dist/cjs/store/builder.d.ts +6 -1
  91. package/dist/cjs/store/builder.js +135 -5
  92. package/dist/cjs/store/builder.js.map +1 -1
  93. package/dist/cjs/store/duckdb/lexical.d.cts +2 -0
  94. package/dist/cjs/store/duckdb/lexical.d.ts +2 -0
  95. package/dist/cjs/store/duckdb/lexical.js +139 -7
  96. package/dist/cjs/store/duckdb/lexical.js.map +1 -1
  97. package/dist/cjs/store/duckdb/open.d.cts +3 -3
  98. package/dist/cjs/store/duckdb/open.d.ts +3 -3
  99. package/dist/cjs/store/duckdb/open.js +61 -42
  100. package/dist/cjs/store/duckdb/open.js.map +1 -1
  101. package/dist/cjs/store/duckdb/reconcile.js +2 -2
  102. package/dist/cjs/store/duckdb/reconcile.js.map +1 -1
  103. package/dist/cjs/store/duckdb/vectors.d.cts +1 -0
  104. package/dist/cjs/store/duckdb/vectors.d.ts +1 -0
  105. package/dist/cjs/store/duckdb/vectors.js +55 -43
  106. package/dist/cjs/store/duckdb/vectors.js.map +1 -1
  107. package/dist/cjs/store/index.d.cts +23 -4
  108. package/dist/cjs/store/index.d.ts +23 -4
  109. package/dist/cjs/store/index.js +224 -15
  110. package/dist/cjs/store/index.js.map +1 -1
  111. package/dist/cjs/store/open.d.cts +9 -1
  112. package/dist/cjs/store/open.d.ts +9 -1
  113. package/dist/cjs/store/open.js +479 -128
  114. package/dist/cjs/store/open.js.map +1 -1
  115. package/dist/cjs/store/reconcile.js +93 -63
  116. package/dist/cjs/store/reconcile.js.map +1 -1
  117. package/dist/cjs/store/sqlite/open.d.cts +3 -3
  118. package/dist/cjs/store/sqlite/open.d.ts +3 -3
  119. package/dist/cjs/store/sqlite/open.js +44 -36
  120. package/dist/cjs/store/sqlite/open.js.map +1 -1
  121. package/dist/cjs/store/turso/open.d.cts +3 -3
  122. package/dist/cjs/store/turso/open.d.ts +3 -3
  123. package/dist/cjs/store/turso/open.js +83 -66
  124. package/dist/cjs/store/turso/open.js.map +1 -1
  125. package/dist/cjs/store/turso/store.d.cts +3 -1
  126. package/dist/cjs/store/turso/store.d.ts +3 -1
  127. package/dist/cjs/store/turso/store.js +46 -31
  128. package/dist/cjs/store/turso/store.js.map +1 -1
  129. package/dist/cjs/store/types.d.cts +12 -3
  130. package/dist/cjs/store/types.d.ts +12 -3
  131. package/dist/cjs/store/types.js.map +1 -1
  132. package/dist/cjs/watch.js +155 -35
  133. package/dist/cjs/watch.js.map +1 -1
  134. package/dist/esm/cli/build.d.ts +3 -0
  135. package/dist/esm/cli/build.js +18 -0
  136. package/dist/esm/cli/build.js.map +1 -0
  137. package/dist/esm/cli/index.d.ts +7 -6
  138. package/dist/esm/cli/index.js +8 -6
  139. package/dist/esm/cli/index.js.map +1 -1
  140. package/dist/esm/cli/init.js +2 -2
  141. package/dist/esm/cli/init.js.map +1 -1
  142. package/dist/esm/cli/map.js +8 -2
  143. package/dist/esm/cli/map.js.map +1 -1
  144. package/dist/esm/cli/named.js +38 -14
  145. package/dist/esm/cli/named.js.map +1 -1
  146. package/dist/esm/cli/path.js +8 -2
  147. package/dist/esm/cli/path.js.map +1 -1
  148. package/dist/esm/cli/peek.js +8 -2
  149. package/dist/esm/cli/peek.js.map +1 -1
  150. package/dist/esm/cli/related.js +21 -3
  151. package/dist/esm/cli/related.js.map +1 -1
  152. package/dist/esm/cli/search.js +28 -7
  153. package/dist/esm/cli/search.js.map +1 -1
  154. package/dist/esm/cli/shared.d.ts +9 -3
  155. package/dist/esm/cli/shared.js +44 -24
  156. package/dist/esm/cli/shared.js.map +1 -1
  157. package/dist/esm/cli/sql.js +8 -2
  158. package/dist/esm/cli/sql.js.map +1 -1
  159. package/dist/esm/cli/status.js +166 -111
  160. package/dist/esm/cli/status.js.map +1 -1
  161. package/dist/esm/cli/types.d.ts +4 -2
  162. package/dist/esm/cli/types.js.map +1 -1
  163. package/dist/esm/cli.js +9 -4
  164. package/dist/esm/cli.js.map +1 -1
  165. package/dist/esm/commands/map.js +5 -1
  166. package/dist/esm/commands/map.js.map +1 -1
  167. package/dist/esm/commands/peek.js +5 -1
  168. package/dist/esm/commands/peek.js.map +1 -1
  169. package/dist/esm/commands/related.d.ts +1 -0
  170. package/dist/esm/commands/related.js +19 -10
  171. package/dist/esm/commands/related.js.map +1 -1
  172. package/dist/esm/commands/scope.js +1 -1
  173. package/dist/esm/commands/scope.js.map +1 -1
  174. package/dist/esm/commands/search.js +11 -10
  175. package/dist/esm/commands/search.js.map +1 -1
  176. package/dist/esm/config/index.d.ts +1 -1
  177. package/dist/esm/config/index.js.map +1 -1
  178. package/dist/esm/config/load.d.ts +6 -1
  179. package/dist/esm/config/load.js +32 -3
  180. package/dist/esm/config/load.js.map +1 -1
  181. package/dist/esm/config/types.d.ts +2 -1
  182. package/dist/esm/config/types.js +1 -1
  183. package/dist/esm/config/types.js.map +1 -1
  184. package/dist/esm/config/validate.js +20 -0
  185. package/dist/esm/config/validate.js.map +1 -1
  186. package/dist/esm/embed/query.d.ts +2 -1
  187. package/dist/esm/embed/query.js +40 -34
  188. package/dist/esm/embed/query.js.map +1 -1
  189. package/dist/esm/errors.d.ts +1 -1
  190. package/dist/esm/errors.js.map +1 -1
  191. package/dist/esm/features/embed.js.map +1 -1
  192. package/dist/esm/graph/traverse.js +5 -1
  193. package/dist/esm/graph/traverse.js.map +1 -1
  194. package/dist/esm/index.d.ts +3 -3
  195. package/dist/esm/index.js +1 -1
  196. package/dist/esm/index.js.map +1 -1
  197. package/dist/esm/lib/atomic-write.js +14 -6
  198. package/dist/esm/lib/atomic-write.js.map +1 -1
  199. package/dist/esm/lib/serial-query.d.ts +1 -0
  200. package/dist/esm/lib/serial-query.js +13 -0
  201. package/dist/esm/lib/serial-query.js.map +1 -0
  202. package/dist/esm/scan/index.d.ts +5 -0
  203. package/dist/esm/scan/index.js +7 -3
  204. package/dist/esm/scan/index.js.map +1 -1
  205. package/dist/esm/scan/pool.d.ts +5 -0
  206. package/dist/esm/scan/pool.js +41 -16
  207. package/dist/esm/scan/pool.js.map +1 -1
  208. package/dist/esm/store/builder.d.ts +6 -1
  209. package/dist/esm/store/builder.js +19 -0
  210. package/dist/esm/store/builder.js.map +1 -1
  211. package/dist/esm/store/duckdb/lexical.d.ts +2 -0
  212. package/dist/esm/store/duckdb/lexical.js +32 -4
  213. package/dist/esm/store/duckdb/lexical.js.map +1 -1
  214. package/dist/esm/store/duckdb/open.d.ts +3 -3
  215. package/dist/esm/store/duckdb/open.js +16 -7
  216. package/dist/esm/store/duckdb/open.js.map +1 -1
  217. package/dist/esm/store/duckdb/reconcile.js +2 -2
  218. package/dist/esm/store/duckdb/reconcile.js.map +1 -1
  219. package/dist/esm/store/duckdb/vectors.d.ts +1 -0
  220. package/dist/esm/store/duckdb/vectors.js +18 -14
  221. package/dist/esm/store/duckdb/vectors.js.map +1 -1
  222. package/dist/esm/store/index.d.ts +23 -4
  223. package/dist/esm/store/index.js +80 -15
  224. package/dist/esm/store/index.js.map +1 -1
  225. package/dist/esm/store/open.d.ts +9 -1
  226. package/dist/esm/store/open.js +175 -84
  227. package/dist/esm/store/open.js.map +1 -1
  228. package/dist/esm/store/reconcile.js +12 -0
  229. package/dist/esm/store/reconcile.js.map +1 -1
  230. package/dist/esm/store/sqlite/open.d.ts +3 -3
  231. package/dist/esm/store/sqlite/open.js +9 -6
  232. package/dist/esm/store/sqlite/open.js.map +1 -1
  233. package/dist/esm/store/turso/open.d.ts +3 -3
  234. package/dist/esm/store/turso/open.js +14 -10
  235. package/dist/esm/store/turso/open.js.map +1 -1
  236. package/dist/esm/store/turso/store.d.ts +3 -1
  237. package/dist/esm/store/turso/store.js +5 -1
  238. package/dist/esm/store/turso/store.js.map +1 -1
  239. package/dist/esm/store/types.d.ts +12 -3
  240. package/dist/esm/store/types.js.map +1 -1
  241. package/dist/esm/watch.js +57 -19
  242. package/dist/esm/watch.js.map +1 -1
  243. package/package.json +1 -1
  244. package/schema.json +7 -2
  245. package/skills/sense/SKILL.md +3 -3
  246. package/skills/sense-bases/SKILL.md +1 -2
  247. package/skills/sense-setup/SKILL.md +1 -1
  248. package/skills/sense-setup/references/embeddings.md +1 -1
  249. package/skills/sense-setup/references/store-benchmarks.md +6 -6
package/README.md CHANGED
@@ -2,20 +2,20 @@
2
2
 
3
3
  Search and query a directory of Markdown notes from the command line. `sense` indexes frontmatter, prose and links in a local database. It can also combine word matches with links and semantic similarity.
4
4
 
5
- Results contain file paths, snippets and line ranges. A person or agent can inspect the relevant passages without loading every note. No server or build step is required.
5
+ Results contain file paths, snippets and line ranges. A person or agent can inspect the relevant passages without loading every note. No server or daemon is required; the default CLI query performs the incremental preparation it needs.
6
6
 
7
7
  ## Problem
8
8
 
9
9
  Markdown notes accumulate: research, decisions, meeting notes, agent output. Past a few dozen, finding the ones relevant to what you're doing means grepping or reading whole folders into context. The structure that makes notes navigable (frontmatter, wikilinks, headings) is exactly what a query needs, but nothing exposes it as a query surface.
10
10
 
11
- `sense` indexes all of it into a local database (SQLite by default, or the experimental DuckDB store, see Config) and reconciles against file timestamps on every query, so results are never stale and nothing has to be running.
11
+ `sense` indexes all of it into a local database (SQLite by default, or the experimental DuckDB store, see Config). By default, CLI queries reconcile the capabilities they need before reading; `--no-build` instead reads the last completed indexed generation without scanning live files. Nothing has to be running.
12
12
 
13
13
  ## Quick start
14
14
 
15
15
  ```bash
16
16
  npm install -g sensemaking
17
17
  cd your-notes && sense init
18
- sense download # the embedding model, once per machine; the first vector search fetches it otherwise
18
+ sense download # optional prefetch; build or the first default vector search fetches it otherwise
19
19
  ```
20
20
 
21
21
  Requires Node.js 22.20 or newer. The default store uses Node's built-in SQLite.
@@ -65,6 +65,7 @@ ORDER BY bm25(content, 10.0, 5.0, 1.0) LIMIT 10
65
65
 
66
66
  | command | does |
67
67
  |---|---|
68
+ | `build [--force]` | incrementally update the derived index and prepare every configured search capability; `--force` recreates only `.sense/` |
68
69
  | `map` | doc count, frontmatter field coverage, top hubs by link rank, recent changes; hub/recent limits use bytewise path order on ties |
69
70
  | `search "<text>" [--preset name] [--include glob] [--exclude glob] [--no-exclude] [--where "<sql>"] [--k n] [--snippet-char-limit n] [--snippet-count-limit n]` | words + links + vectors, one fused ranked list; `via` labels each row's evidence. `--k` bounds notes returned, `--snippet-char-limit` (default 80) each passage, `--snippet-count-limit` (default 1) passages per note |
70
71
  | `peek <path> [--preset name] [--where "<sql>"]` | frontmatter + heading outline (`[L143-162, ~380t]`) + links both ways (first 20 per list, each with its total) |
@@ -74,9 +75,15 @@ ORDER BY bm25(content, 10.0, 5.0, 1.0) LIMIT 10
74
75
  | `<name> [params...]` | run a query saved in the config; `--list` names them |
75
76
  | `init` | write a starter `sense.config.json` |
76
77
  | `status` | index location, doc count, per-preset coverage, watcher heartbeat |
77
- | `download` | fetch the embedding model named in the config (once per machine; the first vector search fetches it otherwise) |
78
+ | `download` | prefetch the embedding model named in the config; build, watch, or a default CLI vector query fetches it when needed otherwise |
78
79
  | `watch` | keep the index warm in the background (optional; see [watch coordination](https://github.com/kmalakoff/sensemaking/blob/master/DESIGN.md#watch-coordination)) |
79
80
 
81
+ Query commands use the config's `"build": true` default to update the index first and prepare only what that operation needs. Core map, peek, path and SQL work do not prepare vectors. Set `"build": false` for a manual-build or watch workflow, or add `--no-build` for one query. These read the last completed generation without scanning source files or repairing missing readiness; they fail with a `sense build` instruction when the requested capability is not ready. This disables Sense index maintenance, not database access or arbitrary SQL.
82
+
83
+ The completed generation stores the exact decoded source used for indexed snippets. A no-build query reads those stored sources and checks readiness for the capabilities it requests; it does not hydrate from newer live files. A default query incrementally scans the configured tree for the capabilities it needs; vector preparation is limited to its eligible scope. `sense build` prepares every configured capability, and `sense watch` keeps them prepared as changes arrive.
84
+
85
+ Explicit `sense build` and `sense watch` prepare the index regardless of the config's `build` default. Watch builds before reporting ready, then processes edits; a no-build query can read the previous generation while an edit is being processed. Library callers choose preparation separately at `open`: `open(config)` prepares every configured capability, and `open(config, { build: false })` opens existing compatible state. The config's `build` setting controls CLI queries only. `build(config, { force: true })` recreates only the derived index. Public `search`, `mapTree`, and `peek` calls on one retained `Store` serialize with one another. Await those calls before running raw SQL, starting a transaction, or closing the handle.
86
+
80
87
  `search` runs one text through every engine its scope has: FTS5 word match (BM25-ranked, bare words AND-join, operators are yours on `sqlite`; on `duckdb` and `turso` the FTS5 operators are a named error, see Config), a personalized-PageRank walk over the link graph, and vector similarity, fused into one list. `via` labels each row's evidence (`match`, `link`, `vector`, combinations). Within the vector signal, candidates rank by the true cosine against the best-matching canonical chunk before `similarity` is rounded to three decimals for display; a zero-direction vector has similarity `0`, exact cosine ties use bytewise path order, and equal-scoring chunks choose the earliest authored chunk. The public search list ranks the combined word, link, and vector candidates by fused reciprocal-rank score. `lines` points at the section that earned the row (a direct read range). A `vector`-only row means the search words don't appear in that note; it showed up because the model judged it semantically related. `--preset` picks a named settings bundle from the config, `--where` filters on frontmatter. `--format json` on any reporting command returns structured output, and `--format csv` writes the row-returning commands one row per line, for redirecting a large result to a file instead of into context; `--version` and `--help` do what they say.
81
88
 
82
89
  Search rows carry `snippets: string[]`. Each passage is generated around the matched words, marked with `«»`, and limited to 80 characters by default. `--snippet-count-limit` returns more non-overlapping passages from a note, in document order. Link- and vector-only rows have `snippets: []`.
@@ -90,7 +97,8 @@ Lexical words are case- and accent-insensitive. SQLite and DuckDB use their nati
90
97
  ```json
91
98
  {
92
99
  "$schema": "https://unpkg.com/sensemaking/schema.json",
93
- "version": 5,
100
+ "version": 6,
101
+ "build": true,
94
102
  "presets": {
95
103
  "default": { "include": ["**/*.md"], "k": 10 },
96
104
  "raw": { "include": ["raw/**/*.md"], "k": 5 }
@@ -106,6 +114,7 @@ Lexical words are case- and accent-insensitive. SQLite and DuckDB use their nati
106
114
 
107
115
  | key | holds |
108
116
  |---|---|
117
+ | `build` | CLI query-time build default, `true`. Set `false` to query the existing index maintained by explicit `build` or `watch`; `--no-build` overrides `true` for one query. |
109
118
  | `root` | optional markdown-tree path. Relative to the config directory; omitted means that directory. Preset globs, filesystem reads, watcher events, and indexed `path` values use this root. `.sense/` state stays beside the config. Changing it rebuilds the index. |
110
119
  | `presets` | named bundles of `include`/`exclude` globs, `k` (result count), `signals` (which engines this scope searches with, `words`, `links`, `vectors`; every signal whose prerequisites hold, unless the preset lists them exhaustively), `where` (a standing SQL filter). A file is indexed if any preset includes it, embedded if a model is named and some covering preset's `signals` include `vectors`; `status` shows each preset's coverage. |
111
120
  | `embed` | the model vectors are built with. Naming one gives the tree vectors; omitting the block means none at all, whatever the presets say. `sense download` fetches it. |
@@ -119,9 +128,9 @@ Bare commands use the `default` preset; `--preset` names another; flags override
119
128
 
120
129
  Choose `sqlite` for the smallest setup, full FTS5 query syntax, and concurrent Sense commands. Choose `duckdb` when the cache should participate in DuckDB analytical work over large datasets or in local/cloud workflows. Choose `turso` for its embedded Rust engine and Tantivy text index. The DuckDB and Turso adapters are experimental, install their native package on first use, and currently serialize Sense commands that open the same cache.
121
130
 
122
- The commands and table names are shared. Raw SQL still follows the selected engine's dialect, and advanced FTS5 operators only work on `sqlite`.
131
+ The commands and table names are shared. Raw SQL still follows the selected engine's dialect, and advanced FTS5 operators only work on `sqlite`. DuckDB and Turso hold their cache file for the life of a native handle, so Sense commands opening the same cache wait for the current command or watcher cycle to close; this is an adapter limitation, not a reader/writer coexistence guarantee.
123
132
 
124
- Vectors need a model. Naming a Hugging Face id in `embed.model` is consent to fetch it: it downloads lazily, on the first vector search, with progress on stderr, into `~/.sense/models` (huggingface_hub's cache layout, one snapshot directory per resolved revision, shared by every tree, 124 MB, never in the package). `sense download` prefetches the same model ahead of time, so the wait happens on your schedule instead of the first query's; it is idempotent and prints the resolved revision. `embed.model` is a Hugging Face id, or a path to a directory holding `model.safetensors` and `tokenizer.json`, which nothing fetches for you. A preset that asks for vectors when a local model path is missing those files is an error naming the fix, rather than a quieter result that would make the same search answer differently before and after; a preset whose `signals` exclude `vectors` never asks, so it is unaffected. An optional top-level `"embed": { "model", "provider", "url", "key" }` block points at any Model2Vec model, local path, or OpenAI-compatible endpoint (Ollama, LM Studio, hosted). Embedding the notes themselves happens on the first vector search, with progress.
133
+ Vectors need a model. Naming a Hugging Face id in `embed.model` is consent to fetch it when `sense build`, `sense watch`, or a default CLI vector query first prepares vectors, with progress on stderr, into `~/.sense/models` (huggingface_hub's cache layout, one snapshot directory per resolved revision, shared by every tree, 124 MB, never in the package). `sense download` prefetches the same model ahead of time; it is idempotent and prints the resolved revision. `embed.model` is a Hugging Face id, or a path to a directory holding `model.safetensors` and `tokenizer.json`, which nothing fetches for you. A preset that asks for vectors when a local model path is missing those files is an error naming the fix, rather than a quieter result that would make the same search answer differently before and after; a preset whose `signals` exclude `vectors` never asks, so it is unaffected. An optional top-level `"embed": { "model", "provider", "url", "key" }` block points at any Model2Vec model, local path, or OpenAI-compatible endpoint (Ollama, LM Studio, hosted). Explicit builds and watch prepare all configured vectors. A default CLI vector query prepares only its eligible scope; `--no-build` requires that scope to be ready and never prepares it. Unrelated pending documents do not block either path.
125
134
 
126
135
  Sense adds `has(field, value)` for array membership or string containment and `basename(path)` for path queries on every store. SQLite and DuckDB also provide `segment(terms)` for hand-written matching over text without word spaces. A frontmatter syntax error records `_parse_error` and leaves that file's discovered fields empty; the file's content still enters the index.
127
136
 
@@ -155,11 +164,11 @@ Ollama serves this shape at `http://localhost:11434/v1`. LM Studio serves the sa
155
164
 
156
165
  ## Scale
157
166
 
158
- Every query starts with a freshness check against the cache in `.sense/`; only changed files are re-parsed. What to expect as a tree grows:
167
+ Default CLI queries start with an incremental build of the capabilities they need; only changed files are re-parsed. `--no-build` skips that scan and reads the last completed generation. What to expect as a tree grows:
159
168
 
160
- - **Work is linear in note count.** Crawl, reconcile, and the freshness check are what every invocation pays; that check is the floor cost of a query and the first thing to watch on a large tree.
169
+ - **Build work is linear in note count.** Crawl and reconcile are the floor cost of a default query and the first thing to watch on a large tree; `--no-build` avoids them when snapshot semantics are appropriate.
161
170
  - **Output is flat.** `map`, `peek`, and a search row cost the same on a small tree as a large one: context cost is bounded by what you ask for, not by how much there is.
162
- - **Bulk changes are paid by whoever queries next.** `sense watch` moves that re-parse into the background ([watch coordination](https://github.com/kmalakoff/sensemaking/blob/master/DESIGN.md#watch-coordination)): it changes latency, never answers, since every query reconciles for itself. To start the cache over, delete the directory `sense status` prints.
171
+ - **Bulk changes are paid by the next builder.** That is normally the next default query. `sense watch` moves the re-parse into the background ([watch coordination](https://github.com/kmalakoff/sensemaking/blob/master/DESIGN.md#watch-coordination)); `--no-build` continues to read the last completed generation. Run `sense build --force` to recreate the derived index.
163
172
 
164
173
  ## For AI agents
165
174
 
@@ -178,7 +187,7 @@ Three skills: `sense` for querying a tree, including store-specific SQL and sear
178
187
  ## Alternatives
179
188
 
180
189
  - **Obsidian Bases/Dataview:** same filters, but only inside the running app; agents can't query it headless.
181
- - **Index-on-build tools (MarkdownDB):** query a snapshot; `sense` reconciles on every query.
190
+ - **Index-on-build tools (MarkdownDB):** query a snapshot; `sense` defaults to an incremental build before querying and also offers explicit snapshot reads with `--no-build`.
182
191
  - **Note CLIs (zk):** fixed schema; `sense` filters on arbitrary frontmatter.
183
192
  - **Graph/LSP tools (IWE):** structural queries over a markdown graph via LSP/CLI/MCP, retrieval by structure rather than similarity; no SQL, no vector search.
184
193
  - **Markdown vector stores (markdown-vdb):** hybrid BM25 + vector search over markdown files, no frontmatter filtering; `sense` treats vectors as one signal alongside SQL, not the whole store.
@@ -0,0 +1,3 @@
1
+ import type { Command } from './types.js';
2
+ declare const build: Command;
3
+ export default build;
@@ -0,0 +1,3 @@
1
+ import type { Command } from './types.js';
2
+ declare const build: Command;
3
+ export default build;
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "default", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return _default;
9
+ }
10
+ });
11
+ var _indexts = require("../store/index.js");
12
+ var _indexts1 = require("./index.js");
13
+ var _sharedts = require("./shared.js");
14
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
15
+ try {
16
+ var info = gen[key](arg);
17
+ var value = info.value;
18
+ } catch (error) {
19
+ reject(error);
20
+ return;
21
+ }
22
+ if (info.done) resolve(value);
23
+ else Promise.resolve(value).then(_next, _throw);
24
+ }
25
+ function _async_to_generator(fn) {
26
+ return function() {
27
+ var self = this, args = arguments;
28
+ return new Promise(function(resolve, reject) {
29
+ var gen = fn.apply(self, args);
30
+ function _next(value) {
31
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
32
+ }
33
+ function _throw(err) {
34
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
35
+ }
36
+ _next(undefined);
37
+ });
38
+ };
39
+ }
40
+ function _define_property(obj, key, value) {
41
+ if (key in obj) {
42
+ Object.defineProperty(obj, key, {
43
+ value: value,
44
+ enumerable: true,
45
+ configurable: true,
46
+ writable: true
47
+ });
48
+ } else obj[key] = value;
49
+ return obj;
50
+ }
51
+ function _object_spread(target) {
52
+ for(var i = 1; i < arguments.length; i++){
53
+ var source = arguments[i] != null ? arguments[i] : {};
54
+ var ownKeys = Object.keys(source);
55
+ if (typeof Object.getOwnPropertySymbols === "function") {
56
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
57
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
58
+ }));
59
+ }
60
+ ownKeys.forEach(function(key) {
61
+ _define_property(target, key, source[key]);
62
+ });
63
+ }
64
+ return target;
65
+ }
66
+ function _ts_generator(thisArg, body) {
67
+ var f, y, t, _ = {
68
+ label: 0,
69
+ sent: function() {
70
+ if (t[0] & 1) throw t[1];
71
+ return t[1];
72
+ },
73
+ trys: [],
74
+ ops: []
75
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
76
+ return d(g, "next", {
77
+ value: verb(0)
78
+ }), d(g, "throw", {
79
+ value: verb(1)
80
+ }), d(g, "return", {
81
+ value: verb(2)
82
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
83
+ value: function() {
84
+ return this;
85
+ }
86
+ }), g;
87
+ function verb(n) {
88
+ return function(v) {
89
+ return step([
90
+ n,
91
+ v
92
+ ]);
93
+ };
94
+ }
95
+ function step(op) {
96
+ if (f) throw new TypeError("Generator is already executing.");
97
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
98
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
99
+ if (y = 0, t) op = [
100
+ op[0] & 2,
101
+ t.value
102
+ ];
103
+ switch(op[0]){
104
+ case 0:
105
+ case 1:
106
+ t = op;
107
+ break;
108
+ case 4:
109
+ _.label++;
110
+ return {
111
+ value: op[1],
112
+ done: false
113
+ };
114
+ case 5:
115
+ _.label++;
116
+ y = op[1];
117
+ op = [
118
+ 0
119
+ ];
120
+ continue;
121
+ case 7:
122
+ op = _.ops.pop();
123
+ _.trys.pop();
124
+ continue;
125
+ default:
126
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
127
+ _ = 0;
128
+ continue;
129
+ }
130
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
131
+ _.label = op[1];
132
+ break;
133
+ }
134
+ if (op[0] === 6 && _.label < t[1]) {
135
+ _.label = t[1];
136
+ t = op;
137
+ break;
138
+ }
139
+ if (t && _.label < t[2]) {
140
+ _.label = t[2];
141
+ _.ops.push(op);
142
+ break;
143
+ }
144
+ if (t[2]) _.ops.pop();
145
+ _.trys.pop();
146
+ continue;
147
+ }
148
+ op = body.call(thisArg, _);
149
+ } catch (e) {
150
+ op = [
151
+ 6,
152
+ e
153
+ ];
154
+ y = 0;
155
+ } finally{
156
+ f = t = 0;
157
+ }
158
+ if (op[0] & 5) throw op[1];
159
+ return {
160
+ value: op[0] ? op[1] : void 0,
161
+ done: true
162
+ };
163
+ }
164
+ }
165
+ var build = function build(ctx) {
166
+ return _async_to_generator(function() {
167
+ var values, result;
168
+ return _ts_generator(this, function(_state) {
169
+ switch(_state.label){
170
+ case 0:
171
+ values = (0, _sharedts.parse)(ctx.argv, "usage: ".concat(ctx.name, " ").concat(_indexts1.USAGE.build), _object_spread({
172
+ force: {
173
+ type: 'boolean',
174
+ default: false
175
+ }
176
+ }, _sharedts.CONFIG)).values;
177
+ return [
178
+ 4,
179
+ (0, _indexts.buildIndex)(ctx.resolveConfig(values.config), {
180
+ force: values.force === true
181
+ })
182
+ ];
183
+ case 1:
184
+ result = _state.sent();
185
+ (0, _sharedts.printWarnings)(result.warnings);
186
+ console.log("".concat(ctx.name, " build: ").concat(result.parsed, " file(s) parsed; index ready at ").concat(result.dbPath));
187
+ return [
188
+ 2
189
+ ];
190
+ }
191
+ });
192
+ })();
193
+ };
194
+ var _default = build;
195
+ /* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/build.ts"],"sourcesContent":["import { buildIndex } from '../store/index.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, parse, printWarnings } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst build: Command = async (ctx) => {\n const { values } = parse(ctx.argv, `usage: ${ctx.name} ${USAGE.build}`, { force: { type: 'boolean', default: false }, ...CONFIG });\n const result = await buildIndex(ctx.resolveConfig(values.config as string | undefined), { force: values.force === true });\n printWarnings(result.warnings);\n console.log(`${ctx.name} build: ${result.parsed} file(s) parsed; index ready at ${result.dbPath}`);\n};\n\nexport default build;\n"],"names":["build","ctx","values","result","parse","argv","USAGE","name","force","type","default","CONFIG","buildIndex","resolveConfig","config","printWarnings","warnings","console","log","parsed","dbPath"],"mappings":";;;;+BAYA;;;eAAA;;;uBAZ2B;wBACL;wBACuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG7C,IAAMA,QAAiB,eAAOC;;YACpBC,QACFC;;;;oBADED,SAAWE,IAAAA,eAAK,EAACH,IAAII,IAAI,EAAE,AAAC,UAAqBC,OAAZL,IAAIM,IAAI,EAAC,KAAe,OAAZD,eAAK,CAACN,KAAK,GAAI;wBAAEQ,OAAO;4BAAEC,MAAM;4BAAWC,SAAS;wBAAM;uBAAMC,gBAAM,GAAvHT;oBACO;;wBAAMU,IAAAA,mBAAU,EAACX,IAAIY,aAAa,CAACX,OAAOY,MAAM,GAAyB;4BAAEN,OAAON,OAAOM,KAAK,KAAK;wBAAK;;;oBAAjHL,SAAS;oBACfY,IAAAA,uBAAa,EAACZ,OAAOa,QAAQ;oBAC7BC,QAAQC,GAAG,CAAC,AAAC,GAAqBf,OAAnBF,IAAIM,IAAI,EAAC,YAA0DJ,OAAhDA,OAAOgB,MAAM,EAAC,oCAAgD,OAAdhB,OAAOiB,MAAM;;;;;;IACjG;;IAEA,WAAepB"}
@@ -1,15 +1,16 @@
1
1
  import type { Command } from './types.js';
2
2
  export declare const USAGE: {
3
3
  readonly init: "init [--model id-or-path] [--provider static|openai|cohere] [--url url]";
4
+ readonly build: "build [--force] [--config path]";
4
5
  readonly watch: "watch [--force] [--config path]";
5
6
  readonly status: "status [--format table|json] [--config path]";
6
7
  readonly download: "download [--config path]";
7
- readonly sql: "sql \"<statement>\" [params...] [--preset name] [--format table|json|csv] [--config path]";
8
- readonly search: "search \"<terms>\" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--snippet-char-limit n] [--snippet-count-limit n] [--format table|json|csv] [--config path]";
9
- readonly map: "map [--format table|json] [--config path]";
10
- readonly peek: "peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--format table|json] [--config path]";
11
- readonly path: "path <a> <b> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--max-depth n] [--format table|json] [--config path]";
12
- readonly related: "related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json|csv] [--config path]";
8
+ readonly sql: "sql \"<statement>\" [params...] [--preset name] [--no-build] [--format table|json|csv] [--config path]";
9
+ readonly search: "search \"<terms>\" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--snippet-char-limit n] [--snippet-count-limit n] [--no-build] [--format table|json|csv] [--config path]";
10
+ readonly map: "map [--no-build] [--format table|json] [--config path]";
11
+ readonly peek: "peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--no-build] [--format table|json] [--config path]";
12
+ readonly path: "path <a> <b> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--max-depth n] [--no-build] [--format table|json] [--config path]";
13
+ readonly related: "related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--no-build] [--format table|json|csv] [--config path]";
13
14
  };
14
15
  export declare const COMMANDS: Record<string, () => Promise<{
15
16
  default: Command;
@@ -1,15 +1,16 @@
1
1
  import type { Command } from './types.js';
2
2
  export declare const USAGE: {
3
3
  readonly init: "init [--model id-or-path] [--provider static|openai|cohere] [--url url]";
4
+ readonly build: "build [--force] [--config path]";
4
5
  readonly watch: "watch [--force] [--config path]";
5
6
  readonly status: "status [--format table|json] [--config path]";
6
7
  readonly download: "download [--config path]";
7
- readonly sql: "sql \"<statement>\" [params...] [--preset name] [--format table|json|csv] [--config path]";
8
- readonly search: "search \"<terms>\" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--snippet-char-limit n] [--snippet-count-limit n] [--format table|json|csv] [--config path]";
9
- readonly map: "map [--format table|json] [--config path]";
10
- readonly peek: "peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--format table|json] [--config path]";
11
- readonly path: "path <a> <b> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--max-depth n] [--format table|json] [--config path]";
12
- readonly related: "related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json|csv] [--config path]";
8
+ readonly sql: "sql \"<statement>\" [params...] [--preset name] [--no-build] [--format table|json|csv] [--config path]";
9
+ readonly search: "search \"<terms>\" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--snippet-char-limit n] [--snippet-count-limit n] [--no-build] [--format table|json|csv] [--config path]";
10
+ readonly map: "map [--no-build] [--format table|json] [--config path]";
11
+ readonly peek: "peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--no-build] [--format table|json] [--config path]";
12
+ readonly path: "path <a> <b> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--max-depth n] [--no-build] [--format table|json] [--config path]";
13
+ readonly related: "related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--no-build] [--format table|json|csv] [--config path]";
13
14
  };
14
15
  export declare const COMMANDS: Record<string, () => Promise<{
15
16
  default: Command;
@@ -48,15 +48,16 @@ function _interop_require_wildcard(obj, nodeInterop) {
48
48
  }
49
49
  var USAGE = {
50
50
  init: 'init [--model id-or-path] [--provider static|openai|cohere] [--url url]',
51
+ build: 'build [--force] [--config path]',
51
52
  watch: 'watch [--force] [--config path]',
52
53
  status: 'status [--format table|json] [--config path]',
53
54
  download: 'download [--config path]',
54
- sql: 'sql "<statement>" [params...] [--preset name] [--format table|json|csv] [--config path]',
55
- search: 'search "<terms>" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--k n] [--snippet-char-limit n] [--snippet-count-limit n] [--format table|json|csv] [--config path]',
56
- map: 'map [--format table|json] [--config path]',
57
- peek: 'peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--format table|json] [--config path]',
58
- path: 'path <a> <b> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--max-depth n] [--format table|json] [--config path]',
59
- related: 'related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--k n] [--format table|json|csv] [--config path]'
55
+ sql: 'sql "<statement>" [params...] [--preset name] [--no-build] [--format table|json|csv] [--config path]',
56
+ search: 'search "<terms>" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--k n] [--snippet-char-limit n] [--snippet-count-limit n] [--no-build] [--format table|json|csv] [--config path]',
57
+ map: 'map [--no-build] [--format table|json] [--config path]',
58
+ peek: 'peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--no-build] [--format table|json] [--config path]',
59
+ path: 'path <a> <b> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--max-depth n] [--no-build] [--format table|json] [--config path]',
60
+ related: 'related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where "<sql>"] [--k n] [--no-build] [--format table|json|csv] [--config path]'
60
61
  };
61
62
  var COMMANDS = {
62
63
  init: function init() {
@@ -64,6 +65,11 @@ var COMMANDS = {
64
65
  return /*#__PURE__*/ _interop_require_wildcard(require("./init.js"));
65
66
  });
66
67
  },
68
+ build: function build() {
69
+ return Promise.resolve().then(function() {
70
+ return /*#__PURE__*/ _interop_require_wildcard(require("./build.js"));
71
+ });
72
+ },
67
73
  watch: function watch() {
68
74
  return Promise.resolve().then(function() {
69
75
  return /*#__PURE__*/ _interop_require_wildcard(require("./watch.js"));
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/index.ts"],"sourcesContent":["import type { Command } from './types.ts';\n\n// Each command's usage line, minus the leading \"usage: <name> \": shared by cli.ts's\n// usage() and the command's own parse() error/--help output so there is one copy, not two.\nexport const USAGE = {\n init: 'init [--model id-or-path] [--provider static|openai|cohere] [--url url]',\n watch: 'watch [--force] [--config path]',\n status: 'status [--format table|json] [--config path]',\n download: 'download [--config path]',\n sql: 'sql \"<statement>\" [params...] [--preset name] [--format table|json|csv] [--config path]',\n search: 'search \"<terms>\" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--snippet-char-limit n] [--snippet-count-limit n] [--format table|json|csv] [--config path]',\n map: 'map [--format table|json] [--config path]',\n peek: 'peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--format table|json] [--config path]',\n path: 'path <a> <b> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--max-depth n] [--format table|json] [--config path]',\n related: 'related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--format table|json|csv] [--config path]',\n} as const;\n\n// Lazy registry: a command's imports load only when it runs, so a heavy dependency in one\n// command never taxes the others (or --version/--help). These names are reserved from saved queries.\nexport const COMMANDS: Record<string, () => Promise<{ default: Command }>> = {\n init: () => import('./init.ts'),\n watch: () => import('./watch.ts'),\n status: () => import('./status.ts'),\n download: () => import('./download.ts'),\n sql: () => import('./sql.ts'),\n search: () => import('./search.ts'),\n map: () => import('./map.ts'),\n peek: () => import('./peek.ts'),\n path: () => import('./path.ts'),\n related: () => import('./related.ts'),\n};\n\nexport type { Command, Ctx } from './types.ts';\n"],"names":["COMMANDS","USAGE","init","watch","status","download","sql","search","map","peek","path","related"],"mappings":";;;;;;;;;;;QAmBaA;eAAAA;;QAfAC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAN,IAAMA,QAAQ;IACnBC,MAAM;IACNC,OAAO;IACPC,QAAQ;IACRC,UAAU;IACVC,KAAK;IACLC,QAAQ;IACRC,KAAK;IACLC,MAAM;IACNC,MAAM;IACNC,SAAS;AACX;AAIO,IAAMX,WAAgE;IAC3EE,MAAM,SAANA;eAAY;2DAAA,QAAO;;;IACnBC,OAAO,SAAPA;eAAa;2DAAA,QAAO;;;IACpBC,QAAQ,SAARA;eAAc;2DAAA,QAAO;;;IACrBC,UAAU,SAAVA;eAAgB;2DAAA,QAAO;;;IACvBC,KAAK,SAALA;eAAW;2DAAA,QAAO;;;IAClBC,QAAQ,SAARA;eAAc;2DAAA,QAAO;;;IACrBC,KAAK,SAALA;eAAW;2DAAA,QAAO;;;IAClBC,MAAM,SAANA;eAAY;2DAAA,QAAO;;;IACnBC,MAAM,SAANA;eAAY;2DAAA,QAAO;;;IACnBC,SAAS,SAATA;eAAe;2DAAA,QAAO;;;AACxB"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/index.ts"],"sourcesContent":["import type { Command } from './types.ts';\n\n// Each command's usage line, minus the leading \"usage: <name> \": shared by cli.ts's\n// usage() and the command's own parse() error/--help output so there is one copy, not two.\nexport const USAGE = {\n init: 'init [--model id-or-path] [--provider static|openai|cohere] [--url url]',\n build: 'build [--force] [--config path]',\n watch: 'watch [--force] [--config path]',\n status: 'status [--format table|json] [--config path]',\n download: 'download [--config path]',\n sql: 'sql \"<statement>\" [params...] [--preset name] [--no-build] [--format table|json|csv] [--config path]',\n search: 'search \"<terms>\" [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--snippet-char-limit n] [--snippet-count-limit n] [--no-build] [--format table|json|csv] [--config path]',\n map: 'map [--no-build] [--format table|json] [--config path]',\n peek: 'peek <path> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--no-build] [--format table|json] [--config path]',\n path: 'path <a> <b> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--max-depth n] [--no-build] [--format table|json] [--config path]',\n related: 'related <note> [--preset name] [--include glob ...] [--exclude glob ...] [--no-exclude] [--where \"<sql>\"] [--k n] [--no-build] [--format table|json|csv] [--config path]',\n} as const;\n\n// Lazy registry: a command's imports load only when it runs, so a heavy dependency in one\n// command never taxes the others (or --version/--help). These names are reserved from saved queries.\nexport const COMMANDS: Record<string, () => Promise<{ default: Command }>> = {\n init: () => import('./init.ts'),\n build: () => import('./build.ts'),\n watch: () => import('./watch.ts'),\n status: () => import('./status.ts'),\n download: () => import('./download.ts'),\n sql: () => import('./sql.ts'),\n search: () => import('./search.ts'),\n map: () => import('./map.ts'),\n peek: () => import('./peek.ts'),\n path: () => import('./path.ts'),\n related: () => import('./related.ts'),\n};\n\nexport type { Command, Ctx } from './types.ts';\n"],"names":["COMMANDS","USAGE","init","build","watch","status","download","sql","search","map","peek","path","related"],"mappings":";;;;;;;;;;;QAoBaA;eAAAA;;QAhBAC;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAN,IAAMA,QAAQ;IACnBC,MAAM;IACNC,OAAO;IACPC,OAAO;IACPC,QAAQ;IACRC,UAAU;IACVC,KAAK;IACLC,QAAQ;IACRC,KAAK;IACLC,MAAM;IACNC,MAAM;IACNC,SAAS;AACX;AAIO,IAAMZ,WAAgE;IAC3EE,MAAM,SAANA;eAAY;2DAAA,QAAO;;;IACnBC,OAAO,SAAPA;eAAa;2DAAA,QAAO;;;IACpBC,OAAO,SAAPA;eAAa;2DAAA,QAAO;;;IACpBC,QAAQ,SAARA;eAAc;2DAAA,QAAO;;;IACrBC,UAAU,SAAVA;eAAgB;2DAAA,QAAO;;;IACvBC,KAAK,SAALA;eAAW;2DAAA,QAAO;;;IAClBC,QAAQ,SAARA;eAAc;2DAAA,QAAO;;;IACrBC,KAAK,SAALA;eAAW;2DAAA,QAAO;;;IAClBC,MAAM,SAANA;eAAY;2DAAA,QAAO;;;IACnBC,MAAM,SAANA;eAAY;2DAAA,QAAO;;;IACnBC,SAAS,SAATA;eAAe;2DAAA,QAAO;;;AACxB"}
@@ -40,9 +40,9 @@ var init = function init(ctx) {
40
40
  // Naming a model is consent to fetch it, so writing one into the config says so loudly,
41
41
  // with the download consequence and the prefetch command, right where it was just written.
42
42
  if (provider === 'static') {
43
- console.log("embed model: ".concat(model, " (static); nothing downloads until the first vector search -- ").concat(ctx.name, " download fetches it now instead"));
43
+ console.log("embed model: ".concat(model, " (static); ").concat(ctx.name, " build, watch, or a vector search downloads it when needed -- ").concat(ctx.name, " download fetches it now instead"));
44
44
  } else {
45
- console.log("embed model: ".concat(model, " (").concat(provider).concat(url ? " at ".concat(url) : '', "); reached over the network at search time, nothing to download"));
45
+ console.log("embed model: ".concat(model, " (").concat(provider).concat(url ? " at ".concat(url) : '', "); build, watch, and vector queries use the network, nothing to download"));
46
46
  }
47
47
  console.log('a non-English tree should pick a model for its languages: see the sense-setup skill or INTEGRATIONS.md');
48
48
  // The decisions a new tree faces -- features, frontmatter conventions, note size -- are not
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/init.ts"],"sourcesContent":["import { DEFAULT_EMBED_MODEL, initConfig } from '../config/index.ts';\nimport { USAGE } from './index.ts';\nimport { parse } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst init: Command = (ctx) => {\n const { values } = parse(ctx.argv, `usage: ${ctx.name} ${USAGE.init}`, {\n model: { type: 'string' },\n provider: { type: 'string' },\n url: { type: 'string' },\n });\n const modelFlag = values.model as string | undefined;\n const providerFlag = values.provider as string | undefined;\n const model = modelFlag ?? DEFAULT_EMBED_MODEL;\n const provider = providerFlag ?? 'static';\n const url = values.url as string | undefined;\n // An invalid --provider throws here (validateConfig's own shape error), before anything is\n // written -- one validator, not a second copy of its rules.\n const configPath = initConfig(process.cwd(), { model: modelFlag, provider: providerFlag, url });\n console.log(`created ${configPath}`);\n console.log(`query away: ${ctx.name} sql \"SELECT path FROM frontmatter LIMIT 10\"`);\n // Naming a model is consent to fetch it, so writing one into the config says so loudly,\n // with the download consequence and the prefetch command, right where it was just written.\n if (provider === 'static') {\n console.log(`embed model: ${model} (static); nothing downloads until the first vector search -- ${ctx.name} download fetches it now instead`);\n } else {\n console.log(`embed model: ${model} (${provider}${url ? ` at ${url}` : ''}); reached over the network at search time, nothing to download`);\n }\n console.log('a non-English tree should pick a model for its languages: see the sense-setup skill or INTEGRATIONS.md');\n // The decisions a new tree faces -- features, frontmatter conventions, note size -- are not\n // in this output; name both places that hold them, since an agent may have neither.\n console.log('features and tree design: the sense-setup skill, or schema.json');\n};\nexport default init;\n"],"names":["init","ctx","values","parse","argv","USAGE","name","model","type","provider","url","modelFlag","providerFlag","DEFAULT_EMBED_MODEL","configPath","initConfig","process","cwd","console","log"],"mappings":";;;;+BAiCA;;;eAAA;;;uBAjCgD;wBAC1B;wBACA;AAGtB,IAAMA,OAAgB,cAACC;IACrB,IAAM,AAAEC,SAAWC,IAAAA,eAAK,EAACF,IAAIG,IAAI,EAAE,AAAC,UAAqBC,OAAZJ,IAAIK,IAAI,EAAC,KAAc,OAAXD,eAAK,CAACL,IAAI,GAAI;QACrEO,OAAO;YAAEC,MAAM;QAAS;QACxBC,UAAU;YAAED,MAAM;QAAS;QAC3BE,KAAK;YAAEF,MAAM;QAAS;IACxB,GAJQN;IAKR,IAAMS,YAAYT,OAAOK,KAAK;IAC9B,IAAMK,eAAeV,OAAOO,QAAQ;IACpC,IAAMF,QAAQI,sBAAAA,uBAAAA,YAAaE,4BAAmB;IAC9C,IAAMJ,WAAWG,yBAAAA,0BAAAA,eAAgB;IACjC,IAAMF,MAAMR,OAAOQ,GAAG;IACtB,2FAA2F;IAC3F,4DAA4D;IAC5D,IAAMI,aAAaC,IAAAA,mBAAU,EAACC,QAAQC,GAAG,IAAI;QAAEV,OAAOI;QAAWF,UAAUG;QAAcF,KAAAA;IAAI;IAC7FQ,QAAQC,GAAG,CAAC,AAAC,WAAqB,OAAXL;IACvBI,QAAQC,GAAG,CAAC,AAAC,eAAuB,OAATlB,IAAIK,IAAI,EAAC;IACpC,wFAAwF;IACxF,2FAA2F;IAC3F,IAAIG,aAAa,UAAU;QACzBS,QAAQC,GAAG,CAAC,AAAC,gBAAqFlB,OAAtEM,OAAM,kEAAyE,OAATN,IAAIK,IAAI,EAAC;IAC7G,OAAO;QACLY,QAAQC,GAAG,CAAC,AAAC,gBAAyBV,OAAVF,OAAM,MAAeG,OAAXD,UAAmC,OAAxBC,MAAM,AAAC,OAAU,OAAJA,OAAQ,IAAG;IAC3E;IACAQ,QAAQC,GAAG,CAAC;IACZ,4FAA4F;IAC5F,oFAAoF;IACpFD,QAAQC,GAAG,CAAC;AACd;IACA,WAAenB"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/init.ts"],"sourcesContent":["import { DEFAULT_EMBED_MODEL, initConfig } from '../config/index.ts';\nimport { USAGE } from './index.ts';\nimport { parse } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst init: Command = (ctx) => {\n const { values } = parse(ctx.argv, `usage: ${ctx.name} ${USAGE.init}`, {\n model: { type: 'string' },\n provider: { type: 'string' },\n url: { type: 'string' },\n });\n const modelFlag = values.model as string | undefined;\n const providerFlag = values.provider as string | undefined;\n const model = modelFlag ?? DEFAULT_EMBED_MODEL;\n const provider = providerFlag ?? 'static';\n const url = values.url as string | undefined;\n // An invalid --provider throws here (validateConfig's own shape error), before anything is\n // written -- one validator, not a second copy of its rules.\n const configPath = initConfig(process.cwd(), { model: modelFlag, provider: providerFlag, url });\n console.log(`created ${configPath}`);\n console.log(`query away: ${ctx.name} sql \"SELECT path FROM frontmatter LIMIT 10\"`);\n // Naming a model is consent to fetch it, so writing one into the config says so loudly,\n // with the download consequence and the prefetch command, right where it was just written.\n if (provider === 'static') {\n console.log(`embed model: ${model} (static); ${ctx.name} build, watch, or a vector search downloads it when needed -- ${ctx.name} download fetches it now instead`);\n } else {\n console.log(`embed model: ${model} (${provider}${url ? ` at ${url}` : ''}); build, watch, and vector queries use the network, nothing to download`);\n }\n console.log('a non-English tree should pick a model for its languages: see the sense-setup skill or INTEGRATIONS.md');\n // The decisions a new tree faces -- features, frontmatter conventions, note size -- are not\n // in this output; name both places that hold them, since an agent may have neither.\n console.log('features and tree design: the sense-setup skill, or schema.json');\n};\nexport default init;\n"],"names":["init","ctx","values","parse","argv","USAGE","name","model","type","provider","url","modelFlag","providerFlag","DEFAULT_EMBED_MODEL","configPath","initConfig","process","cwd","console","log"],"mappings":";;;;+BAiCA;;;eAAA;;;uBAjCgD;wBAC1B;wBACA;AAGtB,IAAMA,OAAgB,cAACC;IACrB,IAAM,AAAEC,SAAWC,IAAAA,eAAK,EAACF,IAAIG,IAAI,EAAE,AAAC,UAAqBC,OAAZJ,IAAIK,IAAI,EAAC,KAAc,OAAXD,eAAK,CAACL,IAAI,GAAI;QACrEO,OAAO;YAAEC,MAAM;QAAS;QACxBC,UAAU;YAAED,MAAM;QAAS;QAC3BE,KAAK;YAAEF,MAAM;QAAS;IACxB,GAJQN;IAKR,IAAMS,YAAYT,OAAOK,KAAK;IAC9B,IAAMK,eAAeV,OAAOO,QAAQ;IACpC,IAAMF,QAAQI,sBAAAA,uBAAAA,YAAaE,4BAAmB;IAC9C,IAAMJ,WAAWG,yBAAAA,0BAAAA,eAAgB;IACjC,IAAMF,MAAMR,OAAOQ,GAAG;IACtB,2FAA2F;IAC3F,4DAA4D;IAC5D,IAAMI,aAAaC,IAAAA,mBAAU,EAACC,QAAQC,GAAG,IAAI;QAAEV,OAAOI;QAAWF,UAAUG;QAAcF,KAAAA;IAAI;IAC7FQ,QAAQC,GAAG,CAAC,AAAC,WAAqB,OAAXL;IACvBI,QAAQC,GAAG,CAAC,AAAC,eAAuB,OAATlB,IAAIK,IAAI,EAAC;IACpC,wFAAwF;IACxF,2FAA2F;IAC3F,IAAIG,aAAa,UAAU;QACzBS,QAAQC,GAAG,CAAC,AAAC,gBAAkClB,OAAnBM,OAAM,eAAsFN,OAAzEA,IAAIK,IAAI,EAAC,kEAAyE,OAATL,IAAIK,IAAI,EAAC;IACnI,OAAO;QACLY,QAAQC,GAAG,CAAC,AAAC,gBAAyBV,OAAVF,OAAM,MAAeG,OAAXD,UAAmC,OAAxBC,MAAM,AAAC,OAAU,OAAJA,OAAQ,IAAG;IAC3E;IACAQ,QAAQC,GAAG,CAAC;IACZ,4FAA4F;IAC5F,oFAAoF;IACpFD,QAAQC,GAAG,CAAC;AACd;IACA,WAAenB"}
@@ -164,9 +164,14 @@ function _ts_generator(thisArg, body) {
164
164
  }
165
165
  }
166
166
  var map = function map(ctx) {
167
- var values = (0, _sharedts.parse)(ctx.argv, "usage: ".concat(ctx.name, " ").concat(_indexts.USAGE.map), _object_spread({}, _sharedts.SCOPE, _sharedts.FORMAT, _sharedts.CONFIG)).values;
167
+ var values = (0, _sharedts.parse)(ctx.argv, "usage: ".concat(ctx.name, " ").concat(_indexts.USAGE.map), _object_spread({}, _sharedts.SCOPE, _sharedts.NO_BUILD, _sharedts.FORMAT, _sharedts.CONFIG)).values;
168
168
  var format = (0, _sharedts.formatOf)(values);
169
- return (0, _sharedts.withDb)(ctx, values.config, function(store, cfg) {
169
+ return (0, _sharedts.withDb)(ctx, values.config, {
170
+ noBuild: values['no-build'] === true,
171
+ requirements: new Set([
172
+ 'core'
173
+ ])
174
+ }, function(store, cfg) {
170
175
  return _async_to_generator(function() {
171
176
  var result;
172
177
  return _ts_generator(this, function(_state) {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/map.ts"],"sourcesContent":["import { mapTree } from '../commands/map.ts';\nimport { renderMap, stringifyJson } from '../output/output.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, formatOf, parse, SCOPE, scopeOf, withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst map: Command = (ctx) => {\n const { values } = parse(ctx.argv, `usage: ${ctx.name} ${USAGE.map}`, { ...SCOPE, ...FORMAT, ...CONFIG });\n const format = formatOf(values);\n return withDb(ctx, values.config as string | undefined, async (store, cfg) => {\n const result = await mapTree(store, cfg, scopeOf(values));\n console.log(format === 'json' ? stringifyJson(result, 2) : renderMap(result));\n });\n};\nexport default map;\n"],"names":["map","ctx","values","parse","argv","USAGE","name","SCOPE","FORMAT","CONFIG","format","formatOf","withDb","config","store","cfg","result","mapTree","scopeOf","console","log","stringifyJson","renderMap"],"mappings":";;;;+BAcA;;;eAAA;;;qBAdwB;wBACiB;uBACnB;wBACkD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGxE,IAAMA,MAAe,aAACC;IACpB,IAAM,AAAEC,SAAWC,IAAAA,eAAK,EAACF,IAAIG,IAAI,EAAE,AAAC,UAAqBC,OAAZJ,IAAIK,IAAI,EAAC,KAAa,OAAVD,cAAK,CAACL,GAAG,GAAI,mBAAKO,eAAK,EAAKC,gBAAM,EAAKC,gBAAM,GAA9FP;IACR,IAAMQ,SAASC,IAAAA,kBAAQ,EAACT;IACxB,OAAOU,IAAAA,gBAAM,EAACX,KAAKC,OAAOW,MAAM,EAAwB,SAAOC,OAAOC;;gBAC9DC;;;;wBAAS;;4BAAMC,IAAAA,cAAO,EAACH,OAAOC,KAAKG,IAAAA,iBAAO,EAAChB;;;wBAA3Cc,SAAS;wBACfG,QAAQC,GAAG,CAACV,WAAW,SAASW,IAAAA,uBAAa,EAACL,QAAQ,KAAKM,IAAAA,mBAAS,EAACN;;;;;;QACvE;;AACF;IACA,WAAehB"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/map.ts"],"sourcesContent":["import { mapTree } from '../commands/map.ts';\nimport { renderMap, stringifyJson } from '../output/output.ts';\nimport type { BuildRequirement } from '../store/open.ts';\nimport { USAGE } from './index.ts';\nimport { CONFIG, FORMAT, formatOf, NO_BUILD, parse, SCOPE, scopeOf, withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst map: Command = (ctx) => {\n const { values } = parse(ctx.argv, `usage: ${ctx.name} ${USAGE.map}`, { ...SCOPE, ...NO_BUILD, ...FORMAT, ...CONFIG });\n const format = formatOf(values);\n return withDb(ctx, values.config as string | undefined, { noBuild: values['no-build'] === true, requirements: new Set<BuildRequirement>(['core']) }, async (store, cfg) => {\n const result = await mapTree(store, cfg, scopeOf(values));\n console.log(format === 'json' ? stringifyJson(result, 2) : renderMap(result));\n });\n};\nexport default map;\n"],"names":["map","ctx","values","parse","argv","USAGE","name","SCOPE","NO_BUILD","FORMAT","CONFIG","format","formatOf","withDb","config","noBuild","requirements","Set","store","cfg","result","mapTree","scopeOf","console","log","stringifyJson","renderMap"],"mappings":";;;;+BAeA;;;eAAA;;;qBAfwB;wBACiB;uBAEnB;wBAC4D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGlF,IAAMA,MAAe,aAACC;IACpB,IAAM,AAAEC,SAAWC,IAAAA,eAAK,EAACF,IAAIG,IAAI,EAAE,AAAC,UAAqBC,OAAZJ,IAAIK,IAAI,EAAC,KAAa,OAAVD,cAAK,CAACL,GAAG,GAAI,mBAAKO,eAAK,EAAKC,kBAAQ,EAAKC,gBAAM,EAAKC,gBAAM,GAA3GR;IACR,IAAMS,SAASC,IAAAA,kBAAQ,EAACV;IACxB,OAAOW,IAAAA,gBAAM,EAACZ,KAAKC,OAAOY,MAAM,EAAwB;QAAEC,SAASb,MAAM,CAAC,WAAW,KAAK;QAAMc,cAAc,IAAIC,IAAsB;YAAC;SAAO;IAAE,GAAG,SAAOC,OAAOC;;gBAC3JC;;;;wBAAS;;4BAAMC,IAAAA,cAAO,EAACH,OAAOC,KAAKG,IAAAA,iBAAO,EAACpB;;;wBAA3CkB,SAAS;wBACfG,QAAQC,GAAG,CAACb,WAAW,SAASc,IAAAA,uBAAa,EAACL,QAAQ,KAAKM,IAAAA,mBAAS,EAACN;;;;;;QACvE;;AACF;IACA,WAAepB"}