sensemaking 0.7.2 → 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 (207) hide show
  1. package/README.md +90 -61
  2. package/dist/cjs/cli/check.js +367 -0
  3. package/dist/cjs/cli/check.js.map +1 -0
  4. package/dist/cjs/{commands → cli}/index.js +2 -2
  5. package/dist/cjs/cli/index.js.map +1 -0
  6. package/dist/cjs/{commands → cli}/init.js +3 -0
  7. package/dist/cjs/cli/init.js.map +1 -0
  8. package/dist/cjs/{commands → cli}/map.js +2 -2
  9. package/dist/cjs/cli/map.js.map +1 -0
  10. package/dist/cjs/{commands → cli}/named.d.cts +1 -1
  11. package/dist/cjs/{commands → cli}/named.d.ts +1 -1
  12. package/dist/cjs/cli/named.js +219 -0
  13. package/dist/cjs/cli/named.js.map +1 -0
  14. package/dist/cjs/{commands → cli}/peek.js +2 -2
  15. package/dist/cjs/cli/peek.js.map +1 -0
  16. package/dist/cjs/cli/query.js.map +1 -0
  17. package/dist/cjs/cli/rebuild.js.map +1 -0
  18. package/dist/cjs/cli/search.d.cts +3 -0
  19. package/dist/cjs/cli/search.d.ts +3 -0
  20. package/dist/cjs/{commands/find.js → cli/search.js} +9 -8
  21. package/dist/cjs/cli/search.js.map +1 -0
  22. package/dist/cjs/{commands → cli}/shared.d.cts +1 -0
  23. package/dist/{esm/commands → cjs/cli}/shared.d.ts +1 -0
  24. package/dist/cjs/{commands → cli}/shared.js +9 -0
  25. package/dist/cjs/cli/shared.js.map +1 -0
  26. package/dist/cjs/{commands → cli}/status.js +36 -13
  27. package/dist/cjs/cli/status.js.map +1 -0
  28. package/dist/cjs/{commands → cli}/types.d.cts +3 -1
  29. package/dist/{esm/commands → cjs/cli}/types.d.ts +3 -1
  30. package/dist/cjs/cli/watch.js.map +1 -0
  31. package/dist/cjs/cli.js +42 -17
  32. package/dist/cjs/cli.js.map +1 -1
  33. package/dist/{esm/verbs.d.ts → cjs/commands.d.cts} +15 -5
  34. package/dist/cjs/{verbs.d.cts → commands.d.ts} +15 -5
  35. package/dist/cjs/{verbs.js → commands.js} +329 -39
  36. package/dist/cjs/commands.js.map +1 -0
  37. package/dist/cjs/config.d.cts +45 -12
  38. package/dist/cjs/config.d.ts +45 -12
  39. package/dist/cjs/config.js +464 -125
  40. package/dist/cjs/config.js.map +1 -1
  41. package/dist/cjs/db.d.cts +1 -1
  42. package/dist/cjs/db.d.ts +1 -1
  43. package/dist/cjs/db.js +293 -76
  44. package/dist/cjs/db.js.map +1 -1
  45. package/dist/cjs/errors.d.cts +1 -1
  46. package/dist/cjs/errors.d.ts +1 -1
  47. package/dist/cjs/errors.js.map +1 -1
  48. package/dist/cjs/features/embed.js +19 -3
  49. package/dist/cjs/features/embed.js.map +1 -1
  50. package/dist/cjs/features/links.js +201 -24
  51. package/dist/cjs/features/links.js.map +1 -1
  52. package/dist/cjs/features/rank.js +8 -1
  53. package/dist/cjs/features/rank.js.map +1 -1
  54. package/dist/cjs/features/types.d.cts +12 -4
  55. package/dist/cjs/features/types.d.ts +12 -4
  56. package/dist/cjs/index.d.cts +3 -3
  57. package/dist/cjs/index.d.ts +3 -3
  58. package/dist/cjs/index.js +9 -6
  59. package/dist/cjs/index.js.map +1 -1
  60. package/dist/cjs/output.d.cts +16 -0
  61. package/dist/cjs/output.d.ts +16 -0
  62. package/dist/cjs/output.js +27 -5
  63. package/dist/cjs/output.js.map +1 -1
  64. package/dist/cjs/progress.d.cts +5 -0
  65. package/dist/cjs/progress.d.ts +5 -0
  66. package/dist/cjs/progress.js +54 -0
  67. package/dist/cjs/progress.js.map +1 -0
  68. package/dist/cjs/scan.d.cts +4 -0
  69. package/dist/cjs/scan.d.ts +4 -0
  70. package/dist/cjs/scan.js +87 -6
  71. package/dist/cjs/scan.js.map +1 -1
  72. package/dist/esm/{commands → cli}/check.js +41 -22
  73. package/dist/esm/cli/check.js.map +1 -0
  74. package/dist/esm/{commands → cli}/index.js +1 -1
  75. package/dist/esm/cli/index.js.map +1 -0
  76. package/dist/esm/{commands → cli}/init.js +3 -0
  77. package/dist/esm/cli/init.js.map +1 -0
  78. package/dist/esm/{commands → cli}/map.js +1 -1
  79. package/dist/esm/cli/map.js.map +1 -0
  80. package/dist/esm/{commands → cli}/named.d.ts +1 -1
  81. package/dist/esm/cli/named.js +41 -0
  82. package/dist/esm/cli/named.js.map +1 -0
  83. package/dist/esm/{commands → cli}/peek.js +1 -1
  84. package/dist/esm/cli/peek.js.map +1 -0
  85. package/dist/esm/cli/query.js.map +1 -0
  86. package/dist/esm/cli/rebuild.js.map +1 -0
  87. package/dist/esm/cli/search.d.ts +3 -0
  88. package/dist/esm/cli/search.js +16 -0
  89. package/dist/esm/cli/search.js.map +1 -0
  90. package/dist/{cjs/commands → esm/cli}/shared.d.ts +1 -0
  91. package/dist/esm/{commands → cli}/shared.js +9 -0
  92. package/dist/esm/cli/shared.js.map +1 -0
  93. package/dist/esm/{commands → cli}/status.js +17 -11
  94. package/dist/esm/cli/status.js.map +1 -0
  95. package/dist/{cjs/commands → esm/cli}/types.d.ts +3 -1
  96. package/dist/esm/cli/types.js.map +1 -0
  97. package/dist/esm/cli/watch.js.map +1 -0
  98. package/dist/esm/cli.js +24 -6
  99. package/dist/esm/cli.js.map +1 -1
  100. package/dist/{cjs/verbs.d.ts → esm/commands.d.ts} +15 -5
  101. package/dist/esm/commands.js +386 -0
  102. package/dist/esm/commands.js.map +1 -0
  103. package/dist/esm/config.d.ts +45 -12
  104. package/dist/esm/config.js +367 -93
  105. package/dist/esm/config.js.map +1 -1
  106. package/dist/esm/db.d.ts +1 -1
  107. package/dist/esm/db.js +126 -17
  108. package/dist/esm/db.js.map +1 -1
  109. package/dist/esm/errors.d.ts +1 -1
  110. package/dist/esm/errors.js.map +1 -1
  111. package/dist/esm/features/embed.js +18 -2
  112. package/dist/esm/features/embed.js.map +1 -1
  113. package/dist/esm/features/links.js +130 -20
  114. package/dist/esm/features/links.js.map +1 -1
  115. package/dist/esm/features/rank.js +8 -1
  116. package/dist/esm/features/rank.js.map +1 -1
  117. package/dist/esm/features/types.d.ts +12 -4
  118. package/dist/esm/features/types.js.map +1 -1
  119. package/dist/esm/index.d.ts +3 -3
  120. package/dist/esm/index.js +1 -1
  121. package/dist/esm/index.js.map +1 -1
  122. package/dist/esm/output.d.ts +16 -0
  123. package/dist/esm/output.js +20 -5
  124. package/dist/esm/output.js.map +1 -1
  125. package/dist/esm/progress.d.ts +5 -0
  126. package/dist/esm/progress.js +44 -0
  127. package/dist/esm/progress.js.map +1 -0
  128. package/dist/esm/scan.d.ts +4 -0
  129. package/dist/esm/scan.js +37 -6
  130. package/dist/esm/scan.js.map +1 -1
  131. package/package.json +12 -2
  132. package/schema.json +85 -50
  133. package/skills/sense/EXAMPLES.md +16 -12
  134. package/skills/sense/SKILL.md +74 -55
  135. package/skills/sense-setup/EXAMPLES.md +121 -0
  136. package/skills/sense-setup/SKILL.md +73 -54
  137. package/dist/cjs/commands/check.js +0 -143
  138. package/dist/cjs/commands/check.js.map +0 -1
  139. package/dist/cjs/commands/find.d.cts +0 -3
  140. package/dist/cjs/commands/find.d.ts +0 -3
  141. package/dist/cjs/commands/find.js.map +0 -1
  142. package/dist/cjs/commands/index.js.map +0 -1
  143. package/dist/cjs/commands/init.js.map +0 -1
  144. package/dist/cjs/commands/map.js.map +0 -1
  145. package/dist/cjs/commands/named.js +0 -23
  146. package/dist/cjs/commands/named.js.map +0 -1
  147. package/dist/cjs/commands/peek.js.map +0 -1
  148. package/dist/cjs/commands/query.js.map +0 -1
  149. package/dist/cjs/commands/rebuild.js.map +0 -1
  150. package/dist/cjs/commands/shared.js.map +0 -1
  151. package/dist/cjs/commands/status.js.map +0 -1
  152. package/dist/cjs/commands/watch.js.map +0 -1
  153. package/dist/cjs/verbs.js.map +0 -1
  154. package/dist/esm/commands/check.js.map +0 -1
  155. package/dist/esm/commands/find.d.ts +0 -3
  156. package/dist/esm/commands/find.js +0 -15
  157. package/dist/esm/commands/find.js.map +0 -1
  158. package/dist/esm/commands/index.js.map +0 -1
  159. package/dist/esm/commands/init.js.map +0 -1
  160. package/dist/esm/commands/map.js.map +0 -1
  161. package/dist/esm/commands/named.js +0 -12
  162. package/dist/esm/commands/named.js.map +0 -1
  163. package/dist/esm/commands/peek.js.map +0 -1
  164. package/dist/esm/commands/query.js.map +0 -1
  165. package/dist/esm/commands/rebuild.js.map +0 -1
  166. package/dist/esm/commands/shared.js.map +0 -1
  167. package/dist/esm/commands/status.js.map +0 -1
  168. package/dist/esm/commands/types.js.map +0 -1
  169. package/dist/esm/commands/watch.js.map +0 -1
  170. package/dist/esm/verbs.js +0 -190
  171. package/dist/esm/verbs.js.map +0 -1
  172. /package/dist/cjs/{commands → cli}/check.d.cts +0 -0
  173. /package/dist/cjs/{commands → cli}/check.d.ts +0 -0
  174. /package/dist/cjs/{commands → cli}/index.d.cts +0 -0
  175. /package/dist/cjs/{commands → cli}/index.d.ts +0 -0
  176. /package/dist/cjs/{commands → cli}/init.d.cts +0 -0
  177. /package/dist/cjs/{commands → cli}/init.d.ts +0 -0
  178. /package/dist/cjs/{commands → cli}/map.d.cts +0 -0
  179. /package/dist/cjs/{commands → cli}/map.d.ts +0 -0
  180. /package/dist/cjs/{commands → cli}/peek.d.cts +0 -0
  181. /package/dist/cjs/{commands → cli}/peek.d.ts +0 -0
  182. /package/dist/cjs/{commands → cli}/query.d.cts +0 -0
  183. /package/dist/cjs/{commands → cli}/query.d.ts +0 -0
  184. /package/dist/cjs/{commands → cli}/query.js +0 -0
  185. /package/dist/cjs/{commands → cli}/rebuild.d.cts +0 -0
  186. /package/dist/cjs/{commands → cli}/rebuild.d.ts +0 -0
  187. /package/dist/cjs/{commands → cli}/rebuild.js +0 -0
  188. /package/dist/cjs/{commands → cli}/status.d.cts +0 -0
  189. /package/dist/cjs/{commands → cli}/status.d.ts +0 -0
  190. /package/dist/cjs/{commands → cli}/types.js +0 -0
  191. /package/dist/cjs/{commands → cli}/types.js.map +0 -0
  192. /package/dist/cjs/{commands → cli}/watch.d.cts +0 -0
  193. /package/dist/cjs/{commands → cli}/watch.d.ts +0 -0
  194. /package/dist/cjs/{commands → cli}/watch.js +0 -0
  195. /package/dist/esm/{commands → cli}/check.d.ts +0 -0
  196. /package/dist/esm/{commands → cli}/index.d.ts +0 -0
  197. /package/dist/esm/{commands → cli}/init.d.ts +0 -0
  198. /package/dist/esm/{commands → cli}/map.d.ts +0 -0
  199. /package/dist/esm/{commands → cli}/peek.d.ts +0 -0
  200. /package/dist/esm/{commands → cli}/query.d.ts +0 -0
  201. /package/dist/esm/{commands → cli}/query.js +0 -0
  202. /package/dist/esm/{commands → cli}/rebuild.d.ts +0 -0
  203. /package/dist/esm/{commands → cli}/rebuild.js +0 -0
  204. /package/dist/esm/{commands → cli}/status.d.ts +0 -0
  205. /package/dist/esm/{commands → cli}/types.js +0 -0
  206. /package/dist/esm/{commands → cli}/watch.d.ts +0 -0
  207. /package/dist/esm/{commands → cli}/watch.js +0 -0
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,14 +23,14 @@ 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
  ```
29
30
 
30
31
  ## Model
31
32
 
32
- Every file becomes rows in four tables:
33
+ Every file becomes rows in these tables, plus whatever an enabled feature adds of its own:
33
34
 
34
35
  | table | holds | for |
35
36
  |---|---|---|
@@ -43,8 +44,9 @@ afterward through the filesystem, scoped to the line ranges `peek` returns. This
43
44
  [just-in-time context pattern](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents):
44
45
  the agent holds lightweight identifiers and loads payloads only when needed.
45
46
 
46
- Measured costs: a `find` row is ~20–40 tokens, a `peek` is ~17% of reading the file, and the
47
- section it points at is a direct `Read` range.
47
+ Output size is a contract, measured per release ([BENCHMARKING.md](BENCHMARKING.md)): `map` is
48
+ fixed-size, a `find` row is tens of tokens, and a `peek` stays flat however large the note is —
49
+ so what it saves over reading grows with the file, and a small note is cheaper read whole.
48
50
 
49
51
  ```sql
50
52
  -- filter and search compose in one query
@@ -54,74 +56,93 @@ WHERE f.status = 'active' AND content MATCH 'revenue'
54
56
  ORDER BY bm25(content, 10.0, 5.0, 1.0) LIMIT 10
55
57
  ```
56
58
 
57
- ## Verbs
59
+ ## Commands
58
60
 
59
- | verb | does |
61
+ | command | does |
60
62
  |---|---|
61
63
  | `map` | doc count, frontmatter field coverage, top hubs by link rank, recent changes |
62
- | `find "<terms>" [--where "<sql>"] [--k n] [--semantic]` | BM25 + link-graph expansion, fused; `via` marks each row `match`, `link`, or `match+link` |
63
- | `peek <path>` | frontmatter + heading outline (`[L143-162, ~380t]`) + links both ways, capped at 20 per list |
64
- | `query "<sql>" [params...]` | ad-hoc SQL over all four tables; `?` binds positional args |
65
-
66
- `find` seeds a personalized-PageRank walk with the BM25 matches, so a note that never contains
67
- the terms but is linked from ones that do still surfaces. Terms pass verbatim to FTS5 `MATCH`
68
- (bare words AND-join; operators are yours to write). `--where` takes a frontmatter condition
69
- against alias `f`. On trees with the `embed` feature, `--semantic` additionally expands by
70
- meaning explicit per query, never silent; rows it adds are labeled `via: vector` and carry a
71
- `lines` column pointing at the best-matching section.
72
- `--format json` on any verb returns structured output.
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 |
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 |
66
+ | `query "<sql>" [params...]` | ad-hoc SQL over all the tables; `?` binds positional args |
67
+ | `<name> [params...]` | run a query saved in the config; `--list` names them |
68
+ | `init` | write a starter `sense.config.json` |
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 |
71
+ | `rebuild` | delete the cache and re-crawl |
72
+ | `watch` | keep the index warm in the background (optional; see [WATCH.md](WATCH.md)) |
73
+
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.
73
83
 
74
84
  ## Config
75
85
 
76
86
  `sense init` writes `sense.config.json`; discovery walks up from cwd like git
77
- (`--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.
78
89
 
79
90
  ```json
80
91
  {
81
92
  "$schema": "https://unpkg.com/sensemaking/schema.json",
82
- "version": 2,
83
- "scan": { "include": ["**/*.md"] },
84
- "features": { "links": true, "sections": true, "rank": true },
93
+ "version": 3,
94
+ "presets": {
95
+ "default": { "include": ["**/*.md"], "k": 10 },
96
+ "raw": { "include": ["raw/**/*.md"], "k": 5, "semantic": false }
97
+ },
85
98
  "queries": {
86
- "by-tag": "SELECT path, title FROM frontmatter WHERE has(tags, ?) ORDER BY path"
99
+ "dead-links": "SELECT src, target FROM links WHERE dst IS NULL",
100
+ "by-tag": "SELECT path, title FROM frontmatter WHERE has(tags, ?) ORDER BY path",
101
+ "hot": { "search": "pricing OR billing", "preset": "raw" }
87
102
  }
88
103
  }
89
104
  ```
90
105
 
91
- Features toggle independently; disabling one degrades its verb instead of failing it (`find`
92
- goes BM25-only without `links`, `map` drops hubs without `rank`, `peek` drops the outline
93
- without `sections`). Toggling rebuilds the cache. Older config versions auto-migrate on load,
94
- noted on stderr.
95
-
96
- `embed` is the one opt-in feature (absent = off; most trees don't need vectors): `"embed": true`
97
- uses the built-in static model (downloaded to `~/.cache/sensemaking` on first use, never in the
98
- package), or `{ "model", "type": "static"|"api", "url", "key" }` points at any Model2Vec model,
99
- local path, or OpenAI-compatible endpoint (Ollama, LM Studio, hosted). With it on, vectors stay
100
- fresh at reconcile and `find --semantic` uses them; default `find` results are unchanged.
101
-
102
- ## Reference
103
-
104
- - `has(field, value)` — the one custom SQL function: array membership on JSON-array fields,
105
- substring on strings (so `has(f.status, 'active')` also matches `inactive`), false on missing
106
- keys. Exact matches: `=` for scalars, `EXISTS (SELECT 1 FROM json_each(f.tags) WHERE value = ?)`
107
- for array members.
108
- - Reserved frontmatter keys (dropped with a warning): `path`, `_mtime`, `_size`, `_rank`,
109
- `content`, `links`, `sections`.
110
- - FTS5 syntax in `MATCH`: `a OR b`, `"phrase"`, `pref*`, `NEAR(a b, 5)`, `summary: term`.
111
- Stemmed; markdown is stripped at index time. `bm25(content, 10.0, 5.0, 1.0)` weights title
112
- over summary over body.
113
- - A one-line `summary:` in frontmatter is both a selectable column and a weighted search field.
114
- - Exit codes: `0` ok, `1` error (SQLite message verbatim), `2` usage.
115
- - Frontmatter parsing is lenient: syntax errors (an alias starting with `@`, say) are per-file
116
- warnings and the values are still indexed.
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.
113
+
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.
118
+
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.
123
+
124
+ `has(field, value)` is the one custom SQL function: array membership on JSON-array fields,
125
+ substring on strings, false on missing keys. Frontmatter parsing is lenient syntax errors are
126
+ per-file warnings and the values are still indexed, so one bad note never costs you the crawl.
117
127
 
118
128
  ## Scale
119
129
 
120
130
  Every query starts with a freshness check against the cache in `.sense/`; only changed files are
121
- re-parsed. Measured per release in [BENCHMARKING.md](BENCHMARKING.md) at 6,566 notes: full
122
- crawl ~5 s, warm query ~100 ms, one-file change ~200 ms. `sense watch` (optional) moves
123
- re-parsing into the background see [WATCH.md](WATCH.md). `sense rebuild` deletes the cache and
124
- re-crawls.
131
+ re-parsed. What to expect as a tree grows:
132
+
133
+ - **Work is linear in note count** crawl, reconcile, and the freshness check every invocation
134
+ pays. That check is the floor cost of a query and the first thing to watch on a large tree.
135
+ - **Output is flat.** `map`, `peek`, and a `find` row cost the same on a small tree as a large
136
+ one: context cost is bounded by what you ask for, not by how much there is.
137
+ - **Bulk changes are paid by whoever queries next.** `sense watch` moves that re-parse into the
138
+ background ([WATCH.md](WATCH.md)) — it changes latency, never answers, since every query
139
+ reconciles for itself. `sense rebuild` starts the cache over.
140
+
141
+ These are release gates rather than hopes: every release regenerates the numbers on pinned
142
+ corpora spanning a 4x range in note count plus a stress tree that packs the worst measured
143
+ shapes into one place — a megabyte-scale note, heading-dense outlines, dense link graphs,
144
+ hundreds of frontmatter fields. A row that grows faster than linearly, or a token count
145
+ that grows at all, blocks the release. Current figures: [BENCHMARKING.md](BENCHMARKING.md).
125
146
 
126
147
  ## For AI agents
127
148
 
@@ -129,18 +150,23 @@ re-crawls.
129
150
  npx skills add kmalakoff/sensemaking # -g for global, -a claude-code to target
130
151
  ```
131
152
 
132
- The skill teaches the descent: `map` to orient, `find` to locate, `peek` before reading,
133
- `Read` line ranges instead of files.
153
+ Two skills: `sense` for querying a tree — what each command is for, FTS5 syntax, reading the
154
+ `via`/`score`/`similarity` columns, worked examples and `sense-setup` for making one, where
155
+ features, frontmatter conventions, and note size are decisions with consequences either way.
134
156
 
135
157
  ## Prior art
136
158
 
137
159
  - [Effective context engineering for AI agents](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents)
138
160
  (Anthropic): agents should hold lightweight identifiers — file paths, links — and load payloads
139
- just in time, because context is a finite resource. The four verbs implement that pattern as a CLI.
161
+ just in time, because context is a finite resource. The commands implement that pattern as a CLI.
140
162
  - [llm-wiki](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) (Karpathy): an
141
163
  agent-maintained wiki navigated by an `index.md` and links, which he notes needs real search
142
164
  infrastructure past a few hundred pages. `sense map` derives that index from the notes instead of
143
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.
144
170
 
145
171
  ## Alternatives
146
172
 
@@ -148,13 +174,16 @@ The skill teaches the descent: `map` to orient, `find` to locate, `peek` before
148
174
  query it headless.
149
175
  - **Index-on-build tools (MarkdownDB)** — query a snapshot; `sense` reconciles on every query.
150
176
  - **Note CLIs (zk)** — fixed schema; `sense` filters on arbitrary frontmatter.
151
- - **RAG / vector stores** — similarity can't express `WHERE status = 'active'`. Here vectors are
152
- the optional `embed` feature: same SQLite file, filters compose, expansion is explicit per
153
- 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.
154
181
 
155
182
  Dependencies: [yaml](https://github.com/eemeli/yaml),
156
183
  [remove-markdown](https://github.com/zuchka/remove-markdown),
157
- [fast-glob](https://github.com/mrmlnc/fast-glob), and Node's built-in SQLite. No native builds.
184
+ [fast-glob](https://github.com/mrmlnc/fast-glob),
185
+ [@huggingface/tokenizers](https://github.com/huggingface/tokenizers.js) (pure JS), and Node's
186
+ built-in SQLite. No native builds.
158
187
 
159
188
  ## License
160
189
 
@@ -0,0 +1,367 @@
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 _commandsts = require("../commands.js");
12
+ var _dbts = require("../db.js");
13
+ var _outputts = require("../output.js");
14
+ var _sharedts = require("./shared.js");
15
+ function _array_like_to_array(arr, len) {
16
+ if (len == null || len > arr.length) len = arr.length;
17
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
18
+ return arr2;
19
+ }
20
+ function _array_with_holes(arr) {
21
+ if (Array.isArray(arr)) return arr;
22
+ }
23
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
24
+ try {
25
+ var info = gen[key](arg);
26
+ var value = info.value;
27
+ } catch (error) {
28
+ reject(error);
29
+ return;
30
+ }
31
+ if (info.done) {
32
+ resolve(value);
33
+ } else {
34
+ Promise.resolve(value).then(_next, _throw);
35
+ }
36
+ }
37
+ function _async_to_generator(fn) {
38
+ return function() {
39
+ var self = this, args = arguments;
40
+ return new Promise(function(resolve, reject) {
41
+ var gen = fn.apply(self, args);
42
+ function _next(value) {
43
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
44
+ }
45
+ function _throw(err) {
46
+ asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
47
+ }
48
+ _next(undefined);
49
+ });
50
+ };
51
+ }
52
+ function _iterable_to_array_limit(arr, i) {
53
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
54
+ if (_i == null) return;
55
+ var _arr = [];
56
+ var _n = true;
57
+ var _d = false;
58
+ var _s, _e;
59
+ try {
60
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
61
+ _arr.push(_s.value);
62
+ if (i && _arr.length === i) break;
63
+ }
64
+ } catch (err) {
65
+ _d = true;
66
+ _e = err;
67
+ } finally{
68
+ try {
69
+ if (!_n && _i["return"] != null) _i["return"]();
70
+ } finally{
71
+ if (_d) throw _e;
72
+ }
73
+ }
74
+ return _arr;
75
+ }
76
+ function _non_iterable_rest() {
77
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
78
+ }
79
+ function _sliced_to_array(arr, i) {
80
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
81
+ }
82
+ function _type_of(obj) {
83
+ "@swc/helpers - typeof";
84
+ return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
85
+ }
86
+ function _unsupported_iterable_to_array(o, minLen) {
87
+ if (!o) return;
88
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
89
+ var n = Object.prototype.toString.call(o).slice(8, -1);
90
+ if (n === "Object" && o.constructor) n = o.constructor.name;
91
+ if (n === "Map" || n === "Set") return Array.from(n);
92
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
93
+ }
94
+ function _ts_generator(thisArg, body) {
95
+ var f, y, t, _ = {
96
+ label: 0,
97
+ sent: function() {
98
+ if (t[0] & 1) throw t[1];
99
+ return t[1];
100
+ },
101
+ trys: [],
102
+ ops: []
103
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
104
+ return d(g, "next", {
105
+ value: verb(0)
106
+ }), d(g, "throw", {
107
+ value: verb(1)
108
+ }), d(g, "return", {
109
+ value: verb(2)
110
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
111
+ value: function() {
112
+ return this;
113
+ }
114
+ }), g;
115
+ function verb(n) {
116
+ return function(v) {
117
+ return step([
118
+ n,
119
+ v
120
+ ]);
121
+ };
122
+ }
123
+ function step(op) {
124
+ if (f) throw new TypeError("Generator is already executing.");
125
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
126
+ 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;
127
+ if (y = 0, t) op = [
128
+ op[0] & 2,
129
+ t.value
130
+ ];
131
+ switch(op[0]){
132
+ case 0:
133
+ case 1:
134
+ t = op;
135
+ break;
136
+ case 4:
137
+ _.label++;
138
+ return {
139
+ value: op[1],
140
+ done: false
141
+ };
142
+ case 5:
143
+ _.label++;
144
+ y = op[1];
145
+ op = [
146
+ 0
147
+ ];
148
+ continue;
149
+ case 7:
150
+ op = _.ops.pop();
151
+ _.trys.pop();
152
+ continue;
153
+ default:
154
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
155
+ _ = 0;
156
+ continue;
157
+ }
158
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
159
+ _.label = op[1];
160
+ break;
161
+ }
162
+ if (op[0] === 6 && _.label < t[1]) {
163
+ _.label = t[1];
164
+ t = op;
165
+ break;
166
+ }
167
+ if (t && _.label < t[2]) {
168
+ _.label = t[2];
169
+ _.ops.push(op);
170
+ break;
171
+ }
172
+ if (t[2]) _.ops.pop();
173
+ _.trys.pop();
174
+ continue;
175
+ }
176
+ op = body.call(thisArg, _);
177
+ } catch (e) {
178
+ op = [
179
+ 6,
180
+ e
181
+ ];
182
+ y = 0;
183
+ } finally{
184
+ f = t = 0;
185
+ }
186
+ if (op[0] & 5) throw op[1];
187
+ return {
188
+ value: op[0] ? op[1] : void 0,
189
+ done: true
190
+ };
191
+ }
192
+ }
193
+ // A saved query that returns zero rows looks identical to a true empty result, so a broken
194
+ // one can sit unnoticed -- one field report had `WHERE flag = 'true'` against a numeric
195
+ // column reading as "nothing tagged yet" for hours. Preparing each query catches syntax and
196
+ // unknown-column errors without executing it; queries that take no parameters are also run
197
+ // for a row count. Parameterised queries are validated but not counted: inventing arguments
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.
203
+ var check = function check(ctx) {
204
+ return _async_to_generator(function() {
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;
206
+ return _ts_generator(this, function(_state) {
207
+ switch(_state.label){
208
+ case 0:
209
+ cfg = ctx.resolveConfig();
210
+ _open = (0, _dbts.open)(cfg), db = _open.db, warnings = _open.warnings;
211
+ (0, _sharedts.printWarnings)(warnings);
212
+ rows = [];
213
+ failed = 0;
214
+ _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
215
+ _state.label = 1;
216
+ case 1:
217
+ _state.trys.push([
218
+ 1,
219
+ 10,
220
+ 11,
221
+ 12
222
+ ]);
223
+ _iterator = Object.entries((_cfg_queries = cfg.queries) !== null && _cfg_queries !== void 0 ? _cfg_queries : {})[Symbol.iterator]();
224
+ _state.label = 2;
225
+ case 2:
226
+ if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
227
+ 3,
228
+ 9
229
+ ];
230
+ _step_value = _sliced_to_array(_step.value, 2), name = _step_value[0], entry = _step_value[1];
231
+ if (!((typeof entry === "undefined" ? "undefined" : _type_of(entry)) === 'object' && entry !== null && 'search' in entry)) return [
232
+ 3,
233
+ 7
234
+ ];
235
+ _state.label = 3;
236
+ case 3:
237
+ _state.trys.push([
238
+ 3,
239
+ 5,
240
+ ,
241
+ 6
242
+ ]);
243
+ return [
244
+ 4,
245
+ (0, _commandsts.search)(db, cfg, entry.search, {
246
+ k: 1,
247
+ where: entry.where,
248
+ preset: entry.preset,
249
+ include: entry.include,
250
+ semantic: false
251
+ })
252
+ ];
253
+ case 4:
254
+ count = _state.sent().length;
255
+ rows.push({
256
+ query: name,
257
+ params: '—',
258
+ rows: '—',
259
+ status: count === 0 ? 'ok, but matches 0 notes (lexical probe)' : 'ok (probe run with k=1)'
260
+ });
261
+ return [
262
+ 3,
263
+ 6
264
+ ];
265
+ case 5:
266
+ err = _state.sent();
267
+ failed++;
268
+ rows.push({
269
+ query: name,
270
+ params: '—',
271
+ rows: '—',
272
+ status: "FAILED: ".concat(err.message)
273
+ });
274
+ return [
275
+ 3,
276
+ 6
277
+ ];
278
+ case 6:
279
+ return [
280
+ 3,
281
+ 8
282
+ ];
283
+ case 7:
284
+ sql = typeof entry === 'string' ? entry : entry.sql;
285
+ params = ((_sql_match = sql.match(/\?/g)) !== null && _sql_match !== void 0 ? _sql_match : []).length;
286
+ try {
287
+ statement = db.prepare(sql);
288
+ if (params > 0) {
289
+ rows.push({
290
+ query: name,
291
+ params: params,
292
+ rows: '—',
293
+ status: 'ok (not run: needs parameters)'
294
+ });
295
+ return [
296
+ 3,
297
+ 8
298
+ ];
299
+ }
300
+ count1 = statement.all().length;
301
+ rows.push({
302
+ query: name,
303
+ params: params,
304
+ rows: count1,
305
+ status: count1 === 0 ? 'ok, but returns 0 rows' : 'ok'
306
+ });
307
+ } catch (err) {
308
+ failed++;
309
+ rows.push({
310
+ query: name,
311
+ params: params,
312
+ rows: '—',
313
+ status: "FAILED: ".concat(err.message)
314
+ });
315
+ }
316
+ _state.label = 8;
317
+ case 8:
318
+ _iteratorNormalCompletion = true;
319
+ return [
320
+ 3,
321
+ 2
322
+ ];
323
+ case 9:
324
+ return [
325
+ 3,
326
+ 12
327
+ ];
328
+ case 10:
329
+ err1 = _state.sent();
330
+ _didIteratorError = true;
331
+ _iteratorError = err1;
332
+ return [
333
+ 3,
334
+ 12
335
+ ];
336
+ case 11:
337
+ try {
338
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
339
+ _iterator.return();
340
+ }
341
+ } finally{
342
+ if (_didIteratorError) {
343
+ throw _iteratorError;
344
+ }
345
+ }
346
+ return [
347
+ 7
348
+ ];
349
+ case 12:
350
+ db.close();
351
+ if (rows.length === 0) {
352
+ console.log('no saved queries in config');
353
+ return [
354
+ 2
355
+ ];
356
+ }
357
+ (0, _outputts.printRows)(rows, ctx.format);
358
+ if (failed > 0) process.exit(1);
359
+ return [
360
+ 2
361
+ ];
362
+ }
363
+ });
364
+ })();
365
+ };
366
+ var _default = check;
367
+ /* 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/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() {
@@ -0,0 +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 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"}
@@ -13,6 +13,9 @@ var init = function init(ctx) {
13
13
  var configPath = (0, _configts.initConfig)(process.cwd());
14
14
  console.log("created ".concat(configPath));
15
15
  console.log("query away: ".concat(ctx.name, ' query "SELECT path FROM frontmatter LIMIT 10"'));
16
+ // The decisions a new tree faces -- features, frontmatter conventions, note size -- are not
17
+ // in this output; name both places that hold them, since an agent may have neither.
18
+ console.log('features and tree design: the sense-setup skill, or schema.json');
16
19
  };
17
20
  var _default = init;
18
21
  /* 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/init.ts"],"sourcesContent":["import { initConfig } from '../config.ts';\nimport type { Command } from './types.ts';\n\nconst init: Command = (ctx) => {\n const configPath = initConfig(process.cwd());\n console.log(`created ${configPath}`);\n console.log(`query away: ${ctx.name} query \"SELECT path FROM frontmatter LIMIT 10\"`);\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","configPath","initConfig","process","cwd","console","log","name"],"mappings":";;;;+BAWA;;;eAAA;;;wBAX2B;AAG3B,IAAMA,OAAgB,cAACC;IACrB,IAAMC,aAAaC,IAAAA,oBAAU,EAACC,QAAQC,GAAG;IACzCC,QAAQC,GAAG,CAAC,AAAC,WAAqB,OAAXL;IACvBI,QAAQC,GAAG,CAAC,AAAC,eAAuB,OAATN,IAAIO,IAAI,EAAC;IACpC,4FAA4F;IAC5F,oFAAoF;IACpFF,QAAQC,GAAG,CAAC;AACd;IACA,WAAeP"}