sensemaking 0.8.0 → 0.9.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 (102) hide show
  1. package/README.md +48 -39
  2. package/dist/cjs/cli/check.js +24 -43
  3. package/dist/cjs/cli/check.js.map +1 -1
  4. package/dist/cjs/cli/index.js +2 -2
  5. package/dist/cjs/cli/index.js.map +1 -1
  6. package/dist/cjs/cli/named.js +18 -8
  7. package/dist/cjs/cli/named.js.map +1 -1
  8. package/dist/cjs/cli/search.d.cts +3 -0
  9. package/dist/cjs/cli/search.d.ts +3 -0
  10. package/dist/cjs/cli/{find.js → search.js} +7 -5
  11. package/dist/cjs/cli/search.js.map +1 -0
  12. package/dist/cjs/cli/shared.js.map +1 -1
  13. package/dist/cjs/cli/status.js +29 -12
  14. package/dist/cjs/cli/status.js.map +1 -1
  15. package/dist/cjs/cli/types.d.cts +3 -1
  16. package/dist/cjs/cli/types.d.ts +3 -1
  17. package/dist/cjs/cli.js +25 -5
  18. package/dist/cjs/cli.js.map +1 -1
  19. package/dist/cjs/commands.d.cts +11 -2
  20. package/dist/cjs/commands.d.ts +11 -2
  21. package/dist/cjs/commands.js +86 -21
  22. package/dist/cjs/commands.js.map +1 -1
  23. package/dist/cjs/config.d.cts +41 -14
  24. package/dist/cjs/config.d.ts +41 -14
  25. package/dist/cjs/config.js +448 -160
  26. package/dist/cjs/config.js.map +1 -1
  27. package/dist/cjs/db.d.cts +1 -1
  28. package/dist/cjs/db.d.ts +1 -1
  29. package/dist/cjs/db.js +208 -62
  30. package/dist/cjs/db.js.map +1 -1
  31. package/dist/cjs/errors.d.cts +1 -1
  32. package/dist/cjs/errors.d.ts +1 -1
  33. package/dist/cjs/errors.js.map +1 -1
  34. package/dist/cjs/features/embed.js +12 -2
  35. package/dist/cjs/features/embed.js.map +1 -1
  36. package/dist/cjs/features/types.d.cts +2 -1
  37. package/dist/cjs/features/types.d.ts +2 -1
  38. package/dist/cjs/index.d.cts +3 -3
  39. package/dist/cjs/index.d.ts +3 -3
  40. package/dist/cjs/index.js +6 -3
  41. package/dist/cjs/index.js.map +1 -1
  42. package/dist/cjs/output.d.cts +15 -0
  43. package/dist/cjs/output.d.ts +15 -0
  44. package/dist/cjs/output.js +26 -5
  45. package/dist/cjs/output.js.map +1 -1
  46. package/dist/cjs/scan.d.cts +3 -0
  47. package/dist/cjs/scan.d.ts +3 -0
  48. package/dist/cjs/scan.js +84 -4
  49. package/dist/cjs/scan.js.map +1 -1
  50. package/dist/esm/cli/check.js +20 -41
  51. package/dist/esm/cli/check.js.map +1 -1
  52. package/dist/esm/cli/index.js +1 -1
  53. package/dist/esm/cli/index.js.map +1 -1
  54. package/dist/esm/cli/named.js +17 -9
  55. package/dist/esm/cli/named.js.map +1 -1
  56. package/dist/esm/cli/search.d.ts +3 -0
  57. package/dist/esm/cli/search.js +16 -0
  58. package/dist/esm/cli/search.js.map +1 -0
  59. package/dist/esm/cli/shared.js +1 -1
  60. package/dist/esm/cli/shared.js.map +1 -1
  61. package/dist/esm/cli/status.js +10 -10
  62. package/dist/esm/cli/status.js.map +1 -1
  63. package/dist/esm/cli/types.d.ts +3 -1
  64. package/dist/esm/cli/types.js.map +1 -1
  65. package/dist/esm/cli.js +20 -4
  66. package/dist/esm/cli.js.map +1 -1
  67. package/dist/esm/commands.d.ts +11 -2
  68. package/dist/esm/commands.js +76 -24
  69. package/dist/esm/commands.js.map +1 -1
  70. package/dist/esm/config.d.ts +41 -14
  71. package/dist/esm/config.js +354 -114
  72. package/dist/esm/config.js.map +1 -1
  73. package/dist/esm/db.d.ts +1 -1
  74. package/dist/esm/db.js +53 -6
  75. package/dist/esm/db.js.map +1 -1
  76. package/dist/esm/errors.d.ts +1 -1
  77. package/dist/esm/errors.js.map +1 -1
  78. package/dist/esm/features/embed.js +12 -2
  79. package/dist/esm/features/embed.js.map +1 -1
  80. package/dist/esm/features/types.d.ts +2 -1
  81. package/dist/esm/features/types.js.map +1 -1
  82. package/dist/esm/index.d.ts +3 -3
  83. package/dist/esm/index.js +1 -1
  84. package/dist/esm/index.js.map +1 -1
  85. package/dist/esm/output.d.ts +15 -0
  86. package/dist/esm/output.js +19 -5
  87. package/dist/esm/output.js.map +1 -1
  88. package/dist/esm/scan.d.ts +3 -0
  89. package/dist/esm/scan.js +32 -4
  90. package/dist/esm/scan.js.map +1 -1
  91. package/package.json +9 -3
  92. package/schema.json +74 -54
  93. package/skills/sense/EXAMPLES.md +8 -6
  94. package/skills/sense/SKILL.md +51 -48
  95. package/skills/sense-setup/EXAMPLES.md +121 -0
  96. package/skills/sense-setup/SKILL.md +71 -66
  97. package/dist/cjs/cli/find.d.cts +0 -3
  98. package/dist/cjs/cli/find.d.ts +0 -3
  99. package/dist/cjs/cli/find.js.map +0 -1
  100. package/dist/esm/cli/find.d.ts +0 -3
  101. package/dist/esm/cli/find.js +0 -14
  102. package/dist/esm/cli/find.js.map +0 -1
package/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # sensemaking
2
2
 
3
- SQL over a tree of markdown notes: filter by frontmatter, search the prose, follow the links,
4
- read the structure. A CLI that starts, answers, and exits — no server, no build step.
3
+ Query and search a tree of markdown notes: SQL over frontmatter and links, ranked search over
4
+ the prose — words, links, and meaning fused. A CLI that starts, answers, and exits — no
5
+ server, no build step.
5
6
 
6
7
  ## Problem
7
8
 
@@ -22,7 +23,7 @@ cd your-notes && sense init
22
23
 
23
24
  ```bash
24
25
  sense map # orient: fields, hub notes, recent changes
25
- sense find "revenue OR earnings" --k 10 # locate: ranked references with excerpts
26
+ sense search "revenue OR earnings" --k 10 # locate: words + links + meaning, one ranked list
26
27
  sense peek notes/q3-report.md # structure: outline + links, before reading
27
28
  sense query "SELECT path FROM frontmatter WHERE has(tags, ?)" urgent
28
29
  ```
@@ -60,62 +61,65 @@ ORDER BY bm25(content, 10.0, 5.0, 1.0) LIMIT 10
60
61
  | command | does |
61
62
  |---|---|
62
63
  | `map` | doc count, frontmatter field coverage, top hubs by link rank, recent changes |
63
- | `find "<terms>" [--where "<sql>"] [--k n] [--semantic]` | BM25 + link-graph expansion, fused; `via` marks each row `match`, `link`, or `match+link` |
64
+ | `search "<text>" [--preset name] [--include glob] [--where "<sql>"] [--k n] [--lexical]` | words + links + vectors, one fused ranked list; `via` labels each row's evidence |
64
65
  | `peek <path>` | frontmatter + heading outline (`[L143-162, ~380t]`) + links both ways — first 20 per list, each with its total; the `links` table has the rest |
65
66
  | `query "<sql>" [params...]` | ad-hoc SQL over all the tables; `?` binds positional args |
66
67
  | `<name> [params...]` | run a query saved in the config; `--list` names them |
67
68
  | `init` | write a starter `sense.config.json` |
68
- | `status` | index location, doc count, feature state, watcher heartbeat |
69
- | `check` | prepare and run the saved queries, so a broken one fails here instead of mid-task |
69
+ | `status` | index location, doc count, per-preset coverage, watcher heartbeat |
70
+ | `check` | run every saved query and search, so a broken one fails here instead of mid-task |
70
71
  | `rebuild` | delete the cache and re-crawl |
71
72
  | `watch` | keep the index warm in the background (optional; see [WATCH.md](WATCH.md)) |
72
73
 
73
- `find` seeds a personalized-PageRank walk with the BM25 matches, so a note that never contains
74
- the terms but is linked from ones that do still surfaces. Terms pass verbatim to FTS5 `MATCH`
75
- (bare words AND-join; operators are yours to write). `--where` takes any SQL condition against
76
- frontmatter alias `f`. On trees with the `embed` feature, `--semantic` additionally expands by
77
- meaning explicit per query, never silent; rows it adds are labeled `via: vector` and carry
78
- `similarity` (cosine against the best-matching chunk). A `lines` column points at the section
79
- that earned a row a direct read range. `--format json` on any command returns structured
80
- output; `--version` and `--help` do what they say.
74
+ `search` runs one text through every engine its scope has FTS5 word match (BM25-ranked,
75
+ bare words AND-join, operators are yours), a personalized-PageRank walk over the link graph,
76
+ and vector similarity fused into one list. `via` labels each row's evidence (`match`,
77
+ `link`, `vector`, combinations); `similarity` is the cosine against the best-matching chunk;
78
+ `lines` points at the section that earned the row a direct read range. Rows that only
79
+ vectors produced are the "these words aren't in the tree, this is what's near in meaning"
80
+ signal. `--preset` picks a named settings bundle from the config, `--lexical` skips vectors
81
+ for one command, `--where` filters on frontmatter. `--format json` on any command returns
82
+ structured output; `--version` and `--help` do what they say.
81
83
 
82
84
  ## Config
83
85
 
84
86
  `sense init` writes `sense.config.json`; discovery walks up from cwd like git
85
- (`--config <path>` overrides). Name reusable queries and run them as `sense <name> [params...]`:
87
+ (`--config <path>` overrides). Three keys: **presets** (named, self-contained setting
88
+ bundles), **queries** (saved commands), and the version.
86
89
 
87
90
  ```json
88
91
  {
89
92
  "$schema": "https://unpkg.com/sensemaking/schema.json",
90
- "version": 2,
91
- "scan": { "include": ["**/*.md"] },
92
- "features": { "links": true, "sections": true, "rank": true },
93
- "defaults": { "find": { "where": "f.type != 'generated'" } },
93
+ "version": 3,
94
+ "presets": {
95
+ "default": { "include": ["**/*.md"], "k": 10 },
96
+ "raw": { "include": ["raw/**/*.md"], "k": 5, "semantic": false }
97
+ },
94
98
  "queries": {
95
99
  "dead-links": "SELECT src, target FROM links WHERE dst IS NULL",
96
100
  "by-tag": "SELECT path, title FROM frontmatter WHERE has(tags, ?) ORDER BY path",
97
- "hot": { "find": "pricing OR billing", "k": 20 }
98
- },
99
- "checks": { "dead-links": "empty" }
101
+ "hot": { "search": "pricing OR billing", "preset": "raw" }
102
+ }
100
103
  }
101
104
  ```
102
105
 
103
- A query entry is a SQL string, or a saved `find` with its settings baked in — `sense hot`
104
- then needs no flags. `defaults.find.where` scopes `find` tree-wide (an explicit `--where`
105
- replaces it, so `--where "1=1"` always reaches everything). `checks` turns a saved query
106
- into an assertion: `sense check` fails when a query marked `empty` returns rows. Every key
107
- is documented in [schema.json](schema.json), which editors read for autocomplete.
106
+ A preset bundles `include`/`exclude` globs (which files), `k` (result count), `semantic`
107
+ (vectors, on unless `false`), and `where` (a standing SQL filter). Bare commands use
108
+ `default`; `--preset` names another; flags override single fields. **Indexing derives from
109
+ the presets**: a file is indexed if any preset includes it, and embedded if any covering
110
+ preset has semantic on so a `semantic: false` preset's files cost no vectors, and
111
+ `status` shows each preset's coverage. Editing a preset rebuilds the cache and says which
112
+ preset caused it.
108
113
 
109
- Features toggle independently; disabling one degrades its command instead of failing it (`find`
110
- goes BM25-only without `links`, `map` drops hubs without `rank`, `peek` drops the outline
111
- without `sections`). Toggling rebuilds the cache. Older config versions auto-migrate on load,
112
- noted on stderr.
114
+ A query entry is a SQL string (`?` binds positional args) or a saved search with its
115
+ settings baked in `sense hot` needs no flags. `sense check` runs them all, so a typo'd
116
+ column fails at check time instead of mid-task. Older config versions auto-migrate on
117
+ load, noted on stderr.
113
118
 
114
- `embed` is opt-in the only feature off by default, since most trees don't need vectors.
115
- `"embed": true` uses the built-in static model (downloaded to `~/.cache/sensemaking` on first
116
- use, never in the package), or `{ "model", "type": "static"|"api", "url", "key" }` points at any Model2Vec model,
117
- local path, or OpenAI-compatible endpoint (Ollama, LM Studio, hosted). With it on, vectors stay
118
- fresh at reconcile and `find --semantic` uses them; default `find` results are unchanged.
119
+ Vectors use the built-in static model (downloaded to `~/.cache/sensemaking` on first use,
120
+ never in the package); an optional top-level `"embed": { "model", "type", "url", "key" }`
121
+ block points at any Model2Vec model, local path, or OpenAI-compatible endpoint (Ollama,
122
+ LM Studio, hosted). Embedding happens on the first semantic search, with progress.
119
123
 
120
124
  `has(field, value)` is the one custom SQL function: array membership on JSON-array fields,
121
125
  substring on strings, false on missing keys. Frontmatter parsing is lenient — syntax errors are
@@ -159,6 +163,10 @@ features, frontmatter conventions, and note size are decisions with consequences
159
163
  agent-maintained wiki navigated by an `index.md` and links, which he notes needs real search
160
164
  infrastructure past a few hundred pages. `sense map` derives that index from the notes instead of
161
165
  maintaining it; `find` is the hybrid local search it calls for.
166
+ - Agent memory patterns — llm-wiki's raw/wiki split, Claude Code's dreaming-style nightly
167
+ consolidation — are trees of small notes with metadata, links, and layers of differing
168
+ authority. sense is the query layer such patterns need (filter by metadata and age, scope
169
+ by layer, surface near-duplicates semantically), not an implementation of any one of them.
162
170
 
163
171
  ## Alternatives
164
172
 
@@ -166,9 +174,10 @@ features, frontmatter conventions, and note size are decisions with consequences
166
174
  query it headless.
167
175
  - **Index-on-build tools (MarkdownDB)** — query a snapshot; `sense` reconciles on every query.
168
176
  - **Note CLIs (zk)** — fixed schema; `sense` filters on arbitrary frontmatter.
169
- - **RAG / vector stores** — similarity can't express `WHERE status = 'active'`. Here vectors are
170
- the optional `embed` feature: same SQLite file, filters compose, expansion is explicit per
171
- query (`find --semantic`) and labeled no second store, no daemon, no native builds.
177
+ - **RAG / vector stores** — similarity can't express `WHERE status = 'active'`. Here vectors
178
+ are one signal inside `search`: same SQLite file, filters compose, every row labels its
179
+ evidence (`via`), and a preset turns vectors off per layer of the tree — no second store,
180
+ no daemon, no native builds.
172
181
 
173
182
  Dependencies: [yaml](https://github.com/eemeli/yaml),
174
183
  [remove-markdown](https://github.com/zuchka/remove-markdown),
@@ -9,7 +9,6 @@ Object.defineProperty(exports, "default", {
9
9
  }
10
10
  });
11
11
  var _commandsts = require("../commands.js");
12
- var _configts = require("../config.js");
13
12
  var _dbts = require("../db.js");
14
13
  var _outputts = require("../output.js");
15
14
  var _sharedts = require("./shared.js");
@@ -80,6 +79,10 @@ function _non_iterable_rest() {
80
79
  function _sliced_to_array(arr, i) {
81
80
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
82
81
  }
82
+ function _type_of(obj) {
83
+ "@swc/helpers - typeof";
84
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
85
+ }
83
86
  function _unsupported_iterable_to_array(o, minLen) {
84
87
  if (!o) return;
85
88
  if (typeof o === "string") return _array_like_to_array(o, minLen);
@@ -192,14 +195,14 @@ function _ts_generator(thisArg, body) {
192
195
  // column reading as "nothing tagged yet" for hours. Preparing each query catches syntax and
193
196
  // unknown-column errors without executing it; queries that take no parameters are also run
194
197
  // for a row count. Parameterised queries are validated but not counted: inventing arguments
195
- // would report a count for a query nobody ran. Saved finds run lexically with k=1 -- that
196
- // validates the `where` fragment and the FTS5 terms against the real schema, the same
197
- // breakage class prepare() catches for SQL strings -- but never semantically (a --semantic
198
- // pass costs model time and, on api trees, network); `semantic: true` is only checked for
199
- // a features.embed to run against.
198
+ // would report a count for a query nobody ran. Saved searches run lexically with k=1 -- that
199
+ // validates the `where` fragment, the FTS5 terms, and the `preset` name (resolveSearch throws
200
+ // on an unknown one, the same breakage class prepare() catches for SQL strings) -- but never
201
+ // semantically (a semantic pass costs model time and, on api trees, network). Whether a
202
+ // result being empty is good or bad is the reader's judgment -- there is no assertion path.
200
203
  var check = function check(ctx) {
201
204
  return _async_to_generator(function() {
202
- var _cfg_queries, cfg, _open, db, warnings, rows, failed, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step_value, name, entry, _sql_match, _cfg_checks, count, err, sql, params, expectEmpty, statement, count1, err1;
205
+ var _cfg_queries, cfg, _open, db, warnings, rows, failed, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, _step_value, name, entry, _sql_match, count, err, sql, params, statement, count1, err1;
203
206
  return _ts_generator(this, function(_state) {
204
207
  switch(_state.label){
205
208
  case 0:
@@ -225,23 +228,10 @@ var check = function check(ctx) {
225
228
  9
226
229
  ];
227
230
  _step_value = _sliced_to_array(_step.value, 2), name = _step_value[0], entry = _step_value[1];
228
- if (!(typeof entry !== 'string')) return [
231
+ if (!((typeof entry === "undefined" ? "undefined" : _type_of(entry)) === 'object' && entry !== null && 'search' in entry)) return [
229
232
  3,
230
233
  7
231
234
  ];
232
- if (entry.semantic && !(0, _configts.featureEnabled)(cfg, 'embed')) {
233
- failed++;
234
- rows.push({
235
- query: name,
236
- params: '—',
237
- rows: '—',
238
- status: 'FAILED: semantic requested but features.embed is off'
239
- });
240
- return [
241
- 3,
242
- 8
243
- ];
244
- }
245
235
  _state.label = 3;
246
236
  case 3:
247
237
  _state.trys.push([
@@ -252,9 +242,12 @@ var check = function check(ctx) {
252
242
  ]);
253
243
  return [
254
244
  4,
255
- (0, _commandsts.find)(db, cfg, entry.find, {
245
+ (0, _commandsts.search)(db, cfg, entry.search, {
256
246
  k: 1,
257
- where: entry.where
247
+ where: entry.where,
248
+ preset: entry.preset,
249
+ include: entry.include,
250
+ semantic: false
258
251
  })
259
252
  ];
260
253
  case 4:
@@ -263,7 +256,7 @@ var check = function check(ctx) {
263
256
  query: name,
264
257
  params: '—',
265
258
  rows: '—',
266
- status: count === 0 ? 'ok, but matches 0 notes (lexical probe)' : entry.semantic ? 'ok (lexical probe; semantic not run)' : 'ok (probe run with k=1)'
259
+ status: count === 0 ? 'ok, but matches 0 notes (lexical probe)' : 'ok (probe run with k=1)'
267
260
  });
268
261
  return [
269
262
  3,
@@ -288,9 +281,8 @@ var check = function check(ctx) {
288
281
  8
289
282
  ];
290
283
  case 7:
291
- sql = entry;
284
+ sql = typeof entry === 'string' ? entry : entry.sql;
292
285
  params = ((_sql_match = sql.match(/\?/g)) !== null && _sql_match !== void 0 ? _sql_match : []).length;
293
- expectEmpty = ((_cfg_checks = cfg.checks) === null || _cfg_checks === void 0 ? void 0 : _cfg_checks[name]) === 'empty';
294
286
  try {
295
287
  statement = db.prepare(sql);
296
288
  if (params > 0) {
@@ -306,23 +298,12 @@ var check = function check(ctx) {
306
298
  ];
307
299
  }
308
300
  count1 = statement.all().length;
309
- if (expectEmpty) {
310
- // An invariant query: rows are violations, so 0 is the pass, anything else fails.
311
- if (count1 > 0) failed++;
312
- rows.push({
313
- query: name,
314
- params: params,
315
- rows: count1,
316
- status: count1 === 0 ? 'ok (empty, as asserted)' : "FAILED: expected empty, returned ".concat(count1, " row(s)")
317
- });
318
- } else {
319
- rows.push({
320
- query: name,
321
- params: params,
322
- rows: count1,
323
- status: count1 === 0 ? 'ok, but returns 0 rows' : 'ok'
324
- });
325
- }
301
+ rows.push({
302
+ query: name,
303
+ params: params,
304
+ rows: count1,
305
+ status: count1 === 0 ? 'ok, but returns 0 rows' : 'ok'
306
+ });
326
307
  } catch (err) {
327
308
  failed++;
328
309
  rows.push({
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/check.ts"],"sourcesContent":["import { find } from '../commands.ts';\nimport { featureEnabled } from '../config.ts';\nimport { open } from '../db.ts';\nimport type { Row } from '../output.ts';\nimport { printRows } from '../output.ts';\nimport { printWarnings } from './shared.ts';\nimport type { Command } from './types.ts';\n\n// A saved query that returns zero rows looks identical to a true empty result, so a broken\n// one can sit unnoticed -- one field report had `WHERE flag = 'true'` against a numeric\n// column reading as \"nothing tagged yet\" for hours. Preparing each query catches syntax and\n// unknown-column errors without executing it; queries that take no parameters are also run\n// for a row count. Parameterised queries are validated but not counted: inventing arguments\n// would report a count for a query nobody ran. Saved finds run lexically with k=1 -- that\n// validates the `where` fragment and the FTS5 terms against the real schema, the same\n// breakage class prepare() catches for SQL strings -- but never semantically (a --semantic\n// pass costs model time and, on api trees, network); `semantic: true` is only checked for\n// a features.embed to run against.\nconst check: Command = async (ctx) => {\n const cfg = ctx.resolveConfig();\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n\n const rows: Row[] = [];\n let failed = 0;\n for (const [name, entry] of Object.entries(cfg.queries ?? {})) {\n if (typeof entry !== 'string') {\n if (entry.semantic && !featureEnabled(cfg, 'embed')) {\n failed++;\n rows.push({ query: name, params: '', rows: '—', status: 'FAILED: semantic requested but features.embed is off' });\n continue;\n }\n try {\n const count = (await find(db, cfg, entry.find, { k: 1, where: entry.where })).length;\n rows.push({ query: name, params: '—', rows: '—', status: count === 0 ? 'ok, but matches 0 notes (lexical probe)' : entry.semantic ? 'ok (lexical probe; semantic not run)' : 'ok (probe run with k=1)' });\n } catch (err) {\n failed++;\n rows.push({ query: name, params: '—', rows: '—', status: `FAILED: ${(err as Error).message}` });\n }\n continue;\n }\n const sql = entry;\n const params = (sql.match(/\\?/g) ?? []).length;\n const expectEmpty = cfg.checks?.[name] === 'empty';\n try {\n const statement = db.prepare(sql);\n if (params > 0) {\n rows.push({ query: name, params, rows: '—', status: 'ok (not run: needs parameters)' });\n continue;\n }\n const count = (statement.all() as unknown[]).length;\n if (expectEmpty) {\n // An invariant query: rows are violations, so 0 is the pass, anything else fails.\n if (count > 0) failed++;\n rows.push({ query: name, params, rows: count, status: count === 0 ? 'ok (empty, as asserted)' : `FAILED: expected empty, returned ${count} row(s)` });\n } else {\n rows.push({ query: name, params, rows: count, status: count === 0 ? 'ok, but returns 0 rows' : 'ok' });\n }\n } catch (err) {\n failed++;\n rows.push({ query: name, params, rows: '—', status: `FAILED: ${(err as Error).message}` });\n }\n }\n\n db.close();\n if (rows.length === 0) {\n console.log('no saved queries in config');\n return;\n }\n printRows(rows, ctx.format);\n if (failed > 0) process.exit(1);\n};\nexport default check;\n"],"names":["check","ctx","cfg","open","db","warnings","rows","failed","name","entry","sql","count","err","params","expectEmpty","statement","resolveConfig","printWarnings","Object","entries","queries","semantic","featureEnabled","push","query","status","find","k","where","length","message","match","checks","prepare","all","close","console","log","printRows","format","process","exit"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/check.ts"],"sourcesContent":["import { search } from '../commands.ts';\nimport { open } from '../db.ts';\nimport type { Row } from '../output.ts';\nimport { printRows } from '../output.ts';\nimport { printWarnings } from './shared.ts';\nimport type { Command } from './types.ts';\n\n// A saved query that returns zero rows looks identical to a true empty result, so a broken\n// one can sit unnoticed -- one field report had `WHERE flag = 'true'` against a numeric\n// column reading as \"nothing tagged yet\" for hours. Preparing each query catches syntax and\n// unknown-column errors without executing it; queries that take no parameters are also run\n// for a row count. Parameterised queries are validated but not counted: inventing arguments\n// would report a count for a query nobody ran. Saved searches run lexically with k=1 -- that\n// validates the `where` fragment, the FTS5 terms, and the `preset` name (resolveSearch throws\n// on an unknown one, the same breakage class prepare() catches for SQL strings) -- but never\n// semantically (a semantic pass costs model time and, on api trees, network). Whether a\n// result being empty is good or bad is the reader's judgment -- there is no assertion path.\nconst check: Command = async (ctx) => {\n const cfg = ctx.resolveConfig();\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n\n const rows: Row[] = [];\n let failed = 0;\n for (const [name, entry] of Object.entries(cfg.queries ?? {})) {\n if (typeof entry === 'object' && entry !== null && 'search' in entry) {\n try {\n const count = (await search(db, cfg, entry.search, { k: 1, where: entry.where, preset: entry.preset, include: entry.include, semantic: false })).length;\n rows.push({ query: name, params: '—', rows: '—', status: count === 0 ? 'ok, but matches 0 notes (lexical probe)' : 'ok (probe run with k=1)' });\n } catch (err) {\n failed++;\n rows.push({ query: name, params: '—', rows: '—', status: `FAILED: ${(err as Error).message}` });\n }\n continue;\n }\n const sql = typeof entry === 'string' ? entry : entry.sql;\n const params = (sql.match(/\\?/g) ?? []).length;\n try {\n const statement = db.prepare(sql);\n if (params > 0) {\n rows.push({ query: name, params, rows: '—', status: 'ok (not run: needs parameters)' });\n continue;\n }\n const count = (statement.all() as unknown[]).length;\n rows.push({ query: name, params, rows: count, status: count === 0 ? 'ok, but returns 0 rows' : 'ok' });\n } catch (err) {\n failed++;\n rows.push({ query: name, params, rows: '—', status: `FAILED: ${(err as Error).message}` });\n }\n }\n\n db.close();\n if (rows.length === 0) {\n console.log('no saved queries in config');\n return;\n }\n printRows(rows, ctx.format);\n if (failed > 0) process.exit(1);\n};\nexport default check;\n"],"names":["check","ctx","cfg","open","db","warnings","rows","failed","name","entry","sql","count","err","params","statement","resolveConfig","printWarnings","Object","entries","queries","search","k","where","preset","include","semantic","length","push","query","status","message","match","prepare","all","close","console","log","printRows","format","process","exit"],"mappings":"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"}
@@ -80,9 +80,9 @@ var COMMANDS = {
80
80
  return /*#__PURE__*/ _interop_require_wildcard(require("./query.js"));
81
81
  });
82
82
  },
83
- find: function find() {
83
+ search: function search() {
84
84
  return Promise.resolve().then(function() {
85
- return /*#__PURE__*/ _interop_require_wildcard(require("./find.js"));
85
+ return /*#__PURE__*/ _interop_require_wildcard(require("./search.js"));
86
86
  });
87
87
  },
88
88
  map: function map() {
@@ -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// 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: a named\n// query in config can never shadow them.\nexport const COMMANDS: Record<string, () => Promise<{ default: Command }>> = {\n init: () => import('./init.ts'),\n watch: () => import('./watch.ts'),\n status: () => import('./status.ts'),\n check: () => import('./check.ts'),\n rebuild: () => import('./rebuild.ts'),\n query: () => import('./query.ts'),\n find: () => import('./find.ts'),\n map: () => import('./map.ts'),\n peek: () => import('./peek.ts'),\n};\n\nexport type { Command, Ctx } from './types.ts';\n"],"names":["COMMANDS","init","watch","status","check","rebuild","query","find","map","peek"],"mappings":";;;;+BAKaA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAN,IAAMA,WAAgE;IAC3EC,MAAM,SAANA;eAAY;2DAAA,QAAO;;;IACnBC,OAAO,SAAPA;eAAa;2DAAA,QAAO;;;IACpBC,QAAQ,SAARA;eAAc;2DAAA,QAAO;;;IACrBC,OAAO,SAAPA;eAAa;2DAAA,QAAO;;;IACpBC,SAAS,SAATA;eAAe;2DAAA,QAAO;;;IACtBC,OAAO,SAAPA;eAAa;2DAAA,QAAO;;;IACpBC,MAAM,SAANA;eAAY;2DAAA,QAAO;;;IACnBC,KAAK,SAALA;eAAW;2DAAA,QAAO;;;IAClBC,MAAM,SAANA;eAAY;2DAAA,QAAO;;;AACrB"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/index.ts"],"sourcesContent":["import type { Command } from './types.ts';\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: a named\n// query in config can never shadow them.\nexport const COMMANDS: Record<string, () => Promise<{ default: Command }>> = {\n init: () => import('./init.ts'),\n watch: () => import('./watch.ts'),\n status: () => import('./status.ts'),\n check: () => import('./check.ts'),\n rebuild: () => import('./rebuild.ts'),\n query: () => import('./query.ts'),\n search: () => import('./search.ts'),\n map: () => import('./map.ts'),\n peek: () => import('./peek.ts'),\n};\n\nexport type { Command, Ctx } from './types.ts';\n"],"names":["COMMANDS","init","watch","status","check","rebuild","query","search","map","peek"],"mappings":";;;;+BAKaA;;;eAAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAN,IAAMA,WAAgE;IAC3EC,MAAM,SAANA;eAAY;2DAAA,QAAO;;;IACnBC,OAAO,SAAPA;eAAa;2DAAA,QAAO;;;IACpBC,QAAQ,SAARA;eAAc;2DAAA,QAAO;;;IACrBC,OAAO,SAAPA;eAAa;2DAAA,QAAO;;;IACpBC,SAAS,SAATA;eAAe;2DAAA,QAAO;;;IACtBC,OAAO,SAAPA;eAAa;2DAAA,QAAO;;;IACpBC,QAAQ,SAARA;eAAc;2DAAA,QAAO;;;IACrBC,KAAK,SAALA;eAAW;2DAAA,QAAO;;;IAClBC,MAAM,SAANA;eAAY;2DAAA,QAAO;;;AACrB"}
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
5
  Object.defineProperty(exports, // Fallback when the first positional is not a command: a named query from config, either a
6
- // SQL string (run as-is) or a saved find (run through the `find` command's own machinery).
6
+ // SQL string (run as-is) or a saved search (run through the `search` command's own machinery).
7
7
  "default", {
8
8
  enumerable: true,
9
9
  get: function() {
@@ -143,7 +143,7 @@ function _ts_generator(thisArg, body) {
143
143
  }
144
144
  function named(ctx, queryName, params) {
145
145
  return _async_to_generator(function() {
146
- var _parseK, _ctx_values_where, cfg, entry, k, where, semantic;
146
+ var _parseK, _ctx_values_where, _ctx_values_preset, _ctx_values_include, cfg, entry, k, where, preset, include, semantic;
147
147
  return _ts_generator(this, function(_state) {
148
148
  switch(_state.label){
149
149
  case 0:
@@ -160,15 +160,23 @@ function named(ctx, queryName, params) {
160
160
  2
161
161
  ];
162
162
  }
163
- // A saved find's terms are fixed in config; there is nowhere for a positional to bind.
163
+ if ('sql' in entry) {
164
+ (0, _sharedts.runSql)(cfg, entry.sql, params, ctx.format, 'query "'.concat(queryName, '"'));
165
+ return [
166
+ 2
167
+ ];
168
+ }
169
+ // A saved search's text is fixed in config; there is nowhere for a positional to bind.
164
170
  if (params.length > 0) {
165
- ctx.usageError('"'.concat(queryName, '" is a saved find and takes no positional parameters; edit its "find" in sense.config.json, or use "').concat(ctx.name, ' find" directly'));
171
+ ctx.usageError('"'.concat(queryName, '" is a saved search and takes no positional parameters; edit its "search" in sense.config.json, or use "').concat(ctx.name, ' search" directly'));
166
172
  }
167
173
  k = (_parseK = (0, _sharedts.parseK)(ctx)) !== null && _parseK !== void 0 ? _parseK : entry.k;
168
174
  where = (_ctx_values_where = ctx.values.where) !== null && _ctx_values_where !== void 0 ? _ctx_values_where : entry.where;
169
- // --semantic upgrades a saved find the same way --where/--k override; absent means the
170
- // saved value (the flag has no default, so absent is distinguishable from false).
171
- semantic = ctx.values.semantic === true || entry.semantic;
175
+ preset = (_ctx_values_preset = ctx.values.preset) !== null && _ctx_values_preset !== void 0 ? _ctx_values_preset : entry.preset;
176
+ include = (_ctx_values_include = ctx.values.include) !== null && _ctx_values_include !== void 0 ? _ctx_values_include : entry.include;
177
+ // --lexical upgrades a saved search's semantic behavior the same way --where/--k
178
+ // override; absent means the saved value (the flag has no default false override).
179
+ semantic = ctx.values.lexical ? false : entry.semantic;
172
180
  return [
173
181
  4,
174
182
  (0, _sharedts.withDb)(ctx, function(db, resolvedCfg) {
@@ -178,9 +186,11 @@ function named(ctx, queryName, params) {
178
186
  case 0:
179
187
  return [
180
188
  4,
181
- (0, _commandsts.find)(db, resolvedCfg, entry.find, {
189
+ (0, _commandsts.search)(db, resolvedCfg, entry.search, {
182
190
  k: k,
183
191
  where: where,
192
+ preset: preset,
193
+ include: include,
184
194
  semantic: semantic
185
195
  })
186
196
  ];
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/named.ts"],"sourcesContent":["import { find } from '../commands.ts';\nimport { printRows } from '../output.ts';\nimport { parseK, runSql, withDb } from './shared.ts';\nimport type { Ctx } from './types.ts';\n\n// Fallback when the first positional is not a command: a named query from config, either a\n// SQL string (run as-is) or a saved find (run through the `find` command's own machinery).\nexport default async function named(ctx: Ctx, queryName: string, params: string[]): Promise<void> {\n const cfg = ctx.resolveConfig();\n const entry = cfg.queries[queryName];\n if (entry === undefined) {\n console.error(`unknown query: \"${queryName}\"`);\n console.error(`valid queries: ${Object.keys(cfg.queries).sort().join(', ')}`);\n process.exit(2);\n }\n\n if (typeof entry === 'string') {\n runSql(cfg, entry, params, ctx.format, `query \"${queryName}\"`);\n return;\n }\n\n // A saved find's terms are fixed in config; there is nowhere for a positional to bind.\n if (params.length > 0) {\n ctx.usageError(`\"${queryName}\" is a saved find and takes no positional parameters; edit its \"find\" in sense.config.json, or use \"${ctx.name} find\" directly`);\n }\n const k = parseK(ctx) ?? entry.k;\n const where = ctx.values.where ?? entry.where;\n // --semantic upgrades a saved find the same way --where/--k override; absent means the\n // saved value (the flag has no default, so absent is distinguishable from false).\n const semantic = ctx.values.semantic === true || entry.semantic;\n await withDb(ctx, async (db, resolvedCfg) => printRows(await find(db, resolvedCfg, entry.find, { k, where, semantic }), ctx.format));\n}\n"],"names":["named","ctx","queryName","params","parseK","cfg","entry","k","where","semantic","resolveConfig","queries","undefined","console","error","Object","keys","sort","join","process","exit","runSql","format","length","usageError","name","values","withDb","db","resolvedCfg","find","printRows"],"mappings":";;;;+BAKA,2FAA2F;AAC3F,2FAA2F;AAC3F;;;eAA8BA;;;0BAPT;wBACK;wBACa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKxB,SAAeA,MAAMC,GAAQ,EAAEC,SAAiB,EAAEC,MAAgB;;YAkBrEC,SACIH,mBAlBRI,KACAC,OAgBAC,GACAC,OAGAC;;;;oBArBAJ,MAAMJ,IAAIS,aAAa;oBACvBJ,QAAQD,IAAIM,OAAO,CAACT,UAAU;oBACpC,IAAII,UAAUM,WAAW;wBACvBC,QAAQC,KAAK,CAAC,AAAC,mBAA4B,OAAVZ,WAAU;wBAC3CW,QAAQC,KAAK,CAAC,AAAC,kBAA4D,OAA3CC,OAAOC,IAAI,CAACX,IAAIM,OAAO,EAAEM,IAAI,GAAGC,IAAI,CAAC;wBACrEC,QAAQC,IAAI,CAAC;oBACf;oBAEA,IAAI,OAAOd,UAAU,UAAU;wBAC7Be,IAAAA,gBAAM,EAAChB,KAAKC,OAAOH,QAAQF,IAAIqB,MAAM,EAAE,AAAC,UAAmB,OAAVpB,WAAU;wBAC3D;;;oBACF;oBAEA,uFAAuF;oBACvF,IAAIC,OAAOoB,MAAM,GAAG,GAAG;wBACrBtB,IAAIuB,UAAU,CAAC,AAAC,IAAmHvB,OAAhHC,WAAU,wGAA+G,OAATD,IAAIwB,IAAI,EAAC;oBAC9I;oBACMlB,KAAIH,UAAAA,IAAAA,gBAAM,EAACH,kBAAPG,qBAAAA,UAAeE,MAAMC,CAAC;oBAC1BC,SAAQP,oBAAAA,IAAIyB,MAAM,CAAClB,KAAK,cAAhBP,+BAAAA,oBAAoBK,MAAME,KAAK;oBAC7C,uFAAuF;oBACvF,kFAAkF;oBAC5EC,WAAWR,IAAIyB,MAAM,CAACjB,QAAQ,KAAK,QAAQH,MAAMG,QAAQ;oBAC/D;;wBAAMkB,IAAAA,gBAAM,EAAC1B,KAAK,SAAO2B,IAAIC;;;;;4CAA0B;;gDAAMC,IAAAA,gBAAI,EAACF,IAAIC,aAAavB,MAAMwB,IAAI,EAAE;oDAAEvB,GAAAA;oDAAGC,OAAAA;oDAAOC,UAAAA;gDAAS;;;;;gDAAvEsB,mBAAS;oDAAC;oDAAiE9B,IAAIqB,MAAM;;;;;;;;;oBAAlI;;;;;;IACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/named.ts"],"sourcesContent":["import { search } from '../commands.ts';\nimport { printRows } from '../output.ts';\nimport { parseK, runSql, withDb } from './shared.ts';\nimport type { Ctx } from './types.ts';\n\n// Fallback when the first positional is not a command: a named query from config, either a\n// SQL string (run as-is) or a saved search (run through the `search` command's own machinery).\nexport default async function named(ctx: Ctx, queryName: string, params: string[]): Promise<void> {\n const cfg = ctx.resolveConfig();\n const entry = cfg.queries[queryName];\n if (entry === undefined) {\n console.error(`unknown query: \"${queryName}\"`);\n console.error(`valid queries: ${Object.keys(cfg.queries).sort().join(', ')}`);\n process.exit(2);\n }\n\n if (typeof entry === 'string') {\n runSql(cfg, entry, params, ctx.format, `query \"${queryName}\"`);\n return;\n }\n if ('sql' in entry) {\n runSql(cfg, entry.sql, params, ctx.format, `query \"${queryName}\"`);\n return;\n }\n\n // A saved search's text is fixed in config; there is nowhere for a positional to bind.\n if (params.length > 0) {\n ctx.usageError(`\"${queryName}\" is a saved search and takes no positional parameters; edit its \"search\" in sense.config.json, or use \"${ctx.name} search\" directly`);\n }\n const k = parseK(ctx) ?? entry.k;\n const where = ctx.values.where ?? entry.where;\n const preset = ctx.values.preset ?? entry.preset;\n const include = ctx.values.include ?? entry.include;\n // --lexical upgrades a saved search's semantic behavior the same way --where/--k\n // override; absent means the saved value (the flag has no default false override).\n const semantic = ctx.values.lexical ? false : entry.semantic;\n await withDb(ctx, async (db, resolvedCfg) => printRows(await search(db, resolvedCfg, entry.search, { k, where, preset, include, semantic }), ctx.format));\n}\n"],"names":["named","ctx","queryName","params","parseK","cfg","entry","k","where","preset","include","semantic","resolveConfig","queries","undefined","console","error","Object","keys","sort","join","process","exit","runSql","format","sql","length","usageError","name","values","lexical","withDb","db","resolvedCfg","search","printRows"],"mappings":";;;;+BAKA,2FAA2F;AAC3F,+FAA+F;AAC/F;;;eAA8BA;;;0BAPP;wBACG;wBACa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKxB,SAAeA,MAAMC,GAAQ,EAAEC,SAAiB,EAAEC,MAAgB;;YAsBrEC,SACIH,mBACCA,oBACCA,qBAxBVI,KACAC,OAoBAC,GACAC,OACAC,QACAC,SAGAC;;;;oBA3BAN,MAAMJ,IAAIW,aAAa;oBACvBN,QAAQD,IAAIQ,OAAO,CAACX,UAAU;oBACpC,IAAII,UAAUQ,WAAW;wBACvBC,QAAQC,KAAK,CAAC,AAAC,mBAA4B,OAAVd,WAAU;wBAC3Ca,QAAQC,KAAK,CAAC,AAAC,kBAA4D,OAA3CC,OAAOC,IAAI,CAACb,IAAIQ,OAAO,EAAEM,IAAI,GAAGC,IAAI,CAAC;wBACrEC,QAAQC,IAAI,CAAC;oBACf;oBAEA,IAAI,OAAOhB,UAAU,UAAU;wBAC7BiB,IAAAA,gBAAM,EAAClB,KAAKC,OAAOH,QAAQF,IAAIuB,MAAM,EAAE,AAAC,UAAmB,OAAVtB,WAAU;wBAC3D;;;oBACF;oBACA,IAAI,SAASI,OAAO;wBAClBiB,IAAAA,gBAAM,EAAClB,KAAKC,MAAMmB,GAAG,EAAEtB,QAAQF,IAAIuB,MAAM,EAAE,AAAC,UAAmB,OAAVtB,WAAU;wBAC/D;;;oBACF;oBAEA,uFAAuF;oBACvF,IAAIC,OAAOuB,MAAM,GAAG,GAAG;wBACrBzB,IAAI0B,UAAU,CAAC,AAAC,IAAuH1B,OAApHC,WAAU,4GAAmH,OAATD,IAAI2B,IAAI,EAAC;oBAClJ;oBACMrB,KAAIH,UAAAA,IAAAA,gBAAM,EAACH,kBAAPG,qBAAAA,UAAeE,MAAMC,CAAC;oBAC1BC,SAAQP,oBAAAA,IAAI4B,MAAM,CAACrB,KAAK,cAAhBP,+BAAAA,oBAAoBK,MAAME,KAAK;oBACvCC,UAASR,qBAAAA,IAAI4B,MAAM,CAACpB,MAAM,cAAjBR,gCAAAA,qBAAqBK,MAAMG,MAAM;oBAC1CC,WAAUT,sBAAAA,IAAI4B,MAAM,CAACnB,OAAO,cAAlBT,iCAAAA,sBAAsBK,MAAMI,OAAO;oBACnD,iFAAiF;oBACjF,mFAAmF;oBAC7EC,WAAWV,IAAI4B,MAAM,CAACC,OAAO,GAAG,QAAQxB,MAAMK,QAAQ;oBAC5D;;wBAAMoB,IAAAA,gBAAM,EAAC9B,KAAK,SAAO+B,IAAIC;;;;;4CAA0B;;gDAAMC,IAAAA,kBAAM,EAACF,IAAIC,aAAa3B,MAAM4B,MAAM,EAAE;oDAAE3B,GAAAA;oDAAGC,OAAAA;oDAAOC,QAAAA;oDAAQC,SAAAA;oDAASC,UAAAA;gDAAS;;;;;gDAA5FwB,mBAAS;oDAAC;oDAAsFlC,IAAIuB,MAAM;;;;;;;;;oBAAvJ;;;;;;IACF"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from './types.js';
2
+ declare const searchCmd: Command;
3
+ export default searchCmd;
@@ -0,0 +1,3 @@
1
+ import type { Command } from './types.js';
2
+ declare const searchCmd: Command;
3
+ export default searchCmd;
@@ -185,14 +185,14 @@ function _ts_generator(thisArg, body) {
185
185
  };
186
186
  }
187
187
  }
188
- var findCmd = function findCmd(ctx) {
188
+ var searchCmd = function searchCmd(ctx) {
189
189
  return _async_to_generator(function() {
190
190
  var _ctx_rest, terms, k;
191
191
  return _ts_generator(this, function(_state) {
192
192
  switch(_state.label){
193
193
  case 0:
194
194
  _ctx_rest = _sliced_to_array(ctx.rest, 1), terms = _ctx_rest[0];
195
- if (!terms) ctx.usageError("usage: ".concat(ctx.name, ' find "<terms>" [--where "<sql>"] [--k n] [--semantic]'));
195
+ if (!terms) ctx.usageError("usage: ".concat(ctx.name, ' search "<terms>" [--preset name] [--include glob ...] [--where "<sql>"] [--k n] [--lexical]'));
196
196
  k = (0, _sharedts.parseK)(ctx);
197
197
  return [
198
198
  4,
@@ -203,10 +203,12 @@ var findCmd = function findCmd(ctx) {
203
203
  case 0:
204
204
  return [
205
205
  4,
206
- (0, _commandsts.find)(db, cfg, terms, {
206
+ (0, _commandsts.search)(db, cfg, terms, {
207
207
  k: k,
208
208
  where: ctx.values.where,
209
- semantic: ctx.values.semantic
209
+ preset: ctx.values.preset,
210
+ include: ctx.values.include,
211
+ semantic: ctx.values.lexical ? false : undefined
210
212
  })
211
213
  ];
212
214
  case 1:
@@ -231,5 +233,5 @@ var findCmd = function findCmd(ctx) {
231
233
  });
232
234
  })();
233
235
  };
234
- var _default = findCmd;
236
+ var _default = searchCmd;
235
237
  /* 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/search.ts"],"sourcesContent":["import { search } from '../commands.ts';\nimport { printRows } from '../output.ts';\nimport { parseK, withDb } from './shared.ts';\nimport type { Command } from './types.ts';\n\nconst searchCmd: Command = async (ctx) => {\n const [terms] = ctx.rest;\n if (!terms) ctx.usageError(`usage: ${ctx.name} search \"<terms>\" [--preset name] [--include glob ...] [--where \"<sql>\"] [--k n] [--lexical]`);\n const k = parseK(ctx);\n await withDb(ctx, async (db, cfg) => printRows(await search(db, cfg, terms, { k, where: ctx.values.where, preset: ctx.values.preset, include: ctx.values.include, semantic: ctx.values.lexical ? false : undefined }), ctx.format));\n};\nexport default searchCmd;\n"],"names":["searchCmd","ctx","terms","k","rest","usageError","name","parseK","withDb","db","cfg","search","where","values","preset","include","semantic","lexical","undefined","printRows","format"],"mappings":";;;;+BAWA;;;eAAA;;;0BAXuB;wBACG;wBACK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG/B,IAAMA,YAAqB,mBAAOC;;YAChBA,WAATC,OAEDC;;;;oBAFUF,6BAAAA,IAAIG,IAAI,MAAjBF,QAASD;oBAChB,IAAI,CAACC,OAAOD,IAAII,UAAU,CAAC,AAAC,UAAkB,OAATJ,IAAIK,IAAI,EAAC;oBACxCH,IAAII,IAAAA,gBAAM,EAACN;oBACjB;;wBAAMO,IAAAA,gBAAM,EAACP,KAAK,SAAOQ,IAAIC;;;;;4CAAkB;;gDAAMC,IAAAA,kBAAM,EAACF,IAAIC,KAAKR,OAAO;oDAAEC,GAAAA;oDAAGS,OAAOX,IAAIY,MAAM,CAACD,KAAK;oDAAEE,QAAQb,IAAIY,MAAM,CAACC,MAAM;oDAAEC,SAASd,IAAIY,MAAM,CAACE,OAAO;oDAAEC,UAAUf,IAAIY,MAAM,CAACI,OAAO,GAAG,QAAQC;gDAAU;;;;;gDAA9KC,mBAAS;oDAAC;oDAAwKlB,IAAImB,MAAM;;;;;;;;;oBAAjO;;;;;;IACF;;IACA,WAAepB"}
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/shared.ts"],"sourcesContent":["import type { ResolvedConfig } from '../config.ts';\nimport type { OpenResult } from '../db.ts';\nimport { open } from '../db.ts';\nimport type { Row } from '../output.ts';\nimport { printRows } from '../output.ts';\nimport { searchError } from '../search-error.ts';\nimport type { Ctx } from './types.ts';\n\n// --k must be a positive integer: SQLite reads a bound LIMIT of -1 as \"unlimited\" and 0 as\n// \"nothing\", and parseInt would silently truncate \"5.9\" -- all three are caller mistakes\n// worth a usage error, matching the config-level SavedFind validation.\nexport function parseK(ctx: Ctx): number | undefined {\n if (ctx.values.k === undefined) return undefined;\n const k = Number(ctx.values.k);\n if (!Number.isInteger(k) || k <= 0) ctx.usageError(`--k expects a positive integer, got \"${ctx.values.k}\"`);\n return k;\n}\n\n// Shared open-query-close envelope for commands that touch the tree.\n\nexport function printWarnings(warnings: string[]): void {\n for (const w of warnings) console.warn(w);\n}\n\nexport async function withDb(ctx: Ctx, fn: (db: OpenResult['db'], cfg: ResolvedConfig) => void | Promise<void>): Promise<void> {\n const cfg = ctx.resolveConfig();\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n try {\n await fn(db, cfg);\n } finally {\n db.close();\n }\n}\n\n// An unbound `?` silently binds NULL, so mismatched param counts fail loudly instead.\nexport function runSql(cfg: ResolvedConfig, sql: string, params: string[], format: 'table' | 'json', label: string): void {\n const placeholderCount = (sql.match(/\\?/g) ?? []).length;\n if (params.length !== placeholderCount) {\n console.error(`${label} expects ${placeholderCount} parameter(s), got ${params.length}`);\n process.exit(2);\n }\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n let rows: Row[];\n try {\n rows = db.prepare(sql).all(...params) as Row[];\n } catch (err) {\n db.close();\n // A saved query or ad-hoc SQL can carry `content MATCH ?` too, so the same FTS5\n // punctuation trap applies -- the bound parameters are the search terms there. SQL\n // without MATCH gets its error verbatim; search advice on a plain typo would mislead.\n if (/\\bMATCH\\b/i.test(sql)) throw searchError(err as Error, params.join(' '));\n throw err;\n }\n printRows(rows, format);\n db.close();\n}\n"],"names":["parseK","printWarnings","runSql","withDb","ctx","values","k","undefined","Number","isInteger","usageError","warnings","w","console","warn","fn","cfg","open","db","resolveConfig","close","sql","params","format","label","placeholderCount","match","length","error","process","exit","rows","prepare","all","err","test","searchError","join","printRows"],"mappings":";;;;;;;;;;;QAWgBA;eAAAA;;QASAC;eAAAA;;QAgBAC;eAAAA;;QAZMC;eAAAA;;;oBAtBD;wBAEK;6BACE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMrB,SAASH,OAAOI,GAAQ;IAC7B,IAAIA,IAAIC,MAAM,CAACC,CAAC,KAAKC,WAAW,OAAOA;IACvC,IAAMD,IAAIE,OAAOJ,IAAIC,MAAM,CAACC,CAAC;IAC7B,IAAI,CAACE,OAAOC,SAAS,CAACH,MAAMA,KAAK,GAAGF,IAAIM,UAAU,CAAC,AAAC,wCAAoD,OAAbN,IAAIC,MAAM,CAACC,CAAC,EAAC;IACxG,OAAOA;AACT;AAIO,SAASL,cAAcU,QAAkB;QACzC,kCAAA,2BAAA;;QAAL,QAAK,YAAWA,6BAAX,SAAA,6BAAA,QAAA,yBAAA;YAAA,IAAMC,IAAN;YAAqBC,QAAQC,IAAI,CAACF;;;QAAlC;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;AACP;AAEO,SAAeT,OAAOC,GAAQ,EAAEW,EAAuE;;YACtGC,KACmBC,OAAjBC,IAAIP;;;;oBADNK,MAAMZ,IAAIe,aAAa;oBACJF,QAAAA,IAAAA,UAAI,EAACD,MAAtBE,KAAiBD,MAAjBC,IAAIP,WAAaM,MAAbN;oBACZV,cAAcU;;;;;;;;;oBAEZ;;wBAAMI,GAAGG,IAAIF;;;oBAAb;;;;;;oBAEAE,GAAGE,KAAK;;;;;;;;;;IAEZ;;AAGO,SAASlB,OAAOc,GAAmB,EAAEK,GAAW,EAAEC,MAAgB,EAAEC,MAAwB,EAAEC,KAAa;QACtFH;IAA1B,IAAMI,mBAAmB,EAACJ,aAAAA,IAAIK,KAAK,CAAC,oBAAVL,wBAAAA,aAAoB,EAAE,EAAEM,MAAM;IACxD,IAAIL,OAAOK,MAAM,KAAKF,kBAAkB;QACtCZ,QAAQe,KAAK,CAAC,AAAC,GAAmBH,OAAjBD,OAAM,aAAiDF,OAAtCG,kBAAiB,uBAAmC,OAAdH,OAAOK,MAAM;QACrFE,QAAQC,IAAI,CAAC;IACf;IACA,IAAyBb,QAAAA,IAAAA,UAAI,EAACD,MAAtBE,KAAiBD,MAAjBC,IAAIP,WAAaM,MAAbN;IACZV,cAAcU;IACd,IAAIoB;IACJ,IAAI;YACKb;QAAPa,OAAOb,CAAAA,cAAAA,GAAGc,OAAO,CAACX,MAAKY,GAAG,OAAnBf,aAAoB,qBAAGI;IAChC,EAAE,OAAOY,KAAK;QACZhB,GAAGE,KAAK;QACR,gFAAgF;QAChF,mFAAmF;QACnF,sFAAsF;QACtF,IAAI,aAAae,IAAI,CAACd,MAAM,MAAMe,IAAAA,0BAAW,EAACF,KAAcZ,OAAOe,IAAI,CAAC;QACxE,MAAMH;IACR;IACAI,IAAAA,mBAAS,EAACP,MAAMR;IAChBL,GAAGE,KAAK;AACV"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/sensemaking/src/cli/shared.ts"],"sourcesContent":["import type { ResolvedConfig } from '../config.ts';\nimport type { OpenResult } from '../db.ts';\nimport { open } from '../db.ts';\nimport type { Row } from '../output.ts';\nimport { printRows } from '../output.ts';\nimport { searchError } from '../search-error.ts';\nimport type { Ctx } from './types.ts';\n\n// --k must be a positive integer: SQLite reads a bound LIMIT of -1 as \"unlimited\" and 0 as\n// \"nothing\", and parseInt would silently truncate \"5.9\" -- all three are caller mistakes\n// worth a usage error, matching the config-level SavedSearch validation.\nexport function parseK(ctx: Ctx): number | undefined {\n if (ctx.values.k === undefined) return undefined;\n const k = Number(ctx.values.k);\n if (!Number.isInteger(k) || k <= 0) ctx.usageError(`--k expects a positive integer, got \"${ctx.values.k}\"`);\n return k;\n}\n\n// Shared open-query-close envelope for commands that touch the tree.\n\nexport function printWarnings(warnings: string[]): void {\n for (const w of warnings) console.warn(w);\n}\n\nexport async function withDb(ctx: Ctx, fn: (db: OpenResult['db'], cfg: ResolvedConfig) => void | Promise<void>): Promise<void> {\n const cfg = ctx.resolveConfig();\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n try {\n await fn(db, cfg);\n } finally {\n db.close();\n }\n}\n\n// An unbound `?` silently binds NULL, so mismatched param counts fail loudly instead.\nexport function runSql(cfg: ResolvedConfig, sql: string, params: string[], format: 'table' | 'json', label: string): void {\n const placeholderCount = (sql.match(/\\?/g) ?? []).length;\n if (params.length !== placeholderCount) {\n console.error(`${label} expects ${placeholderCount} parameter(s), got ${params.length}`);\n process.exit(2);\n }\n const { db, warnings } = open(cfg);\n printWarnings(warnings);\n let rows: Row[];\n try {\n rows = db.prepare(sql).all(...params) as Row[];\n } catch (err) {\n db.close();\n // A saved query or ad-hoc SQL can carry `content MATCH ?` too, so the same FTS5\n // punctuation trap applies -- the bound parameters are the search terms there. SQL\n // without MATCH gets its error verbatim; search advice on a plain typo would mislead.\n if (/\\bMATCH\\b/i.test(sql)) throw searchError(err as Error, params.join(' '));\n throw err;\n }\n printRows(rows, format);\n db.close();\n}\n"],"names":["parseK","printWarnings","runSql","withDb","ctx","values","k","undefined","Number","isInteger","usageError","warnings","w","console","warn","fn","cfg","open","db","resolveConfig","close","sql","params","format","label","placeholderCount","match","length","error","process","exit","rows","prepare","all","err","test","searchError","join","printRows"],"mappings":";;;;;;;;;;;QAWgBA;eAAAA;;QASAC;eAAAA;;QAgBAC;eAAAA;;QAZMC;eAAAA;;;oBAtBD;wBAEK;6BACE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAMrB,SAASH,OAAOI,GAAQ;IAC7B,IAAIA,IAAIC,MAAM,CAACC,CAAC,KAAKC,WAAW,OAAOA;IACvC,IAAMD,IAAIE,OAAOJ,IAAIC,MAAM,CAACC,CAAC;IAC7B,IAAI,CAACE,OAAOC,SAAS,CAACH,MAAMA,KAAK,GAAGF,IAAIM,UAAU,CAAC,AAAC,wCAAoD,OAAbN,IAAIC,MAAM,CAACC,CAAC,EAAC;IACxG,OAAOA;AACT;AAIO,SAASL,cAAcU,QAAkB;QACzC,kCAAA,2BAAA;;QAAL,QAAK,YAAWA,6BAAX,SAAA,6BAAA,QAAA,yBAAA;YAAA,IAAMC,IAAN;YAAqBC,QAAQC,IAAI,CAACF;;;QAAlC;QAAA;;;iBAAA,6BAAA;gBAAA;;;gBAAA;sBAAA;;;;AACP;AAEO,SAAeT,OAAOC,GAAQ,EAAEW,EAAuE;;YACtGC,KACmBC,OAAjBC,IAAIP;;;;oBADNK,MAAMZ,IAAIe,aAAa;oBACJF,QAAAA,IAAAA,UAAI,EAACD,MAAtBE,KAAiBD,MAAjBC,IAAIP,WAAaM,MAAbN;oBACZV,cAAcU;;;;;;;;;oBAEZ;;wBAAMI,GAAGG,IAAIF;;;oBAAb;;;;;;oBAEAE,GAAGE,KAAK;;;;;;;;;;IAEZ;;AAGO,SAASlB,OAAOc,GAAmB,EAAEK,GAAW,EAAEC,MAAgB,EAAEC,MAAwB,EAAEC,KAAa;QACtFH;IAA1B,IAAMI,mBAAmB,EAACJ,aAAAA,IAAIK,KAAK,CAAC,oBAAVL,wBAAAA,aAAoB,EAAE,EAAEM,MAAM;IACxD,IAAIL,OAAOK,MAAM,KAAKF,kBAAkB;QACtCZ,QAAQe,KAAK,CAAC,AAAC,GAAmBH,OAAjBD,OAAM,aAAiDF,OAAtCG,kBAAiB,uBAAmC,OAAdH,OAAOK,MAAM;QACrFE,QAAQC,IAAI,CAAC;IACf;IACA,IAAyBb,QAAAA,IAAAA,UAAI,EAACD,MAAtBE,KAAiBD,MAAjBC,IAAIP,WAAaM,MAAbN;IACZV,cAAcU;IACd,IAAIoB;IACJ,IAAI;YACKb;QAAPa,OAAOb,CAAAA,cAAAA,GAAGc,OAAO,CAACX,MAAKY,GAAG,OAAnBf,aAAoB,qBAAGI;IAChC,EAAE,OAAOY,KAAK;QACZhB,GAAGE,KAAK;QACR,gFAAgF;QAChF,mFAAmF;QACnF,sFAAsF;QACtF,IAAI,aAAae,IAAI,CAACd,MAAM,MAAMe,IAAAA,0BAAW,EAACF,KAAcZ,OAAOe,IAAI,CAAC;QACxE,MAAMH;IACR;IACAI,IAAAA,mBAAS,EAACP,MAAMR;IAChBL,GAAGE,KAAK;AACV"}
@@ -8,8 +8,10 @@ Object.defineProperty(exports, "default", {
8
8
  return _default;
9
9
  }
10
10
  });
11
+ var _commandsts = require("../commands.js");
11
12
  var _configts = require("../config.js");
12
13
  var _dbts = require("../db.js");
14
+ var _outputts = require("../output.js");
13
15
  var _sharedts = require("./shared.js");
14
16
  function _define_property(obj, key, value) {
15
17
  if (key in obj) {
@@ -39,9 +41,9 @@ function _object_spread(target) {
39
41
  }
40
42
  return target;
41
43
  }
42
- // Vectors are computed on the first semantic query, not at reconcile, so a tree can be
43
- // embed-enabled with nothing embedded yet -- reported here because a fast `rebuild` on an
44
- // embed tree otherwise reads as "the feature isn't on".
44
+ // Vectors are computed on the first semantic query, not at reconcile, so a tree can have a
45
+ // semantic-on preset with nothing embedded yet -- reported here because a fast `rebuild` on
46
+ // such a tree otherwise reads as "the feature isn't on".
45
47
  function vectorState(db) {
46
48
  try {
47
49
  var row = db.prepare('SELECT COUNT(vector) AS embedded, COUNT(*) - COUNT(vector) AS pending FROM embeddings').get();
@@ -51,14 +53,13 @@ function vectorState(db) {
51
53
  }
52
54
  }
53
55
  var status = function status(ctx) {
54
- var _ref;
55
- var _cfg_defaults_find, _cfg_defaults;
56
56
  var cfg = ctx.resolveConfig();
57
57
  var _open = (0, _dbts.open)(cfg), db = _open.db, dbPath = _open.dbPath, warnings = _open.warnings;
58
58
  (0, _sharedts.printWarnings)(warnings);
59
59
  var features = (0, _configts.featureStates)(cfg);
60
60
  var e = (0, _configts.embedConfig)(cfg);
61
61
  var vectors = e ? vectorState(db) : null;
62
+ var presets = (0, _commandsts.presetCoverage)(db, cfg);
62
63
  var heartbeat = (0, _dbts.getMeta)(db, 'watch_heartbeat');
63
64
  // Derived at open() (F): 3x the largest reconcile this cache has ever held its write
64
65
  // transaction for, floored at 30s -- read back from the connection rather than
@@ -73,7 +74,7 @@ var status = function status(ctx) {
73
74
  type: e.type,
74
75
  model: e.model
75
76
  }, vectors !== null && vectors !== void 0 ? vectors : {}) : null,
76
- findDefaultWhere: (_ref = (_cfg_defaults = cfg.defaults) === null || _cfg_defaults === void 0 ? void 0 : (_cfg_defaults_find = _cfg_defaults.find) === null || _cfg_defaults_find === void 0 ? void 0 : _cfg_defaults_find.where) !== null && _ref !== void 0 ? _ref : null,
77
+ presets: presets,
77
78
  watcherHeartbeatSecondsAgo: heartbeat ? Math.round((Date.now() - Date.parse(heartbeat)) / 1000) : null,
78
79
  busyTimeoutMs: busyTimeoutMs
79
80
  };
@@ -82,12 +83,28 @@ var status = function status(ctx) {
82
83
  } else {
83
84
  console.log("db: ".concat(result.db));
84
85
  console.log("docs: ".concat(result.docs));
85
- var off = features.off.length > 0 ? " \xb7 off: ".concat(features.off.map(function(name) {
86
- return "".concat(name, " (features.").concat(name, ")");
87
- }).join(', ')) : '';
88
- console.log("features: ".concat(features.on.join(', ')).concat(off));
89
- if (e) console.log("embed: ".concat(e.type, " ").concat(e.model).concat(vectors ? " (vectors: ".concat(vectors.embedded, " embedded, ").concat(vectors.pending, " pending — embedded on first --semantic query)") : ''));
90
- if (result.findDefaultWhere) console.log("find default scope: ".concat(result.findDefaultWhere, " (--where replaces it)"));
86
+ console.log((0, _outputts.featuresLine)(features));
87
+ if (e) console.log("embed: ".concat(e.type, " ").concat(e.model).concat(vectors ? " (vectors: ".concat(vectors.embedded, " embedded, ").concat(vectors.pending, " pending — embedded on the first semantic search)") : ''));
88
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
89
+ try {
90
+ for(var _iterator = (0, _outputts.presetsLines)(presets)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
91
+ var line = _step.value;
92
+ console.log(line);
93
+ }
94
+ } catch (err) {
95
+ _didIteratorError = true;
96
+ _iteratorError = err;
97
+ } finally{
98
+ try {
99
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
100
+ _iterator.return();
101
+ }
102
+ } finally{
103
+ if (_didIteratorError) {
104
+ throw _iteratorError;
105
+ }
106
+ }
107
+ }
91
108
  console.log(result.watcherHeartbeatSecondsAgo === null ? 'watcher: no watcher' : "watcher: last heartbeat ".concat(result.watcherHeartbeatSecondsAgo, "s ago"));
92
109
  console.log("busy_timeout: ".concat(result.busyTimeoutMs, "ms (derived: 3x the largest reconcile this cache has recorded, floored at 30000ms)"));
93
110
  }