@dikolab/kbdb 0.4.3 → 0.6.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 (224) hide show
  1. package/CLA.md +68 -0
  2. package/LICENSE +676 -12
  3. package/LICENSING.md +58 -0
  4. package/README.md +50 -27
  5. package/README.md.bak +320 -0
  6. package/dist/README.md +320 -0
  7. package/dist/{chunk-BJXEVALU.mjs → chunk-QLJ33C74.mjs} +44 -44
  8. package/dist/chunk-QLJ33C74.mjs.map +7 -0
  9. package/dist/cli.cjs +550 -232
  10. package/dist/cli.cjs.map +4 -4
  11. package/dist/cli.d.ts +0 -8
  12. package/dist/cli.mjs +483 -154
  13. package/dist/cli.mjs.map +4 -4
  14. package/dist/kbdb-worker.cjs +36 -5
  15. package/dist/kbdb-worker.cjs.map +3 -3
  16. package/dist/mod.cjs +89 -30
  17. package/dist/mod.cjs.map +4 -4
  18. package/dist/mod.mjs +88 -30
  19. package/dist/mod.mjs.map +4 -4
  20. package/dist/src/cli.d.ts +0 -8
  21. package/dist/src/shared/cli/constants/defaults.constant.d.ts +1 -1
  22. package/dist/src/shared/cli/constants/recfile-command-field-map.constant.d.ts +8 -0
  23. package/dist/src/shared/cli/constants/recfile-field-maps.constant.d.ts +21 -0
  24. package/dist/src/shared/cli/functions/compute-directory-level.function.d.ts +14 -0
  25. package/dist/src/shared/cli/functions/dispatch-command.function.d.ts +2 -28
  26. package/dist/src/shared/cli/functions/format-command-output.function.d.ts +14 -0
  27. package/dist/src/shared/cli/functions/format-db-not-found.function.d.ts +20 -0
  28. package/dist/src/shared/cli/functions/format-output.function.d.ts +1 -0
  29. package/dist/src/shared/cli/functions/format-recfile-output.function.d.ts +11 -0
  30. package/dist/src/shared/cli/functions/render-recfile-value.function.d.ts +11 -0
  31. package/dist/src/shared/cli/functions/resolve-db-dir.function.d.ts +24 -0
  32. package/dist/src/shared/cli/functions/resolve-recfile-key.function.d.ts +9 -0
  33. package/dist/src/shared/cli/functions/run-db-path.function.d.ts +10 -0
  34. package/dist/src/shared/cli/functions/run-export.function.d.ts +8 -4
  35. package/dist/src/shared/cli/functions/run-import.function.d.ts +4 -0
  36. package/dist/src/shared/cli/functions/run-learn.function.d.ts +12 -0
  37. package/dist/src/shared/cli/index.d.ts +4 -1
  38. package/dist/src/shared/cli/typings/cli-options.interface.d.ts +9 -2
  39. package/dist/src/shared/cli/typings/db-resolution.interface.d.ts +9 -0
  40. package/dist/src/shared/cli/typings/recfile-field-map.type.d.ts +10 -0
  41. package/dist/src/shared/version/constants/version.constant.d.ts +1 -1
  42. package/dist/src/shared/wasm-codec/functions/decode-option-u8.function.d.ts +9 -0
  43. package/dist/src/shared/wasm-codec/functions/decode-section-records.function.d.ts +4 -0
  44. package/dist/src/shared/wasm-codec/functions/encode-add-section-params.function.d.ts +2 -45
  45. package/dist/src/shared/wasm-codec/functions/encode-update-section-params.function.d.ts +10 -1
  46. package/dist/src/shared/wasm-codec/index.d.ts +1 -1
  47. package/dist/src/shared/wasm-codec/typings/add-section-input.model.d.ts +6 -0
  48. package/dist/src/shared/wasm-codec/typings/section-record-trailing.model.d.ts +5 -0
  49. package/dist/src/shared/wasm-codec/typings/section-record.model.d.ts +5 -0
  50. package/dist/src/shared/worker-client/functions/build-deno-permissions.function.d.ts +11 -0
  51. package/dist/src/shared/worker-client/functions/read-crash-reason.function.d.ts +9 -0
  52. package/dist/src/shared/worker-client/functions/resolve-spawn-script.function.d.ts +6 -0
  53. package/dist/src/shared/worker-client/functions/spawn-daemon.function.d.ts +1 -1
  54. package/dist/src/shared/worker-client/typings/section.model.d.ts +5 -0
  55. package/dist/src/shared/worker-client/typings/worker-client-options.interface.d.ts +0 -6
  56. package/dist/src/shared/worker-daemon/functions/count-files.function.d.ts +12 -0
  57. package/dist/src/shared/worker-daemon/functions/handle-import.function.d.ts +2 -0
  58. package/dist/src/shared/worker-daemon/functions/handle-read-ops.function.d.ts +8 -0
  59. package/dist/src/shared/worker-daemon/functions/validate-daemon-path.function.d.ts +15 -0
  60. package/dist/src/worker.d.ts +0 -7
  61. package/dist/wasm/default-embedding/kbdb_default_embedding_bg.wasm +0 -0
  62. package/dist/wasm/default-embedding/package.json +1 -1
  63. package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
  64. package/dist/wasm/fs-database/package.json +1 -1
  65. package/dist/wasm/fs-migration/kbdb_fs_migration_bg.wasm +0 -0
  66. package/dist/wasm/fs-migration/package.json +1 -1
  67. package/dist/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
  68. package/dist/wasm/kb-worker/package.json +1 -1
  69. package/dist/wasm/query-parser/kbdb_query_parser_bg.wasm +0 -0
  70. package/dist/wasm/query-parser/package.json +1 -1
  71. package/dist/worker.d.ts +0 -7
  72. package/dist/worker.mjs +37 -6
  73. package/dist/worker.mjs.map +3 -3
  74. package/package.json +13 -12
  75. package/dist/chunk-BJXEVALU.mjs.map +0 -7
  76. package/dist/src/shared/cli/functions/resolve-raw-db-path.function.d.ts +0 -10
  77. package/docs/details/README.md +0 -30
  78. package/docs/details/agent-tooling.md +0 -132
  79. package/docs/details/cli.md +0 -777
  80. package/docs/details/knowledge-base.md +0 -180
  81. package/docs/details/library-api.md +0 -495
  82. package/docs/details/mcp-server.md +0 -482
  83. package/docs/details/search-and-ranking.md +0 -575
  84. package/docs/details/storage.md +0 -531
  85. package/docs/goals/agents.md +0 -751
  86. package/docs/goals/architecture.svg +0 -198
  87. package/docs/goals/auto-capture.md +0 -378
  88. package/docs/goals/benchmarking.md +0 -296
  89. package/docs/goals/cli.md +0 -2654
  90. package/docs/goals/concurrency.md +0 -259
  91. package/docs/goals/content-composer.md +0 -609
  92. package/docs/goals/content-parser.md +0 -279
  93. package/docs/goals/database.md +0 -1679
  94. package/docs/goals/document.md +0 -368
  95. package/docs/goals/hybrid-search.md +0 -465
  96. package/docs/goals/mcp.md +0 -1541
  97. package/docs/goals/overview.md +0 -124
  98. package/docs/goals/query-parser.md +0 -373
  99. package/docs/goals/query-result.md +0 -860
  100. package/docs/goals/semantic-dedup.md +0 -233
  101. package/docs/goals/skills.md +0 -810
  102. package/docs/goals/sync.md +0 -217
  103. package/docs/goals/worker-client.md +0 -1005
  104. package/docs/goals/worker-daemon.md +0 -1547
  105. package/docs/modules/overview.md +0 -319
  106. package/docs/modules/rust/embedding/module.md +0 -91
  107. package/docs/modules/rust/fs-database/functions/document.md +0 -48
  108. package/docs/modules/rust/fs-database/functions/integrity.md +0 -79
  109. package/docs/modules/rust/fs-database/functions/io.md +0 -87
  110. package/docs/modules/rust/fs-database/functions/module.md +0 -22
  111. package/docs/modules/rust/fs-database/functions/query-exec.md +0 -44
  112. package/docs/modules/rust/fs-database/functions/section.md +0 -76
  113. package/docs/modules/rust/fs-database/indexes/btree.md +0 -35
  114. package/docs/modules/rust/fs-database/indexes/corpus.md +0 -61
  115. package/docs/modules/rust/fs-database/indexes/inverted.md +0 -60
  116. package/docs/modules/rust/fs-database/indexes/module.md +0 -64
  117. package/docs/modules/rust/fs-database/indexes/positional.md +0 -39
  118. package/docs/modules/rust/fs-database/indexes/vectors.md +0 -110
  119. package/docs/modules/rust/fs-database/module.md +0 -150
  120. package/docs/modules/rust/fs-database/types/catalog.md +0 -53
  121. package/docs/modules/rust/fs-database/types/module.md +0 -12
  122. package/docs/modules/rust/fs-database/types/section.md +0 -127
  123. package/docs/modules/rust/kb-worker/functions/compose.md +0 -57
  124. package/docs/modules/rust/kb-worker/functions/module.md +0 -20
  125. package/docs/modules/rust/kb-worker/functions/retrieve.md +0 -194
  126. package/docs/modules/rust/kb-worker/functions/search.md +0 -173
  127. package/docs/modules/rust/kb-worker/functions/write.md +0 -172
  128. package/docs/modules/rust/kb-worker/module.md +0 -171
  129. package/docs/modules/rust/kb-worker/types/cache.md +0 -90
  130. package/docs/modules/rust/kb-worker/types/context.md +0 -26
  131. package/docs/modules/rust/kb-worker/types/module.md +0 -16
  132. package/docs/modules/rust/kb-worker/types/status.md +0 -29
  133. package/docs/modules/rust/kb-worker/types/token.md +0 -50
  134. package/docs/modules/rust/overview.md +0 -531
  135. package/docs/modules/rust/query-parser/functions/extract.md +0 -56
  136. package/docs/modules/rust/query-parser/functions/module.md +0 -18
  137. package/docs/modules/rust/query-parser/functions/parse.md +0 -33
  138. package/docs/modules/rust/query-parser/functions/pipeline.md +0 -9
  139. package/docs/modules/rust/query-parser/functions/rank.md +0 -85
  140. package/docs/modules/rust/query-parser/module.md +0 -131
  141. package/docs/modules/rust/query-parser/types/cache.md +0 -39
  142. package/docs/modules/rust/query-parser/types/keyphrase.md +0 -71
  143. package/docs/modules/rust/query-parser/types/module.md +0 -18
  144. package/docs/modules/rust/query-parser/types/token.md +0 -46
  145. package/docs/modules/rust/shared/content-composer/functions.md +0 -114
  146. package/docs/modules/rust/shared/content-composer/module.md +0 -147
  147. package/docs/modules/rust/shared/content-composer/types.md +0 -93
  148. package/docs/modules/rust/shared/content-parser/functions.md +0 -72
  149. package/docs/modules/rust/shared/content-parser/module.md +0 -99
  150. package/docs/modules/rust/shared/content-parser/types.md +0 -71
  151. package/docs/modules/rust/shared/corpus/module.md +0 -24
  152. package/docs/modules/rust/shared/corpus/types.md +0 -141
  153. package/docs/modules/rust/shared/document/module.md +0 -25
  154. package/docs/modules/rust/shared/document/types.md +0 -154
  155. package/docs/modules/rust/shared/encode/module.md +0 -22
  156. package/docs/modules/rust/shared/encode/traits.md +0 -304
  157. package/docs/modules/rust/shared/error/module.md +0 -28
  158. package/docs/modules/rust/shared/error/types.md +0 -302
  159. package/docs/modules/rust/shared/kbid/module.md +0 -24
  160. package/docs/modules/rust/shared/kbid/types.md +0 -147
  161. package/docs/modules/rust/shared/memory/functions.md +0 -209
  162. package/docs/modules/rust/shared/memory/module.md +0 -24
  163. package/docs/modules/rust/shared/module.md +0 -196
  164. package/docs/modules/rust/shared/pipeline/functions.md +0 -141
  165. package/docs/modules/rust/shared/pipeline/module.md +0 -62
  166. package/docs/modules/rust/shared/pipeline/types.md +0 -43
  167. package/docs/modules/rust/shared/query/module.md +0 -27
  168. package/docs/modules/rust/shared/query/types.md +0 -236
  169. package/docs/modules/rust/shared/section/module.md +0 -25
  170. package/docs/modules/rust/shared/section/types.md +0 -294
  171. package/docs/modules/rust/shared/term/module.md +0 -25
  172. package/docs/modules/rust/shared/term/types.md +0 -139
  173. package/docs/modules/typescript/cli.md +0 -131
  174. package/docs/modules/typescript/kbdb-worker.md +0 -150
  175. package/docs/modules/typescript/overview.md +0 -400
  176. package/docs/modules/typescript/shared/auto-capture/module.md +0 -73
  177. package/docs/modules/typescript/shared/cli/constants.md +0 -23
  178. package/docs/modules/typescript/shared/cli/functions.md +0 -809
  179. package/docs/modules/typescript/shared/cli/module.md +0 -138
  180. package/docs/modules/typescript/shared/cli/typings.md +0 -197
  181. package/docs/modules/typescript/shared/embedding/functions.md +0 -200
  182. package/docs/modules/typescript/shared/embedding/module.md +0 -77
  183. package/docs/modules/typescript/shared/embedding/typings.md +0 -124
  184. package/docs/modules/typescript/shared/hash/functions.md +0 -20
  185. package/docs/modules/typescript/shared/hash/module.md +0 -21
  186. package/docs/modules/typescript/shared/log/constants.md +0 -82
  187. package/docs/modules/typescript/shared/log/functions.md +0 -131
  188. package/docs/modules/typescript/shared/log/module.md +0 -153
  189. package/docs/modules/typescript/shared/log/typings.md +0 -82
  190. package/docs/modules/typescript/shared/mcp/classes.md +0 -179
  191. package/docs/modules/typescript/shared/mcp/functions.md +0 -386
  192. package/docs/modules/typescript/shared/mcp/module.md +0 -160
  193. package/docs/modules/typescript/shared/mcp/typings.md +0 -529
  194. package/docs/modules/typescript/shared/module.md +0 -110
  195. package/docs/modules/typescript/shared/platform/functions.md +0 -42
  196. package/docs/modules/typescript/shared/platform/module.md +0 -25
  197. package/docs/modules/typescript/shared/runtime/functions.md +0 -26
  198. package/docs/modules/typescript/shared/runtime/module.md +0 -27
  199. package/docs/modules/typescript/shared/runtime/typings.md +0 -13
  200. package/docs/modules/typescript/shared/version/module.md +0 -27
  201. package/docs/modules/typescript/shared/wasm-codec/functions.md +0 -391
  202. package/docs/modules/typescript/shared/wasm-codec/module.md +0 -98
  203. package/docs/modules/typescript/shared/worker-client/classes.md +0 -264
  204. package/docs/modules/typescript/shared/worker-client/functions.md +0 -175
  205. package/docs/modules/typescript/shared/worker-client/module.md +0 -92
  206. package/docs/modules/typescript/shared/worker-client/typings.md +0 -511
  207. package/docs/modules/typescript/shared/worker-daemon/classes.md +0 -239
  208. package/docs/modules/typescript/shared/worker-daemon/constants.md +0 -37
  209. package/docs/modules/typescript/shared/worker-daemon/functions.md +0 -234
  210. package/docs/modules/typescript/shared/worker-daemon/module.md +0 -118
  211. package/docs/modules/typescript/shared/worker-daemon/typings.md +0 -132
  212. package/docs/overview.md +0 -191
  213. package/docs/release-notes/0.1.0.md +0 -189
  214. package/docs/release-notes/0.1.1.md +0 -46
  215. package/docs/release-notes/0.1.2.md +0 -38
  216. package/docs/release-notes/0.1.3.md +0 -42
  217. package/docs/release-notes/0.2.0.md +0 -147
  218. package/docs/release-notes/0.3.0.md +0 -89
  219. package/docs/release-notes/0.3.1.md +0 -121
  220. package/docs/release-notes/0.3.2.md +0 -64
  221. package/docs/release-notes/0.4.0.md +0 -80
  222. package/docs/release-notes/0.4.1.md +0 -149
  223. package/docs/release-notes/0.4.3.md +0 -60
  224. package/docs/release-notes/README.md +0 -13
@@ -1,259 +0,0 @@
1
- # Concurrent Write Safety
2
-
3
- *One writer at a time, unlimited concurrent readers --
4
- formalizing the locking model, multi-daemon prevention,
5
- crash recovery, and stress-test methodology.*
6
-
7
- ## Goal
8
-
9
- The worker daemon serializes all write operations
10
- through a single-writer lock. Multiple concurrent
11
- readers proceed without any lock. This document
12
- formalizes the locking model, multi-daemon prevention,
13
- atomic write guarantees, crash recovery, and
14
- stress-test methodology.
15
-
16
- This goal addresses gap #3 from the issue
17
- [2026-06-23 Opus 4.8 Second Brain Review](../issues/2026-06-23-opus-48-second-brain-review.md):
18
- the single-writer lock in the worker daemon must be
19
- validated under concurrent load before concurrent
20
- multi-agent use can be trusted.
21
-
22
- ## Single-Writer Lock
23
-
24
- The daemon acquires an exclusive file lock on
25
- `kbdb-{ctx}.lock` in the OS temporary directory during
26
- write operations. The lock file uses the same context
27
- ID as the PID file and IPC socket (see
28
- [Worker Daemon](worker-daemon.md) for context ID
29
- derivation).
30
-
31
- - **Read operations** -- search, recall, retrieve,
32
- content, dbStatus, and listByType -- proceed without
33
- acquiring the lock. Concurrent read requests from
34
- multiple worker client connections are fully parallel.
35
- - **Write operations** -- addSection, updateSection,
36
- removeSection, groupSections, removeGrouping,
37
- initDirectory, gc, rebuildIndexes, and export --
38
- acquire the exclusive lock before calling the
39
- corresponding WASM export. If another write is
40
- already in progress, the new write queues behind the
41
- lock and waits.
42
- - The lock is held only for the duration of a single
43
- write operation. It is released immediately after
44
- the operation completes. It is never held across
45
- multiple operations or across client connections.
46
- - The locking model is implemented in TypeScript inside
47
- the worker daemon (`src/shared/worker-daemon/`), not
48
- inside any WASM module.
49
-
50
- This model is equivalent to SQLite's default locking:
51
- readers never block, and writers take turns one at a
52
- time.
53
-
54
- ### Write Operations Subject to the Lock
55
-
56
- | IPC Method | WASM Export |
57
- |--------------------------|----------------------------|
58
- | `addSection` | `worker_add_section` |
59
- | `updateSection` | `worker_update_section` |
60
- | `removeSection` | `worker_remove_section` |
61
- | `groupSections` | `worker_group_sections` |
62
- | `removeGrouping` | `worker_remove_grouping` |
63
- | `initDirectory` | `worker_init_directory` |
64
- | `gc` | `worker_garbage_collect` |
65
- | `rebuildIndexes` | `worker_rebuild_indexes` |
66
- | `export` | `db_export` |
67
-
68
- ## Multi-Daemon Prevention
69
-
70
- Each database context gets exactly one daemon process
71
- at a time, enforced by a PID file keyed to the context
72
- ID.
73
-
74
- - The PID file is named `kbdb-{ctx}.pid` and lives in
75
- the OS temporary directory. Its presence means a
76
- daemon for that context is either running or died
77
- without cleaning up.
78
- - Before spawning a new daemon, the worker client reads
79
- the PID file (if present) and checks whether the
80
- recorded process is alive.
81
- - **PID file absent** -- no running daemon; spawn a
82
- new one.
83
- - **PID file present, process alive** -- connect to
84
- the existing daemon; do not spawn.
85
- - **PID file present, process dead** -- stale PID
86
- file from a prior crash; remove the file and spawn
87
- a new daemon.
88
- - The daemon writes its PID file only after all startup
89
- preconditions pass and the WASM module is loaded
90
- successfully. See [Worker Daemon](worker-daemon.md)
91
- for the full startup sequence.
92
- - On graceful shutdown, the daemon removes its PID
93
- file before exiting.
94
-
95
- This protocol ensures that the same database directory
96
- is never served by two concurrent daemon processes.
97
-
98
- ## Atomic Write Guarantees
99
-
100
- All file writes in the database use the atomic
101
- write pattern: content is written to a temporary file
102
- first, then the temporary file is renamed to the final
103
- path. Rename is an atomic operation on all supported
104
- filesystems (POSIX and Windows NTFS).
105
-
106
- - **Section files** (`sections/{prefix}/{kbid}.sec`)
107
- are written to `sections/{prefix}/{kbid}.sec.tmp`
108
- then renamed.
109
- - **Document manifests** (`documents/{docid}.toml`)
110
- are written to `documents/{docid}.toml.tmp` then
111
- renamed.
112
- - **Index files** (`indexes/terms.idx`, etc.) are
113
- rebuilt to temporary paths then renamed into place.
114
- - **Catalog** (`catalog.toml`) is written last,
115
- after all data files are in place. A crash
116
- before the catalog rename leaves the catalog
117
- consistent with the previous complete state.
118
-
119
- If the daemon crashes mid-write, the temporary file
120
- is orphaned but the original file is intact. On next
121
- daemon startup, orphaned temporary files (matching
122
- `*.tmp`) in the database directory are cleaned up.
123
-
124
- The atomic write pattern is specified in
125
- [Database](database.md) under Storage Design.
126
-
127
- ## Crash Recovery
128
-
129
- The table below describes every identified failure
130
- scenario, the resulting disk state, and the recovery
131
- action.
132
-
133
- | Scenario | State After Crash | Recovery |
134
- |---|---|---|
135
- | Crash during section write | `*.sec.tmp` orphaned, original `.sec` intact | Startup cleans `*.tmp` files |
136
- | Crash during index rebuild | Partial `*.idx.tmp`, originals intact | Startup cleans `*.tmp`; next `rebuildIndexes` overwrites |
137
- | Crash during GC | Some unreferenced sections deleted, others not | Re-run `gc`; idempotent |
138
- | Crash during catalog write | `catalog.toml.tmp` orphaned, original intact | Startup cleans `*.tmp` |
139
- | PID file not removed | Stale `kbdb-{ctx}.pid` on disk | Worker client detects dead process, removes PID, spawns new daemon |
140
- | Lock file not released | `kbdb-{ctx}.lock` orphaned | Daemon startup acquires the exclusive lock fresh; OS releases orphaned file locks when the process that held them exits |
141
- | WASM crash inside write | Partial in-memory state, temp file may exist | Daemon exits; startup cleans `*.tmp`; next operation starts clean |
142
-
143
- All recovery actions are automatic. No manual
144
- intervention is required for any scenario in this
145
- table.
146
-
147
- ## Stress Test Specification
148
-
149
- The following test harness validates concurrent write
150
- safety. It must pass on both Deno and Node.js runtimes
151
- before a release can claim concurrent safety.
152
-
153
- ### Setup
154
-
155
- 1. Create a fresh, empty database directory.
156
- 2. Prepare N unique documents (N in the range 10--50).
157
- Each document must have distinct content to avoid
158
- content-address collisions that would make section
159
- count verification meaningless.
160
-
161
- ### Execution
162
-
163
- 3. Launch N concurrent `kbdb learn` invocations, all
164
- targeting the same database directory. Each
165
- invocation learns one of the N unique documents.
166
- 4. Use a process pool or parallel shell to launch all
167
- N invocations simultaneously -- not sequentially.
168
- 5. Wait for all N invocations to complete. Record any
169
- non-zero exit codes as failures.
170
-
171
- ### Verification
172
-
173
- 6. Run `kbdb check` against the database.
174
- The response must have `ok: true`. Any errors in the
175
- response are test failures.
176
- 7. Query the section count. The count must equal the
177
- expected number of sections derived from the N
178
- documents (no duplicates from race conditions, no
179
- losses from interleaved writes).
180
- 8. Verify that no section has a checksum mismatch.
181
- A mismatch indicates a torn write -- the atomic
182
- rename pattern failed or was bypassed.
183
-
184
- ### Pass Criteria
185
-
186
- | Check | Expected Result |
187
- |---|---|
188
- | All `kbdb learn` exit codes | `0` |
189
- | `kbdb check` response | `ok: true`, zero errors |
190
- | Section count | Exactly the expected count |
191
- | Checksum mismatches | Zero |
192
-
193
- ### Runtime Matrix
194
-
195
- Run the full harness on both runtimes:
196
-
197
- | Runtime | Command prefix |
198
- |---|---|
199
- | Node.js >= 20 | `node dist/kbdb.mjs` |
200
- | Deno | `deno run --allow-all src/cli.ts` |
201
-
202
- Both must pass. A failure on one runtime but not the
203
- other indicates a runtime-specific locking bug.
204
-
205
- ## Edge Cases
206
-
207
- ### Two CLI Invocations Through the Same Daemon
208
-
209
- When two `kbdb` CLI processes connect to the same
210
- daemon (same database directory), their write requests
211
- share the single-writer lock automatically. No user
212
- action is required. The second write waits for the
213
- first to complete.
214
-
215
- ### MCP Server Connections
216
-
217
- An MCP server connection routes all requests through
218
- a worker client to the daemon, the same as a CLI
219
- invocation. Multiple MCP client connections routed to
220
- the same daemon share the write lock:
221
-
222
- - Concurrent read requests from multiple MCP clients
223
- are served in parallel.
224
- - Concurrent write requests from multiple MCP clients
225
- are serialized through the lock one at a time.
226
-
227
- There is no per-connection or per-client lock; the
228
- lock is global to the daemon process.
229
-
230
- ### Direct File Access
231
-
232
- Accessing or modifying `.kbdb` files directly -- via
233
- text editor, shell commands, or any process other than
234
- the daemon -- is not supported. Direct writes bypass
235
- the single-writer lock and the atomic write pattern,
236
- and may corrupt the database. All mutations must go
237
- through the daemon's IPC API.
238
-
239
- ## Design Constraints
240
-
241
- - **Per-daemon locking, not per-file** -- The lock
242
- covers all writes to a database context, not writes
243
- to individual files. This means writes to unrelated
244
- sections still serialize behind the same lock. The
245
- simplicity of a single lock outweighs the throughput
246
- cost at current scale. If per-section parallelism
247
- becomes necessary, this constraint is the place to
248
- revisit.
249
- - **Single-machine only** -- The locking model
250
- relies on OS-level file locks and process identity
251
- on a single machine. It provides no guarantees across
252
- network filesystems or multiple machines. Cross-machine
253
- scenarios require an external sync mechanism (see
254
- [Sync](sync.md) when available).
255
- - **Lock implemented in TypeScript** -- The write lock
256
- is managed by the TypeScript worker daemon layer, not
257
- by any WASM module. WASM modules have no knowledge of
258
- concurrent callers; they process one call at a time
259
- through the host.