@dikolab/kbdb 0.1.6 → 0.2.1

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 (199) hide show
  1. package/README.md +30 -9
  2. package/dist/cli.cjs +181 -50
  3. package/dist/cli.cjs.map +3 -3
  4. package/dist/cli.mjs +181 -50
  5. package/dist/cli.mjs.map +3 -3
  6. package/dist/kbdb-worker.cjs +283 -29
  7. package/dist/kbdb-worker.cjs.map +4 -4
  8. package/dist/mod.cjs +13 -2
  9. package/dist/mod.cjs.map +2 -2
  10. package/dist/mod.d.ts +25 -0
  11. package/dist/mod.mjs +13 -2
  12. package/dist/mod.mjs.map +2 -2
  13. package/dist/src/cli.d.ts +8 -0
  14. package/dist/src/shared/cli/functions/format-output.function.d.ts +7 -7
  15. package/dist/src/shared/cli/functions/run-search.function.d.ts +25 -16
  16. package/dist/src/shared/cli/index.d.ts +1 -1
  17. package/dist/src/shared/cli/typings/cli-options.interface.d.ts +2 -0
  18. package/dist/src/shared/cli/typings/search-display.model.d.ts +25 -7
  19. package/dist/src/shared/mcp/functions/handle-recall.function.d.ts +29 -0
  20. package/dist/src/shared/mcp/typings/mcp-client.interface.d.ts +30 -11
  21. package/dist/src/shared/version/constants/version.constant.d.ts +1 -1
  22. package/dist/src/shared/wasm-codec/functions/decode-recall-result.function.d.ts +28 -0
  23. package/dist/src/shared/wasm-codec/functions/decode-scored-results.function.d.ts +14 -7
  24. package/dist/src/shared/wasm-codec/functions/encode-recall-params.function.d.ts +21 -0
  25. package/dist/src/shared/wasm-codec/functions/encode-search-params.function.d.ts +1 -1
  26. package/dist/src/shared/wasm-codec/index.d.ts +5 -2
  27. package/dist/src/shared/worker-client/classes/worker-client.class.d.ts +13 -3
  28. package/dist/src/shared/worker-client/index.d.ts +2 -1
  29. package/dist/src/shared/worker-client/typings/recall-result.model.d.ts +94 -0
  30. package/dist/src/shared/worker-client/typings/search-params.model.d.ts +2 -0
  31. package/dist/src/shared/worker-client/typings/search-result.model.d.ts +23 -7
  32. package/dist/src/shared/worker-daemon/classes/worker-daemon.class.d.ts +1 -0
  33. package/dist/src/worker.d.ts +7 -0
  34. package/dist/wasm/fs-database/kbdb_fs_database.d.ts +18 -0
  35. package/dist/wasm/fs-database/kbdb_fs_database.js +30 -0
  36. package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
  37. package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm.d.ts +2 -0
  38. package/dist/wasm/kb-worker/kbdb_worker.d.ts +38 -0
  39. package/dist/wasm/kb-worker/kbdb_worker.js +56 -0
  40. package/dist/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
  41. package/dist/wasm/kb-worker/kbdb_worker_bg.wasm.d.ts +3 -0
  42. package/dist/worker.mjs +283 -29
  43. package/dist/worker.mjs.map +4 -4
  44. package/docs/details/README.md +26 -0
  45. package/docs/details/cli.md +608 -0
  46. package/docs/details/library-api.md +406 -0
  47. package/docs/details/mcp-server.md +430 -0
  48. package/docs/details/search-and-ranking.md +457 -0
  49. package/docs/details/storage.md +529 -0
  50. package/docs/goals/agents.md +751 -0
  51. package/docs/goals/architecture.svg +198 -0
  52. package/docs/goals/cli.md +2308 -0
  53. package/docs/goals/content-composer.md +609 -0
  54. package/docs/goals/content-parser.md +279 -0
  55. package/docs/goals/database.md +1452 -0
  56. package/docs/goals/document.md +368 -0
  57. package/docs/goals/mcp.md +1467 -0
  58. package/docs/goals/overview.md +124 -0
  59. package/docs/goals/query-parser.md +271 -0
  60. package/docs/goals/query-result.md +693 -0
  61. package/docs/goals/skills.md +738 -0
  62. package/docs/goals/worker-client.md +944 -0
  63. package/docs/goals/worker-daemon.md +1447 -0
  64. package/docs/modules/overview.md +298 -0
  65. package/docs/modules/rust/fs-database/functions/document.md +48 -0
  66. package/docs/modules/rust/fs-database/functions/integrity.md +68 -0
  67. package/docs/modules/rust/fs-database/functions/io.md +87 -0
  68. package/docs/modules/rust/fs-database/functions/module.md +22 -0
  69. package/docs/modules/rust/fs-database/functions/query-exec.md +44 -0
  70. package/docs/modules/rust/fs-database/functions/section.md +59 -0
  71. package/docs/modules/rust/fs-database/indexes/btree.md +35 -0
  72. package/docs/modules/rust/fs-database/indexes/corpus.md +61 -0
  73. package/docs/modules/rust/fs-database/indexes/inverted.md +60 -0
  74. package/docs/modules/rust/fs-database/indexes/module.md +64 -0
  75. package/docs/modules/rust/fs-database/indexes/positional.md +39 -0
  76. package/docs/modules/rust/fs-database/module.md +149 -0
  77. package/docs/modules/rust/fs-database/types/catalog.md +53 -0
  78. package/docs/modules/rust/fs-database/types/module.md +12 -0
  79. package/docs/modules/rust/fs-database/types/section.md +101 -0
  80. package/docs/modules/rust/kb-worker/functions/compose.md +57 -0
  81. package/docs/modules/rust/kb-worker/functions/module.md +20 -0
  82. package/docs/modules/rust/kb-worker/functions/retrieve.md +194 -0
  83. package/docs/modules/rust/kb-worker/functions/search.md +173 -0
  84. package/docs/modules/rust/kb-worker/functions/write.md +172 -0
  85. package/docs/modules/rust/kb-worker/module.md +171 -0
  86. package/docs/modules/rust/kb-worker/types/cache.md +90 -0
  87. package/docs/modules/rust/kb-worker/types/context.md +26 -0
  88. package/docs/modules/rust/kb-worker/types/module.md +16 -0
  89. package/docs/modules/rust/kb-worker/types/status.md +29 -0
  90. package/docs/modules/rust/kb-worker/types/token.md +50 -0
  91. package/docs/modules/rust/overview.md +495 -0
  92. package/docs/modules/rust/query-parser/functions/extract.md +56 -0
  93. package/docs/modules/rust/query-parser/functions/module.md +16 -0
  94. package/docs/modules/rust/query-parser/functions/parse.md +33 -0
  95. package/docs/modules/rust/query-parser/functions/pipeline.md +103 -0
  96. package/docs/modules/rust/query-parser/functions/rank.md +85 -0
  97. package/docs/modules/rust/query-parser/module.md +136 -0
  98. package/docs/modules/rust/query-parser/types/cache.md +39 -0
  99. package/docs/modules/rust/query-parser/types/keyphrase.md +60 -0
  100. package/docs/modules/rust/query-parser/types/module.md +17 -0
  101. package/docs/modules/rust/query-parser/types/token.md +42 -0
  102. package/docs/modules/rust/shared/content-composer/functions.md +114 -0
  103. package/docs/modules/rust/shared/content-composer/module.md +147 -0
  104. package/docs/modules/rust/shared/content-composer/types.md +93 -0
  105. package/docs/modules/rust/shared/content-parser/functions.md +72 -0
  106. package/docs/modules/rust/shared/content-parser/module.md +99 -0
  107. package/docs/modules/rust/shared/content-parser/types.md +71 -0
  108. package/docs/modules/rust/shared/corpus/module.md +24 -0
  109. package/docs/modules/rust/shared/corpus/types.md +141 -0
  110. package/docs/modules/rust/shared/document/module.md +25 -0
  111. package/docs/modules/rust/shared/document/types.md +154 -0
  112. package/docs/modules/rust/shared/encode/module.md +22 -0
  113. package/docs/modules/rust/shared/encode/traits.md +304 -0
  114. package/docs/modules/rust/shared/error/module.md +28 -0
  115. package/docs/modules/rust/shared/error/types.md +302 -0
  116. package/docs/modules/rust/shared/kbid/module.md +24 -0
  117. package/docs/modules/rust/shared/kbid/types.md +147 -0
  118. package/docs/modules/rust/shared/memory/functions.md +209 -0
  119. package/docs/modules/rust/shared/memory/module.md +24 -0
  120. package/docs/modules/rust/shared/module.md +168 -0
  121. package/docs/modules/rust/shared/query/module.md +27 -0
  122. package/docs/modules/rust/shared/query/types.md +236 -0
  123. package/docs/modules/rust/shared/section/module.md +25 -0
  124. package/docs/modules/rust/shared/section/types.md +294 -0
  125. package/docs/modules/rust/shared/term/module.md +25 -0
  126. package/docs/modules/rust/shared/term/types.md +139 -0
  127. package/docs/modules/typescript/cli.md +129 -0
  128. package/docs/modules/typescript/kbdb-worker.md +135 -0
  129. package/docs/modules/typescript/overview.md +378 -0
  130. package/docs/modules/typescript/shared/cli/constants.md +23 -0
  131. package/docs/modules/typescript/shared/cli/functions.md +630 -0
  132. package/docs/modules/typescript/shared/cli/module.md +125 -0
  133. package/docs/modules/typescript/shared/cli/typings.md +172 -0
  134. package/docs/modules/typescript/shared/hash/functions.md +20 -0
  135. package/docs/modules/typescript/shared/hash/module.md +21 -0
  136. package/docs/modules/typescript/shared/mcp/classes.md +179 -0
  137. package/docs/modules/typescript/shared/mcp/functions.md +386 -0
  138. package/docs/modules/typescript/shared/mcp/module.md +160 -0
  139. package/docs/modules/typescript/shared/mcp/typings.md +522 -0
  140. package/docs/modules/typescript/shared/module.md +94 -0
  141. package/docs/modules/typescript/shared/platform/functions.md +42 -0
  142. package/docs/modules/typescript/shared/platform/module.md +25 -0
  143. package/docs/modules/typescript/shared/runtime/functions.md +26 -0
  144. package/docs/modules/typescript/shared/runtime/module.md +27 -0
  145. package/docs/modules/typescript/shared/runtime/typings.md +13 -0
  146. package/docs/modules/typescript/shared/version/module.md +27 -0
  147. package/docs/modules/typescript/shared/wasm-codec/functions.md +391 -0
  148. package/docs/modules/typescript/shared/wasm-codec/module.md +98 -0
  149. package/docs/modules/typescript/shared/worker-client/classes.md +264 -0
  150. package/docs/modules/typescript/shared/worker-client/functions.md +175 -0
  151. package/docs/modules/typescript/shared/worker-client/module.md +84 -0
  152. package/docs/modules/typescript/shared/worker-client/typings.md +508 -0
  153. package/docs/modules/typescript/shared/worker-daemon/classes.md +239 -0
  154. package/docs/modules/typescript/shared/worker-daemon/constants.md +37 -0
  155. package/docs/modules/typescript/shared/worker-daemon/functions.md +221 -0
  156. package/docs/modules/typescript/shared/worker-daemon/module.md +112 -0
  157. package/docs/modules/typescript/shared/worker-daemon/typings.md +126 -0
  158. package/docs/overview.md +188 -0
  159. package/docs/release-notes/0.1.0.md +189 -0
  160. package/docs/release-notes/0.1.1.md +46 -0
  161. package/docs/release-notes/0.1.2.md +38 -0
  162. package/docs/release-notes/0.1.3.md +42 -0
  163. package/docs/release-notes/0.2.0.md +147 -0
  164. package/docs/release-notes/README.md +9 -0
  165. package/mod.ts +26 -0
  166. package/package.json +8 -2
  167. package/src/cli.ts +9 -0
  168. package/src/shared/cli/functions/dispatch-command.function.ts +3 -3
  169. package/src/shared/cli/functions/format-output.function.ts +41 -34
  170. package/src/shared/cli/functions/parse-args.function.ts +7 -0
  171. package/src/shared/cli/functions/run-search.function.ts +53 -27
  172. package/src/shared/cli/index.ts +4 -1
  173. package/src/shared/cli/typings/cli-options.interface.ts +2 -0
  174. package/src/shared/cli/typings/search-display.model.ts +26 -7
  175. package/src/shared/mcp/functions/create-tool-definitions.function.ts +64 -4
  176. package/src/shared/mcp/functions/handle-recall.function.ts +66 -0
  177. package/src/shared/mcp/functions/handle-tool-call.function.ts +11 -1
  178. package/src/shared/mcp/typings/mcp-client.interface.ts +33 -15
  179. package/src/shared/version/constants/version.constant.ts +1 -1
  180. package/src/shared/wasm-codec/functions/decode-recall-result.function.ts +267 -0
  181. package/src/shared/wasm-codec/functions/decode-scored-results.function.ts +81 -27
  182. package/src/shared/wasm-codec/functions/encode-recall-params.function.ts +68 -0
  183. package/src/shared/wasm-codec/functions/encode-search-params.function.ts +4 -1
  184. package/src/shared/wasm-codec/index.ts +11 -3
  185. package/src/shared/worker-client/classes/worker-client.class.ts +24 -4
  186. package/src/shared/worker-client/index.ts +11 -1
  187. package/src/shared/worker-client/typings/recall-result.model.ts +98 -0
  188. package/src/shared/worker-client/typings/search-params.model.ts +2 -0
  189. package/src/shared/worker-client/typings/search-result.model.ts +24 -7
  190. package/src/shared/worker-daemon/classes/worker-daemon.class.ts +25 -4
  191. package/src/wasm/fs-database/kbdb_fs_database.d.ts +18 -0
  192. package/src/wasm/fs-database/kbdb_fs_database.js +30 -0
  193. package/src/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
  194. package/src/wasm/fs-database/kbdb_fs_database_bg.wasm.d.ts +2 -0
  195. package/src/wasm/kb-worker/kbdb_worker.d.ts +38 -0
  196. package/src/wasm/kb-worker/kbdb_worker.js +56 -0
  197. package/src/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
  198. package/src/wasm/kb-worker/kbdb_worker_bg.wasm.d.ts +3 -0
  199. package/src/worker.ts +8 -0
@@ -0,0 +1,1447 @@
1
+ # Worker Daemon
2
+
3
+ *A detached TypeScript daemon that loads the WASM
4
+ module, caches indexes and content objects in memory,
5
+ and serves database operations over local IPC.*
6
+
7
+ ## Goal
8
+
9
+ The worker daemon (`src/worker.ts`) is a detached
10
+ background process that provides knowledge base content
11
+ retrieval and caching management. It is accessible
12
+ **only** by worker client connections over local IPC
13
+ (see [Worker Client](worker-client.md)).
14
+
15
+ The daemon:
16
+
17
+ 1. Loads and compiles the `kb-worker` WASM module once
18
+ at startup.
19
+ 2. Holds indexes and content objects in an in-memory
20
+ cache managed by the WASM module.
21
+ 3. Listens for IPC requests from worker client
22
+ connections.
23
+ 4. Processes all database operations through the WASM
24
+ module.
25
+ 5. Returns results over IPC.
26
+
27
+ The daemon is spawned on demand by the worker client
28
+ module and shuts itself down after a configurable idle
29
+ timeout. It is not a persistent server -- it is a
30
+ short-lived background process that exists only to
31
+ amortize WASM compilation cost and share cached data
32
+ across worker client connections.
33
+
34
+ The daemon has no knowledge of its callers. It does not
35
+ know whether a request originates from a CLI invocation,
36
+ an MCP server, or any other consumer. It speaks only
37
+ the JSON-RPC 2.0 protocol defined in this document.
38
+
39
+ ### Why a Separate Process
40
+
41
+ The daemon runs as a separate OS process rather than an
42
+ in-process worker thread to provide:
43
+
44
+ - **Process isolation** -- The daemon survives the exit
45
+ of the process that spawned it. It stays alive as
46
+ long as the idle timeout allows, serving any worker
47
+ client that connects.
48
+ - **Cross-connection sharing** -- Multiple concurrent
49
+ worker client connections share the same daemon and
50
+ its warm cache for the same database directory.
51
+ - **Independent lifecycle** -- The daemon starts and
52
+ stops independently of any single consumer.
53
+ - **Single WASM compilation** -- The daemon compiles
54
+ the WASM module once at startup. All connected worker
55
+ clients reuse the compiled module, avoiding repeated
56
+ compilation overhead.
57
+
58
+ ## Context
59
+
60
+ Every worker daemon operates within a **context** --
61
+ the absolute path to the knowledge base database
62
+ directory (e.g. `${target_dir}/.kbdb`). The context is
63
+ the fundamental scope for all daemon operations. It
64
+ determines:
65
+
66
+ - **Which database is served** -- The daemon loads the
67
+ WASM module and operates exclusively on the database
68
+ at its context path. It never accesses other
69
+ databases.
70
+ - **Which daemon to connect to** -- Each context gets
71
+ its own independent daemon process. Worker client
72
+ connections targeting the same database share one
73
+ daemon; different databases run separate daemons.
74
+ - **Which configuration applies** -- Daemon
75
+ configuration (cache limits, timeouts) is read from
76
+ `worker.toml` inside the context directory.
77
+
78
+ ### Context ID
79
+
80
+ Each context has a **context ID** (`ctx`) -- a
81
+ **SHA-256 hash of the database directory's absolute
82
+ path**, truncated to 16 lowercase hexadecimal
83
+ characters. The truncated hash provides 64 bits of
84
+ entropy -- sufficient to disambiguate all database
85
+ directories on a single machine.
86
+
87
+ Example: `/home/user/project/.kbdb` hashes to
88
+ `ctx = "a1b2c3d4e5f67890"`.
89
+
90
+ The context ID serves as:
91
+
92
+ - **PID file name** -- `kbdb-{ctx}.pid` in the OS
93
+ temporary directory.
94
+ - **IPC socket/pipe name** --
95
+ `kbdb-{ctx}.sock` (Unix) or
96
+ `\\.\pipe\kbdb-{ctx}` (Windows).
97
+ - **Crash log file name** -- `kbdb-{ctx}.crash` in
98
+ the OS temporary directory, written on startup
99
+ failure.
100
+ - **Request validation** -- Every IPC request includes
101
+ the `ctx` param. The daemon verifies it matches its
102
+ own context and rejects misrouted requests with error
103
+ code `-32001` (context mismatch).
104
+
105
+ A single machine may host multiple knowledge bases.
106
+ Each database directory is an independent context with
107
+ its own daemon, its own cache, and its own WASM module
108
+ instance. There is no shared state across contexts.
109
+
110
+ ## Daemon Startup
111
+
112
+ When the worker client spawns a new daemon (see
113
+ [Worker Client -- Spawning](worker-client.md)), the
114
+ daemon process performs the following startup sequence:
115
+
116
+ 1. Reads `worker.toml` from the context directory for
117
+ configuration (falls back to defaults if absent).
118
+ 2. Computes the SHA-256 of the context path to derive
119
+ the context ID.
120
+ 3. Validates startup preconditions (see Startup
121
+ Preconditions below). If any check fails, the daemon
122
+ prints an error to stderr, writes a crash log to
123
+ `{tmpdir}/kbdb-{ctx}.crash`, and exits with code 1.
124
+ It does **not** write a PID file or create an IPC
125
+ socket.
126
+ 4. Compiles and instantiates the `kb-worker` WASM
127
+ module (see WASM Module below).
128
+ 5. Calls `worker_init` on the WASM module to open the
129
+ database context.
130
+ 6. Writes its PID to `kbdb-{ctx}.pid` in the OS
131
+ temporary directory.
132
+ 7. Creates the IPC socket (`kbdb-{ctx}.sock` on Unix,
133
+ named pipe on Windows).
134
+ 8. Begins listening for connections.
135
+
136
+ The daemon only writes its PID file and creates the
137
+ IPC socket after all preconditions pass and the WASM
138
+ module is loaded. If the daemon exits before step 6,
139
+ the worker client's PID-file poll times out, and the
140
+ worker client reads the crash log (or the daemon's
141
+ stderr) to report the failure reason.
142
+
143
+ ### Startup Preconditions
144
+
145
+ The daemon validates the following conditions before
146
+ proceeding with WASM module loading and IPC setup. If
147
+ any condition fails, the daemon prints a structured
148
+ error message to stderr, writes a crash log, and exits
149
+ with exit code `1`.
150
+
151
+ **1. Database directory exists**
152
+
153
+ The context path must be an existing directory. If the
154
+ directory does not exist, the daemon prints to stderr:
155
+
156
+ ```
157
+ kbdb-worker: database directory not found: /path/to/.kbdb
158
+ ```
159
+
160
+ The daemon does not create the directory. Database
161
+ initialisation is the responsibility of the CLI
162
+ (`kbdb --init`) or the `initDirectory` IPC method.
163
+
164
+ **2. Database directory is readable and writable**
165
+
166
+ The daemon must have both read and write access to the
167
+ context directory. The daemon checks both R_OK and
168
+ W_OK access flags.
169
+
170
+ If the directory is not accessible:
171
+
172
+ ```
173
+ kbdb-worker: cannot access database directory: /path/to/.kbdb
174
+ -- permission denied
175
+ ```
176
+
177
+ The daemon requires write access because database
178
+ operations (add, update, remove sections) modify files
179
+ in the context directory. A read-only daemon mode is
180
+ not supported.
181
+
182
+ **3. Database version is compatible**
183
+
184
+ After confirming the directory exists and is
185
+ accessible, the daemon reads `catalog.toml` and checks
186
+ the `version` field against `DB_FORMAT_VERSION` (fixed
187
+ at `1` in `daemon-defaults.constant.ts`).
188
+
189
+ - **version == DB_FORMAT_VERSION** -- compatible,
190
+ proceed with startup.
191
+ - **version > DB_FORMAT_VERSION** -- the database was
192
+ created or migrated by a newer version of kbdb that
193
+ this daemon cannot handle. The daemon prints to
194
+ stderr:
195
+
196
+ ```
197
+ kbdb-worker: database version 3 is newer than kbdb
198
+ version 1 -- upgrade kbdb to open this database
199
+ ```
200
+
201
+ - **version < DB_FORMAT_VERSION** (or absent) -- the
202
+ database needs migration. The daemon prints to
203
+ stderr:
204
+
205
+ ```
206
+ kbdb-worker: database version 0 requires migration
207
+ to version 1 -- run `kbdb --migrate` before
208
+ starting the daemon
209
+ ```
210
+
211
+ The daemon does not auto-migrate. Migration is an
212
+ explicit user action.
213
+
214
+ ### Startup Failure Behaviour
215
+
216
+ When a precondition fails (or WASM loading fails):
217
+
218
+ 1. The daemon prints the error message to **stderr**.
219
+ 2. The daemon writes a crash log to
220
+ `{tmpdir}/kbdb-{ctx}.crash` (JSON with `error`
221
+ and `timestamp` fields).
222
+ 3. The daemon exits with exit code **1**.
223
+ 4. No PID file is written.
224
+ 5. No IPC socket is created.
225
+
226
+ The crash log and stderr output are the mechanisms for
227
+ communicating startup failures. The crash log persists
228
+ after the daemon exits so the worker client can read it
229
+ even after the subprocess has gone.
230
+
231
+ ## Connection Tracking
232
+
233
+ The daemon tracks active client connections via an
234
+ internal counter. The idle timer is only active when
235
+ the connection count is zero. The timer resets whenever
236
+ a client connects, disconnects, or sends a request.
237
+ The daemon stays alive as long as at least one client
238
+ is connected, regardless of the idle timer.
239
+
240
+ ## Graceful Shutdown
241
+
242
+ On shutdown (idle timeout or OS signal SIGTERM/SIGINT),
243
+ the daemon:
244
+
245
+ 1. Clears the idle timer.
246
+ 2. Closes the IPC server, stopping new connections.
247
+ 3. Clears the WASM module references.
248
+ 4. Removes its PID file (`kbdb-{ctx}.pid`).
249
+ 5. Removes the IPC socket file (`kbdb-{ctx}.sock` on
250
+ Unix).
251
+ 6. Removes the crash log (`kbdb-{ctx}.crash`) if it
252
+ exists.
253
+ 7. Calls `process.exit(0)`.
254
+
255
+ ## WASM Module
256
+
257
+ The daemon loads a single WASM module: `kb-worker.wasm`
258
+ (file: `kbdb_worker_bg.wasm`). This module statically
259
+ links the `fs-database` and `query-parser` crates, so
260
+ only one module needs to be compiled and instantiated.
261
+
262
+ ```
263
+ kbdb_worker_bg.wasm
264
+ (statically links fs-database + query-parser)
265
+
266
+ host I/O imports (TypeScript)
267
+ ```
268
+
269
+ ### WASM Module: kb-worker.wasm
270
+
271
+ `kb-worker.wasm` is the single module loaded by the
272
+ daemon. Its responsibilities:
273
+
274
+ - **Query orchestration** -- Parses queries, performs
275
+ index lookups, scores and ranks results.
276
+ - **Write orchestration** -- Tokenizes content per
277
+ field and stores pre-computed term frequencies,
278
+ positions, and token counts in the database.
279
+ - **Cache management** -- Manages the LRU cache of
280
+ sections, indexes, and manifests internally.
281
+ - **Result tokens** -- Manages async query tokens for
282
+ IPC callers.
283
+
284
+ ### Module Loading
285
+
286
+ When the daemon starts (after all startup preconditions
287
+ pass), it:
288
+
289
+ 1. Creates a deferred `MemoryRef` (initially `null`)
290
+ and `AllocatorRef` (initially `null`).
291
+ 2. Builds the host I/O import record using
292
+ `createHostImports`, passing the context path and
293
+ both deferred refs.
294
+ 3. Reads `kbdb_worker_bg.wasm` from the WASM build
295
+ output directory (`kb-worker/kbdb_worker_bg.wasm`).
296
+ 4. Compiles the WASM bytes with `WebAssembly.compile`.
297
+ 5. Instantiates the module with `WebAssembly.instantiate`,
298
+ providing `{ env: { ...hostImports } }`.
299
+ 6. Wires the `MemoryRef` to the module's exported
300
+ `memory` and the `AllocatorRef` to the module's
301
+ exported `kbdb_alloc`.
302
+ 7. Calls `worker_init(pathBytes)` to open the database
303
+ context (passes `.` as the path, resolved relative
304
+ to the context path).
305
+
306
+ The `WasmModules` record tracks only two fields:
307
+
308
+ ```typescript
309
+ interface WasmModules {
310
+ readonly memory: WebAssembly.Memory;
311
+ readonly kbWorker: WebAssembly.Instance;
312
+ }
313
+ ```
314
+
315
+ The module exports its own linear memory (not imported
316
+ externally). Host I/O imports read and write it through
317
+ the deferred `MemoryRef`.
318
+
319
+ ### Host I/O Imports
320
+
321
+ The `kb-worker.wasm` module calls back into TypeScript
322
+ for all filesystem operations. The host import record
323
+ (`createHostImports`) provides:
324
+
325
+ | Import name | Description |
326
+ |-------------------|--------------------------------------------|
327
+ | `host_read_file` | Read file bytes; out-pointer protocol |
328
+ | `host_write_file` | Write bytes to file |
329
+ | `host_rename` | Rename (atomic swap) a file |
330
+ | `host_remove_file`| Delete a file |
331
+ | `host_list_dir` | List directory entries; out-pointer protocol |
332
+ | `host_mkdir` | Create directory recursively |
333
+ | `host_file_exists`| Check if a file exists (returns 1 or 0) |
334
+
335
+ All paths passed from WASM are relative; the host
336
+ resolves them against the `contextPath`. Out-pointer
337
+ functions (`host_read_file`, `host_list_dir`) allocate
338
+ a buffer in WASM memory via `allocator.alloc` and write
339
+ the pointer and length back to WASM-provided addresses.
340
+
341
+ ### WASM Memory Management
342
+
343
+ The TypeScript layer uses four WASM exports to manage
344
+ shared memory:
345
+
346
+ | Export | Signature | Purpose |
347
+ |-------------------|----------------------------------|-----------------------|
348
+ | `kbdb_alloc` | `(size: i32) -> i32` | Allocate WASM memory |
349
+ | `kbdb_free` | `(ptr: i32, size: i32) -> void` | Free WASM memory |
350
+ | `get_return_ptr` | `() -> i32` | Read return slot ptr |
351
+ | `get_return_len` | `() -> i32` | Read return slot len |
352
+
353
+ For call conventions that pass input data:
354
+
355
+ 1. Encode the input as bytes.
356
+ 2. Allocate a buffer with `kbdb_alloc(len)`.
357
+ 3. Write the bytes into WASM memory at the returned
358
+ pointer.
359
+ 4. Call the WASM export with `(ptr, len)`.
360
+ 5. Free the input buffer with `kbdb_free(ptr, len)`.
361
+ 6. Read the return slot with `get_return_ptr()` and
362
+ `get_return_len()`, copy the bytes, then free
363
+ the return buffer.
364
+
365
+ Zero-argument WASM exports (no input data) are called
366
+ directly; only the return slot is read afterward.
367
+
368
+ Return code `-1` (as a signed i32) signals an error;
369
+ the return slot contains a UTF-8 error message.
370
+
371
+ ## Configuration
372
+
373
+ Daemon configuration is stored in
374
+ `${context_path}/worker.toml`. The daemon reads it at
375
+ startup via `readConfig`. If the file is absent or
376
+ unreadable, all defaults apply. The `DaemonConfig`
377
+ interface uses camelCase properties:
378
+
379
+ ```typescript
380
+ interface DaemonConfig {
381
+ readonly contextPath: string;
382
+ readonly itemLimit: number;
383
+ readonly indexLimit: number;
384
+ readonly timeoutMs: number;
385
+ readonly itemTtlMs: number;
386
+ }
387
+ ```
388
+
389
+ Settings (TOML keys map to camelCase properties):
390
+
391
+ | TOML key | Property | Description | Default |
392
+ |----------------|---------------|--------------------------------------|----------------|
393
+ | `item_limit` | `itemLimit` | Max content objects held in cache | 1000 |
394
+ | `index_limit` | `indexLimit` | Max index segments held in cache | 100 |
395
+ | `timeout_ms` | `timeoutMs` | Daemon idle timeout in milliseconds | 300000 (5 min) |
396
+ | `item_ttl_ms` | `itemTtlMs` | Per-item cache TTL in milliseconds | 60000 (1 min) |
397
+
398
+ The `contextPath` field is always set from the runtime
399
+ argument; it is not read from `worker.toml`.
400
+
401
+ Example `worker.toml`:
402
+
403
+ ```toml
404
+ item_limit = 2000
405
+ index_limit = 200
406
+ timeout_ms = 600000
407
+ item_ttl_ms = 120000
408
+ ```
409
+
410
+ Configuration is set once when the daemon spawns and
411
+ does not change until the daemon shuts down and a new
412
+ one is spawned.
413
+
414
+ ## IPC Transport
415
+
416
+ The daemon listens on a local IPC channel:
417
+
418
+ - **Linux / macOS** -- Unix domain socket at
419
+ `{tmpdir}/kbdb-{ctx}.sock`
420
+ (e.g., `/tmp/kbdb-a1b2c3d4e5f67890.sock`).
421
+ - **Windows** -- Named pipe at
422
+ `\\.\pipe\kbdb-{ctx}`.
423
+
424
+ The IPC path is computed by the platform-specific
425
+ `getIpcPath(ctx)` function.
426
+
427
+ Both Deno and Node.js support Unix domain sockets and
428
+ Windows named pipes natively:
429
+
430
+ - **Node.js** -- `net.createServer()` with
431
+ `server.listen(path)` and
432
+ `net.createConnection(path)`.
433
+
434
+ No third-party IPC library is required. The daemon
435
+ creates the IPC socket at startup and removes it on
436
+ shutdown.
437
+
438
+ ## IPC Protocol
439
+
440
+ Communication uses **JSON-RPC 2.0** over the IPC
441
+ channel. Each request is a JSON-RPC call with a method
442
+ name and params; each response is a JSON-RPC result or
443
+ error.
444
+
445
+ Messages are delimited by newlines. Each JSON-RPC
446
+ message is a single line of JSON followed by `\n`. This
447
+ provides simple framing over the stream-oriented IPC
448
+ transport.
449
+
450
+ Every request includes a `ctx` param -- the context ID.
451
+ The daemon verifies the `ctx` matches its own context
452
+ and returns a JSON-RPC error (`-32001`, "context
453
+ mismatch") if it does not.
454
+
455
+ ## Method Routing
456
+
457
+ The daemon dispatches each IPC method to one of three
458
+ categories:
459
+
460
+ 1. **Daemon-state methods** -- handled directly in
461
+ TypeScript without touching WASM.
462
+ 2. **Config methods** (`config_{key}`) -- read from
463
+ `DaemonConfig` in TypeScript.
464
+ 3. **WASM methods** -- routed through `WASM_METHOD_MAP`
465
+ to a named `kb-worker.wasm` export.
466
+
467
+ ### WASM Method Map
468
+
469
+ The daemon accepts both camelCase and snake_case aliases
470
+ for each WASM operation:
471
+
472
+ | IPC method(s) | WASM export |
473
+ |-----------------------------------------|--------------------------|
474
+ | `search`, `query` | `worker_search` |
475
+ | `addSection`, `add_section` | `worker_add_section` |
476
+ | `updateSection`, `update_section` | `worker_update_section` |
477
+ | `removeSection`, `remove_section` | `worker_remove_section` |
478
+ | `readSections`, `read_sections` | `worker_read_sections` |
479
+ | `groupSections`, `group_sections` | `worker_group_sections` |
480
+ | `removeGrouping`, `remove_grouping` | `worker_remove_grouping` |
481
+ | `retrieveDocument`, `retrieve_doc` | `worker_retrieve_doc` |
482
+ | `content`, `compose` | `worker_compose` |
483
+ | `integrityCheck`, `integrity_check` | `worker_check_integrity` |
484
+ | `gc` | `worker_garbage_collect` |
485
+ | `rebuildIndexes`, `rebuild_indexes` | `worker_rebuild_indexes` |
486
+ | `initDirectory`, `init_directory` | `worker_init_directory` |
487
+ | `migrateDatabase` | (not yet supported) |
488
+ | `query` | `worker_query` |
489
+ | `get_result_status` | `worker_result_status` |
490
+ | `get_result` | `worker_get_result` |
491
+ | `invalidate` | `worker_invalidate` |
492
+ | `invalidateAll`, `invalidate_all` | `worker_invalidate_all` |
493
+ | `dbStatus`, `db_status` | `worker_status` |
494
+ | `listByType`, `list_by_type` | `worker_list_by_type` |
495
+ | `listDocumentsByType` | `worker_list_docs_by_type` |
496
+ | `recall` | `worker_recall` |
497
+
498
+ `migrateDatabase` is listed in the map but throws
499
+ `IpcError(-32601, 'migrateDatabase is not yet
500
+ supported')` when called.
501
+
502
+ ## IPC API -- Daemon-State Methods
503
+
504
+ These methods are handled in TypeScript without WASM
505
+ calls.
506
+
507
+ ### `status`
508
+
509
+ Returns the daemon's current state.
510
+
511
+ ```json
512
+ // Request
513
+ {
514
+ "jsonrpc": "2.0",
515
+ "method": "status",
516
+ "params": { "ctx": "<context-id>" },
517
+ "id": 1
518
+ }
519
+
520
+ // Response
521
+ {
522
+ "jsonrpc": "2.0", "id": 1,
523
+ "result": "busy"
524
+ }
525
+ ```
526
+
527
+ Result: `"busy"` if the connection count is greater
528
+ than zero, `"idle"` otherwise.
529
+
530
+ ### `idle_at`
531
+
532
+ Returns the Unix timestamp (in seconds) when the last
533
+ transaction completed.
534
+
535
+ ```json
536
+ // Request
537
+ {
538
+ "jsonrpc": "2.0",
539
+ "method": "idle_at",
540
+ "params": { "ctx": "<context-id>" },
541
+ "id": 2
542
+ }
543
+
544
+ // Response
545
+ {
546
+ "jsonrpc": "2.0", "id": 2,
547
+ "result": 1750012800
548
+ }
549
+ ```
550
+
551
+ Result: integer (Unix epoch seconds). `0` if no
552
+ transaction has completed since startup.
553
+
554
+ ### `config_{key}`
555
+
556
+ Returns a configuration value. Method name is `config_`
557
+ followed by the TOML key name.
558
+
559
+ | Method | DaemonConfig property | Returns |
560
+ |----------------------|-----------------------|------------------------------|
561
+ | `config_timeout_ms` | `timeoutMs` | Daemon idle timeout in ms |
562
+ | `config_item_ttl_ms` | `itemTtlMs` | Per-item cache TTL in ms |
563
+ | `config_item_limit` | `itemLimit` | Max cached content objects |
564
+ | `config_index_limit` | `indexLimit` | Max cached index segments |
565
+
566
+ ```json
567
+ // Request
568
+ {
569
+ "jsonrpc": "2.0",
570
+ "method": "config_timeout_ms",
571
+ "params": { "ctx": "<context-id>" },
572
+ "id": 3
573
+ }
574
+
575
+ // Response
576
+ {
577
+ "jsonrpc": "2.0", "id": 3,
578
+ "result": 300000
579
+ }
580
+ ```
581
+
582
+ ### `checkVersion`
583
+
584
+ Reads `catalog.toml` from the given path (or the
585
+ daemon's own context path) and returns a version status
586
+ object. Does not require the daemon to be fully started.
587
+
588
+ **Request params:**
589
+
590
+ | Param | Type | Required | Description |
591
+ |--------------|--------|----------|-----------------------------------|
592
+ | `ctx` | string | yes | Context ID |
593
+ | `targetPath` | string | no | Path to read catalog from; defaults to `contextPath` |
594
+
595
+ **Response (`VersionStatus`):**
596
+
597
+ | Field | Type | Values |
598
+ |-------------------|--------|----------------------------------------------|
599
+ | `status` | string | `"compatible"` \| `"needs_migration"` \| `"too_new"` |
600
+ | `currentVersion` | number | Version found in catalog (0 if absent) |
601
+ | `requiredVersion` | number | `DB_FORMAT_VERSION` (currently `1`) |
602
+
603
+ ```json
604
+ // Request
605
+ {
606
+ "jsonrpc": "2.0",
607
+ "method": "checkVersion",
608
+ "params": { "ctx": "<context-id>" },
609
+ "id": 4
610
+ }
611
+
612
+ // Response
613
+ {
614
+ "jsonrpc": "2.0", "id": 4,
615
+ "result": {
616
+ "status": "compatible",
617
+ "currentVersion": 1,
618
+ "requiredVersion": 1
619
+ }
620
+ }
621
+ ```
622
+
623
+ ## IPC API -- WASM Read Methods
624
+
625
+ ### `search` / `query`
626
+
627
+ Submits a full-text search query. The daemon encodes
628
+ the params, calls `worker_search`, and decodes the
629
+ result synchronously. Returns a `ScoredResult[]` array.
630
+
631
+ **Request params:**
632
+
633
+ | Param | Type | Required | Description |
634
+ |----------|--------|----------|-------------------------------|
635
+ | `ctx` | string | yes | Context ID |
636
+ | `query` | string | yes | Query text |
637
+ | `mode` | string | no | `"and"` (default) or `"or"` |
638
+ | `limit` | number | no | Max results (default 20) |
639
+ | `offset` | number | no | Zero-based result offset (default 0) |
640
+
641
+ ```json
642
+ // Request
643
+ {
644
+ "jsonrpc": "2.0",
645
+ "method": "search",
646
+ "params": {
647
+ "ctx": "<context-id>",
648
+ "query": "TypeScript architecture",
649
+ "mode": "and",
650
+ "limit": 10
651
+ },
652
+ "id": 5
653
+ }
654
+
655
+ // Response
656
+ {
657
+ "jsonrpc": "2.0", "id": 5,
658
+ "result": {
659
+ "items": [
660
+ {
661
+ "kbid": "a1b2c3d4e5f6g7h8j9k0l1m2n3",
662
+ "heading": "Architecture Overview",
663
+ "type": "text/markdown",
664
+ "docids": ["doc-5678"],
665
+ "snippet": "The system is organized...",
666
+ "matched_terms": ["architecture", "system"],
667
+ "score": 8.7432
668
+ }
669
+ ],
670
+ "total": 42,
671
+ "offset": 0,
672
+ "limit": 20,
673
+ "has_more": true
674
+ }
675
+ }
676
+ ```
677
+
678
+ Note: the IPC layer keeps `score` (CLI uses it). The
679
+ MCP layer strips it.
680
+
681
+ Result: `PagedSearchResult` decoded from the WASM
682
+ binary return slot.
683
+
684
+ ### `get_result_status`
685
+
686
+ Checks the status of a previously submitted async
687
+ operation by its numeric token.
688
+
689
+ **Request params:**
690
+
691
+ | Param | Type | Description |
692
+ |---------|--------|------------------------|
693
+ | `ctx` | string | Context ID |
694
+ | `token` | number | Token from prior call |
695
+
696
+ ```json
697
+ // Request
698
+ {
699
+ "jsonrpc": "2.0",
700
+ "method": "get_result_status",
701
+ "params": { "ctx": "<context-id>", "token": 42 },
702
+ "id": 6
703
+ }
704
+
705
+ // Response
706
+ {
707
+ "jsonrpc": "2.0", "id": 6,
708
+ "result": { "status": 2 }
709
+ }
710
+ ```
711
+
712
+ Result: `{ status: number }` -- the raw status code
713
+ from `worker_result_status`.
714
+
715
+ ### `get_result`
716
+
717
+ Retrieves the result for a previously submitted async
718
+ operation by its numeric token. Decodes the return slot
719
+ as `ScoredResult[]`.
720
+
721
+ **Request params:**
722
+
723
+ | Param | Type | Description |
724
+ |---------|--------|------------------------|
725
+ | `ctx` | string | Context ID |
726
+ | `token` | number | Token from prior call |
727
+
728
+ ```json
729
+ // Request
730
+ {
731
+ "jsonrpc": "2.0",
732
+ "method": "get_result",
733
+ "params": { "ctx": "<context-id>", "token": 42 },
734
+ "id": 7
735
+ }
736
+
737
+ // Response
738
+ {
739
+ "jsonrpc": "2.0", "id": 7,
740
+ "result": [
741
+ { "kbid": "a1b2c3d4e5f6g7h8j9k0l1m2n3", "score": 0.95 }
742
+ ]
743
+ }
744
+ ```
745
+
746
+ ### `readSections` / `read_sections`
747
+
748
+ Reads multiple sections by kb-id. Returns an array of
749
+ `SectionRecord` objects decoded from the WASM binary.
750
+
751
+ **Request params:**
752
+
753
+ | Param | Type | Description |
754
+ |----------|----------|--------------------------------|
755
+ | `ctx` | string | Context ID |
756
+ | `kbids` | string[] | List of section IDs to read |
757
+
758
+ ```json
759
+ // Request
760
+ {
761
+ "jsonrpc": "2.0",
762
+ "method": "readSections",
763
+ "params": {
764
+ "ctx": "<context-id>",
765
+ "kbids": [
766
+ "a1b2c3d4e5f6g7h8j9k0l1m2n3",
767
+ "p4q5r6s7t8u9v0w1x2y3z4a5b6"
768
+ ]
769
+ },
770
+ "id": 8
771
+ }
772
+
773
+ // Response
774
+ {
775
+ "jsonrpc": "2.0", "id": 8,
776
+ "result": [
777
+ {
778
+ "kbid": "a1b2c3d4e5f6g7h8j9k0l1m2n3",
779
+ "docids": ["doc-5678"],
780
+ "type": "text/markdown",
781
+ "title": "Architecture Overview",
782
+ "description": "High-level overview",
783
+ "content": "Section body text..."
784
+ }
785
+ ]
786
+ }
787
+ ```
788
+
789
+ ### `recall`
790
+
791
+ Progressive context expansion for one or more
792
+ sections. Returns section content plus, depending
793
+ on the `depth` parameter, parent documents,
794
+ sibling sections, forward references, and
795
+ back-references from the reference graph index.
796
+
797
+ **Request params:**
798
+
799
+ | Param | Type | Required | Description |
800
+ |---------|----------|----------|--------------------------|
801
+ | `ctx` | string | yes | Context ID |
802
+ | `kbid` | string | no* | Single section ID |
803
+ | `kbids` | string[] | no* | Batch section IDs |
804
+ | `depth` | number | no | Expansion depth (0--3, default 0) |
805
+
806
+ *At least one of `kbid` or `kbids` required.
807
+
808
+ The daemon calls `worker_recall` in the WASM
809
+ engine, which reads sections, optionally looks up
810
+ parent documents, sibling sections, forward
811
+ references, and back-references from
812
+ `references.idx` depending on the requested depth.
813
+
814
+ Result: `RecallResult` (single) or
815
+ `RecallResult[]` (batch) decoded from the WASM
816
+ binary return slot.
817
+
818
+ ### `retrieveDocument` / `retrieve_doc`
819
+
820
+ Retrieves a document manifest by document ID. Returns
821
+ a decoded `DocumentManifest`.
822
+
823
+ **Request params:**
824
+
825
+ | Param | Type | Description |
826
+ |---------|--------|--------------------|
827
+ | `ctx` | string | Context ID |
828
+ | `docid` | string | Document ID |
829
+
830
+ ```json
831
+ // Request
832
+ {
833
+ "jsonrpc": "2.0",
834
+ "method": "retrieveDocument",
835
+ "params": {
836
+ "ctx": "<context-id>",
837
+ "docid": "doc-5678"
838
+ },
839
+ "id": 9
840
+ }
841
+
842
+ // Response (decoded DocumentManifest)
843
+ {
844
+ "jsonrpc": "2.0", "id": 9,
845
+ "result": { ... }
846
+ }
847
+ ```
848
+
849
+ ### `dbStatus` / `db_status`
850
+
851
+ Returns database status information. The WASM module
852
+ (`worker_status`) writes a key-value text block to the
853
+ return slot; the daemon decodes it and returns it as an
854
+ object.
855
+
856
+ **Request params:** `ctx` only.
857
+
858
+ ```json
859
+ // Request
860
+ {
861
+ "jsonrpc": "2.0",
862
+ "method": "dbStatus",
863
+ "params": { "ctx": "<context-id>" },
864
+ "id": 10
865
+ }
866
+
867
+ // Response (decoded key-value text)
868
+ {
869
+ "jsonrpc": "2.0", "id": 10,
870
+ "result": { "sections": "42", "documents": "5" }
871
+ }
872
+ ```
873
+
874
+ ### `listByType` / `list_by_type`
875
+
876
+ Returns all sections whose `sectionType` field
877
+ matches the given type string. The daemon encodes the
878
+ params, calls `worker_list_by_type`, and decodes the
879
+ result as an array of section records.
880
+
881
+ **Request params:**
882
+
883
+ | Param | Type | Required | Description |
884
+ |---------------|--------|----------|-----------------------------------|
885
+ | `ctx` | string | yes | Context ID |
886
+ | `sectionType` | string | yes | Section type to filter by |
887
+
888
+ ```json
889
+ // Request
890
+ {
891
+ "jsonrpc": "2.0",
892
+ "method": "listByType",
893
+ "params": {
894
+ "ctx": "<context-id>",
895
+ "sectionType": "skill"
896
+ },
897
+ "id": 23
898
+ }
899
+
900
+ // Response
901
+ {
902
+ "jsonrpc": "2.0", "id": 23,
903
+ "result": [
904
+ {
905
+ "kbid": "a1b2c3d4e5f6g7h8j9k0l1m2n3",
906
+ "docids": [],
907
+ "type": "skill",
908
+ "title": "summarize-document",
909
+ "description": "Summarize a document into
910
+ key points",
911
+ "content": "{\"name\":\"summarize-document\",...}"
912
+ }
913
+ ]
914
+ }
915
+ ```
916
+
917
+ Result: array of `SectionRecord` objects filtered by
918
+ the requested `sectionType`. Returns an empty array
919
+ when no sections match.
920
+
921
+ ### `listDocumentsByType`
922
+
923
+ Returns all document manifests whose `type` field
924
+ matches the given document type string. The daemon
925
+ encodes the params, calls `worker_list_docs_by_type`,
926
+ and decodes the result as an array of document
927
+ manifests.
928
+
929
+ **Request params:**
930
+
931
+ | Param | Type | Required | Description |
932
+ |-----------|--------|----------|------------------------------------|
933
+ | `ctx` | string | yes | Context ID |
934
+ | `docType` | string | yes | Document type to filter by |
935
+
936
+ ```json
937
+ // Request
938
+ {
939
+ "jsonrpc": "2.0",
940
+ "method": "listDocumentsByType",
941
+ "params": {
942
+ "ctx": "<context-id>",
943
+ "docType": "agent"
944
+ },
945
+ "id": 24
946
+ }
947
+
948
+ // Response
949
+ {
950
+ "jsonrpc": "2.0", "id": 24,
951
+ "result": [
952
+ {
953
+ "docid": "agent-code-reviewer",
954
+ "title": "Code Reviewer Agent",
955
+ "type": "agent",
956
+ "sections": [
957
+ { "kbid": "a1b2c3d4e5f6g7h8j9k0l1m2n3", "position": 0 },
958
+ { "kbid": "p4q5r6s7t8u9v0w1x2y3z4a5b6", "position": 1 }
959
+ ]
960
+ }
961
+ ]
962
+ }
963
+ ```
964
+
965
+ Result: array of document manifest objects filtered
966
+ by the requested `docType`. Returns an empty array
967
+ when no documents match. Documents without a `type`
968
+ field are regular documents and are not returned by
969
+ this method.
970
+
971
+ ## IPC API -- WASM Write Methods
972
+
973
+ ### `addSection` / `add_section`
974
+
975
+ Adds a new section to the database. The params are
976
+ binary-encoded and passed to `worker_add_section`. The
977
+ return slot contains the new section's kb-id as UTF-8.
978
+
979
+ **Request params:**
980
+
981
+ | Param | Type | Required | Description |
982
+ |---------------|--------|----------|-----------------------------------------------|
983
+ | `ctx` | string | yes | Context ID |
984
+ | `sectionType` | string | yes | Section type (`"text"`, `"image"`, `"code"`, etc.) |
985
+ | `mimeType` | string | no | MIME type |
986
+ | `content` | string | yes | Section content |
987
+ | `title` | string | no | Section title |
988
+ | `description` | string | no | Section description |
989
+ | `docid` | string | no | Document ID to attach this section to |
990
+
991
+ ```json
992
+ // Request
993
+ {
994
+ "jsonrpc": "2.0",
995
+ "method": "addSection",
996
+ "params": {
997
+ "ctx": "<context-id>",
998
+ "sectionType": "text",
999
+ "mimeType": "text/markdown",
1000
+ "content": "# Architecture\n\nOverview...",
1001
+ "title": "Architecture Overview",
1002
+ "docid": "doc-5678"
1003
+ },
1004
+ "id": 11
1005
+ }
1006
+
1007
+ // Response
1008
+ {
1009
+ "jsonrpc": "2.0", "id": 11,
1010
+ "result": { "kbid": "a1b2c3d4e5f6g7h8j9k0l1m2n3" }
1011
+ }
1012
+ ```
1013
+
1014
+ ### `updateSection` / `update_section`
1015
+
1016
+ Updates an existing section. The params are
1017
+ binary-encoded and passed to `worker_update_section`.
1018
+ Returns the new kb-id (content hash may change).
1019
+
1020
+ **Request params:**
1021
+
1022
+ | Param | Type | Required | Description |
1023
+ |---------------|--------|----------|----------------------------------------|
1024
+ | `ctx` | string | yes | Context ID |
1025
+ | `kbid` | string | yes | Existing section ID to replace |
1026
+ | `sectionType` | string | yes | New section type |
1027
+ | `mimeType` | string | no | New MIME type |
1028
+ | `content` | string | yes | New content |
1029
+ | `title` | string | no | New title |
1030
+ | `description` | string | no | New description |
1031
+ | `docid` | string | no | Document ID |
1032
+
1033
+ ```json
1034
+ // Request
1035
+ {
1036
+ "jsonrpc": "2.0",
1037
+ "method": "updateSection",
1038
+ "params": {
1039
+ "ctx": "<context-id>",
1040
+ "kbid": "a1b2c3d4e5f6g7h8j9k0l1m2n3",
1041
+ "sectionType": "text",
1042
+ "content": "Updated content...",
1043
+ "title": "Updated Title"
1044
+ },
1045
+ "id": 12
1046
+ }
1047
+
1048
+ // Response
1049
+ {
1050
+ "jsonrpc": "2.0", "id": 12,
1051
+ "result": { "kbid": "x9y8z7w6v5u4t3s2r1q0p9o8n7" }
1052
+ }
1053
+ ```
1054
+
1055
+ ### `removeSection` / `remove_section`
1056
+
1057
+ Removes a section by kb-id. The kb-id is UTF-8 encoded
1058
+ and passed to `worker_remove_section`. The return flag
1059
+ is decoded by `decodeRemoveFlag`.
1060
+
1061
+ **Request params:**
1062
+
1063
+ | Param | Type | Description |
1064
+ |---------|--------|-------------------------|
1065
+ | `ctx` | string | Context ID |
1066
+ | `kbid` | string | Section ID to remove |
1067
+
1068
+ ```json
1069
+ // Request
1070
+ {
1071
+ "jsonrpc": "2.0",
1072
+ "method": "removeSection",
1073
+ "params": {
1074
+ "ctx": "<context-id>",
1075
+ "kbid": "a1b2c3d4e5f6g7h8j9k0l1m2n3"
1076
+ },
1077
+ "id": 13
1078
+ }
1079
+
1080
+ // Response
1081
+ {
1082
+ "jsonrpc": "2.0", "id": 13,
1083
+ "result": { "removed": true }
1084
+ }
1085
+ ```
1086
+
1087
+ ### `groupSections` / `group_sections`
1088
+
1089
+ Groups a set of sections into a named document. Params
1090
+ are binary-encoded and passed to `worker_group_sections`.
1091
+ Returns the new document ID.
1092
+
1093
+ **Request params:**
1094
+
1095
+ | Param | Type | Description |
1096
+ |---------|----------|-----------------------------------|
1097
+ | `ctx` | string | Context ID |
1098
+ | `title` | string | Document title |
1099
+ | `kbids` | string[] | Section IDs to group |
1100
+
1101
+ ```json
1102
+ // Request
1103
+ {
1104
+ "jsonrpc": "2.0",
1105
+ "method": "groupSections",
1106
+ "params": {
1107
+ "ctx": "<context-id>",
1108
+ "title": "Architecture Guide",
1109
+ "kbids": [
1110
+ "a1b2c3d4e5f6g7h8j9k0l1m2n3",
1111
+ "p4q5r6s7t8u9v0w1x2y3z4a5b6"
1112
+ ]
1113
+ },
1114
+ "id": 14
1115
+ }
1116
+
1117
+ // Response
1118
+ {
1119
+ "jsonrpc": "2.0", "id": 14,
1120
+ "result": { "docid": "doc-5678" }
1121
+ }
1122
+ ```
1123
+
1124
+ ### `removeGrouping` / `remove_grouping`
1125
+
1126
+ Removes a document grouping (the manifest), leaving
1127
+ the underlying sections intact. The document ID is
1128
+ UTF-8 encoded and passed to `worker_remove_grouping`.
1129
+
1130
+ **Request params:**
1131
+
1132
+ | Param | Type | Description |
1133
+ |---------|--------|----------------------|
1134
+ | `ctx` | string | Context ID |
1135
+ | `docid` | string | Document ID to ungroup |
1136
+
1137
+ ```json
1138
+ // Request
1139
+ {
1140
+ "jsonrpc": "2.0",
1141
+ "method": "removeGrouping",
1142
+ "params": {
1143
+ "ctx": "<context-id>",
1144
+ "docid": "doc-5678"
1145
+ },
1146
+ "id": 15
1147
+ }
1148
+
1149
+ // Response
1150
+ {
1151
+ "jsonrpc": "2.0", "id": 15,
1152
+ "result": { "ok": true }
1153
+ }
1154
+ ```
1155
+
1156
+ ### `content` / `compose`
1157
+
1158
+ Composes a rendered Markdown document from one or more
1159
+ kbid or docid identifiers. The identifiers are
1160
+ binary-encoded and passed to `worker_compose`. The
1161
+ return slot is decoded by `decodeComposeOutput`.
1162
+
1163
+ **Request params:**
1164
+
1165
+ | Param | Type | Description |
1166
+ |---------|----------|----------------------------------------|
1167
+ | `ctx` | string | Context ID |
1168
+ | `ids` | string[] | kbids or docids to compose |
1169
+
1170
+ ```json
1171
+ // Request
1172
+ {
1173
+ "jsonrpc": "2.0",
1174
+ "method": "compose",
1175
+ "params": {
1176
+ "ctx": "<context-id>",
1177
+ "ids": [
1178
+ "a1b2c3d4e5f6g7h8j9k0l1m2n3",
1179
+ "doc-5678"
1180
+ ]
1181
+ },
1182
+ "id": 16
1183
+ }
1184
+
1185
+ // Response
1186
+ {
1187
+ "jsonrpc": "2.0", "id": 16,
1188
+ "result": {
1189
+ "data": "# Architecture Guide\n\n...",
1190
+ "total": 4096
1191
+ }
1192
+ }
1193
+ ```
1194
+
1195
+ Result fields:
1196
+
1197
+ | Field | Type | Description |
1198
+ |---------|--------|-----------------------------------------------|
1199
+ | `data` | string | Rendered Markdown string (`output.markdown`) |
1200
+ | `total` | number | Total character count (`output.totalChars`) |
1201
+
1202
+ ### `invalidate`
1203
+
1204
+ Evicts a single cached entry by kb-id. The kb-id is
1205
+ UTF-8 encoded and passed to `worker_invalidate`.
1206
+
1207
+ **Request params:**
1208
+
1209
+ | Param | Type | Description |
1210
+ |---------|--------|------------------------|
1211
+ | `ctx` | string | Context ID |
1212
+ | `kbid` | string | Section ID to evict |
1213
+
1214
+ ```json
1215
+ // Request
1216
+ {
1217
+ "jsonrpc": "2.0",
1218
+ "method": "invalidate",
1219
+ "params": {
1220
+ "ctx": "<context-id>",
1221
+ "kbid": "a1b2c3d4e5f6g7h8j9k0l1m2n3"
1222
+ },
1223
+ "id": 17
1224
+ }
1225
+
1226
+ // Response
1227
+ {
1228
+ "jsonrpc": "2.0", "id": 17,
1229
+ "result": { "ok": true }
1230
+ }
1231
+ ```
1232
+
1233
+ ### `invalidateAll` / `invalidate_all`
1234
+
1235
+ Evicts the entire WASM cache by calling
1236
+ `worker_invalidate_all` with no arguments.
1237
+
1238
+ **Request params:** `ctx` only.
1239
+
1240
+ ```json
1241
+ // Request
1242
+ {
1243
+ "jsonrpc": "2.0",
1244
+ "method": "invalidateAll",
1245
+ "params": { "ctx": "<context-id>" },
1246
+ "id": 18
1247
+ }
1248
+
1249
+ // Response
1250
+ {
1251
+ "jsonrpc": "2.0", "id": 18,
1252
+ "result": { "ok": true }
1253
+ }
1254
+ ```
1255
+
1256
+ ### `initDirectory` / `init_directory`
1257
+
1258
+ Initialises a new database directory. The path is
1259
+ UTF-8 encoded and passed to `worker_init_directory`.
1260
+ When `path` is omitted, the daemon uses its own
1261
+ `targetDir`.
1262
+
1263
+ **Request params:**
1264
+
1265
+ | Param | Type | Required | Description |
1266
+ |---------|--------|----------|----------------------------------------------|
1267
+ | `ctx` | string | yes | Context ID |
1268
+ | `path` | string | no | Path to initialise; defaults to `targetDir` |
1269
+
1270
+ ```json
1271
+ // Request
1272
+ {
1273
+ "jsonrpc": "2.0",
1274
+ "method": "initDirectory",
1275
+ "params": { "ctx": "<context-id>" },
1276
+ "id": 19
1277
+ }
1278
+
1279
+ // Response
1280
+ {
1281
+ "jsonrpc": "2.0", "id": 19,
1282
+ "result": { "ok": true }
1283
+ }
1284
+ ```
1285
+
1286
+ ## IPC API -- Maintenance Methods
1287
+
1288
+ Maintenance methods perform database-wide operations.
1289
+ They call WASM and return results directly.
1290
+
1291
+ ### `integrityCheck` / `integrity_check`
1292
+
1293
+ Verifies the integrity of the database. Calls
1294
+ `worker_check_integrity` with no arguments. The return
1295
+ slot contains a key-value text block decoded by
1296
+ `decodeKeyValueText`.
1297
+
1298
+ **Request params:** `ctx` only.
1299
+
1300
+ ```json
1301
+ // Request
1302
+ {
1303
+ "jsonrpc": "2.0",
1304
+ "method": "integrityCheck",
1305
+ "params": { "ctx": "<context-id>" },
1306
+ "id": 20
1307
+ }
1308
+
1309
+ // Response (decoded key-value text as object)
1310
+ {
1311
+ "jsonrpc": "2.0", "id": 20,
1312
+ "result": { "ok": "true", "sections_checked": "42" }
1313
+ }
1314
+ ```
1315
+
1316
+ ### `gc`
1317
+
1318
+ Removes section files not referenced by any document
1319
+ manifest. Calls `worker_garbage_collect` with no
1320
+ arguments. The return slot contains a key-value text
1321
+ block decoded by `decodeKeyValueText`.
1322
+
1323
+ **Request params:** `ctx` only.
1324
+
1325
+ ```json
1326
+ // Request
1327
+ {
1328
+ "jsonrpc": "2.0",
1329
+ "method": "gc",
1330
+ "params": { "ctx": "<context-id>" },
1331
+ "id": 21
1332
+ }
1333
+
1334
+ // Response (decoded key-value text as object)
1335
+ {
1336
+ "jsonrpc": "2.0", "id": 21,
1337
+ "result": { "removed_sections": "3", "removed_bytes": "15360" }
1338
+ }
1339
+ ```
1340
+
1341
+ ### `rebuildIndexes` / `rebuild_indexes`
1342
+
1343
+ Reconstructs all index files from section files and
1344
+ document manifests on disk. Calls
1345
+ `worker_rebuild_indexes` with no arguments. Returns
1346
+ `{ ok: true }` on success.
1347
+
1348
+ **Request params:** `ctx` only.
1349
+
1350
+ ```json
1351
+ // Request
1352
+ {
1353
+ "jsonrpc": "2.0",
1354
+ "method": "rebuildIndexes",
1355
+ "params": { "ctx": "<context-id>" },
1356
+ "id": 22
1357
+ }
1358
+
1359
+ // Response
1360
+ {
1361
+ "jsonrpc": "2.0", "id": 22,
1362
+ "result": { "ok": true }
1363
+ }
1364
+ ```
1365
+
1366
+ ## Error Responses
1367
+
1368
+ JSON-RPC 2.0 error format for invalid requests:
1369
+
1370
+ ```json
1371
+ {
1372
+ "jsonrpc": "2.0", "id": 11,
1373
+ "error": {
1374
+ "code": -32601,
1375
+ "message": "Method not found: unknownMethod"
1376
+ }
1377
+ }
1378
+ ```
1379
+
1380
+ Standard JSON-RPC 2.0 error codes apply. Application
1381
+ errors use codes in the `-32000` to `-32099` range:
1382
+
1383
+ | Code | Meaning |
1384
+ |----------|--------------------------------------|
1385
+ | `-32001` | Context mismatch |
1386
+ | `-32700` | Parse error (malformed JSON line) |
1387
+ | `-32601` | Method not found |
1388
+ | `-32000` | WASM call error (message from WASM) |
1389
+
1390
+ Startup errors (`-32004` through `-32007` in previous
1391
+ versions of this document) are not returned over IPC
1392
+ because the daemon exits before creating the IPC
1393
+ socket. They are communicated via stderr and the crash
1394
+ log.
1395
+
1396
+ ## Source Files
1397
+
1398
+ The worker daemon module lives in
1399
+ `src/shared/worker-daemon/` with the following
1400
+ structure:
1401
+
1402
+ ```
1403
+ src/shared/worker-daemon/
1404
+ classes/
1405
+ worker-daemon.class.ts # WorkerDaemon class
1406
+ functions/
1407
+ create-host-imports.function.ts # WASM host I/O imports
1408
+ create-ipc-server.function.ts # IPC socket server
1409
+ load-wasm-modules.function.ts # WASM compilation/instantiation
1410
+ read-config.function.ts # worker.toml parser
1411
+ run-worker.function.ts # entry-point logic
1412
+ start-daemon.function.ts # startup orchestration
1413
+ constants/
1414
+ daemon-defaults.constant.ts # defaults + DB_FORMAT_VERSION
1415
+ typings/
1416
+ daemon-config.interface.ts # DaemonConfig
1417
+ ipc-handler.interface.ts # IpcRequest, IpcResponse, IpcHandler
1418
+ wasm-modules.interface.ts # WasmModules
1419
+ wasm/
1420
+ kb-worker/
1421
+ kbdb_worker_bg.wasm # compiled WASM (gitignored)
1422
+ ```
1423
+
1424
+ The `run-worker.function.ts` implements the entry-point
1425
+ logic (argument validation and calling `startDaemon`).
1426
+ The `start-daemon.function.ts` orchestrates the full
1427
+ startup sequence: reads config, computes the context ID,
1428
+ constructs `WorkerDaemon`, checks preconditions, starts
1429
+ the daemon, and installs signal handlers.
1430
+
1431
+ ## Distribution
1432
+
1433
+ The worker daemon (`src/worker.ts` and its compiled
1434
+ `kbdb-worker.js`) ships as part of the npm/JSR package.
1435
+ No per-platform native binaries are required.
1436
+
1437
+ The package includes one WASM module:
1438
+
1439
+ - `kb-worker/kbdb_worker_bg.wasm` -- single module
1440
+ that statically links the query-parser and
1441
+ fs-database crates
1442
+
1443
+ It is compiled from Rust via `wasm-pack` and works on
1444
+ all platforms. The daemon loads and compiles it at
1445
+ startup using the runtime's `WebAssembly` API. The
1446
+ daemon runs on the same runtime (Node.js or Deno) as
1447
+ the worker client that spawns it.