@dikolab/kbdb 0.5.0 → 0.6.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 (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 -25
  5. package/README.md.bak +322 -0
  6. package/dist/README.md +322 -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/package.json +1 -1
  66. package/dist/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
  67. package/dist/wasm/kb-worker/package.json +1 -1
  68. package/dist/wasm/query-parser/kbdb_query_parser_bg.wasm +0 -0
  69. package/dist/wasm/query-parser/package.json +1 -1
  70. package/dist/worker.d.ts +0 -7
  71. package/dist/worker.mjs +37 -6
  72. package/dist/worker.mjs.map +3 -3
  73. package/package.json +11 -10
  74. package/dist/chunk-BJXEVALU.mjs.map +0 -7
  75. package/dist/src/shared/cli/functions/resolve-raw-db-path.function.d.ts +0 -10
  76. package/docs/details/README.md +0 -30
  77. package/docs/details/agent-tooling.md +0 -132
  78. package/docs/details/cli.md +0 -777
  79. package/docs/details/knowledge-base.md +0 -180
  80. package/docs/details/library-api.md +0 -495
  81. package/docs/details/mcp-server.md +0 -482
  82. package/docs/details/search-and-ranking.md +0 -575
  83. package/docs/details/storage.md +0 -531
  84. package/docs/goals/agents.md +0 -751
  85. package/docs/goals/architecture.svg +0 -198
  86. package/docs/goals/auto-capture.md +0 -378
  87. package/docs/goals/benchmarking.md +0 -296
  88. package/docs/goals/cli.md +0 -2654
  89. package/docs/goals/concurrency.md +0 -259
  90. package/docs/goals/content-composer.md +0 -609
  91. package/docs/goals/content-parser.md +0 -279
  92. package/docs/goals/database.md +0 -1679
  93. package/docs/goals/document.md +0 -368
  94. package/docs/goals/hybrid-search.md +0 -465
  95. package/docs/goals/mcp.md +0 -1541
  96. package/docs/goals/overview.md +0 -124
  97. package/docs/goals/query-parser.md +0 -373
  98. package/docs/goals/query-result.md +0 -860
  99. package/docs/goals/semantic-dedup.md +0 -233
  100. package/docs/goals/skills.md +0 -810
  101. package/docs/goals/sync.md +0 -217
  102. package/docs/goals/worker-client.md +0 -1005
  103. package/docs/goals/worker-daemon.md +0 -1547
  104. package/docs/modules/overview.md +0 -319
  105. package/docs/modules/rust/embedding/module.md +0 -91
  106. package/docs/modules/rust/fs-database/functions/document.md +0 -48
  107. package/docs/modules/rust/fs-database/functions/integrity.md +0 -79
  108. package/docs/modules/rust/fs-database/functions/io.md +0 -87
  109. package/docs/modules/rust/fs-database/functions/module.md +0 -22
  110. package/docs/modules/rust/fs-database/functions/query-exec.md +0 -44
  111. package/docs/modules/rust/fs-database/functions/section.md +0 -76
  112. package/docs/modules/rust/fs-database/indexes/btree.md +0 -35
  113. package/docs/modules/rust/fs-database/indexes/corpus.md +0 -61
  114. package/docs/modules/rust/fs-database/indexes/inverted.md +0 -60
  115. package/docs/modules/rust/fs-database/indexes/module.md +0 -64
  116. package/docs/modules/rust/fs-database/indexes/positional.md +0 -39
  117. package/docs/modules/rust/fs-database/indexes/vectors.md +0 -110
  118. package/docs/modules/rust/fs-database/module.md +0 -150
  119. package/docs/modules/rust/fs-database/types/catalog.md +0 -53
  120. package/docs/modules/rust/fs-database/types/module.md +0 -12
  121. package/docs/modules/rust/fs-database/types/section.md +0 -127
  122. package/docs/modules/rust/kb-worker/functions/compose.md +0 -57
  123. package/docs/modules/rust/kb-worker/functions/module.md +0 -20
  124. package/docs/modules/rust/kb-worker/functions/retrieve.md +0 -194
  125. package/docs/modules/rust/kb-worker/functions/search.md +0 -173
  126. package/docs/modules/rust/kb-worker/functions/write.md +0 -172
  127. package/docs/modules/rust/kb-worker/module.md +0 -171
  128. package/docs/modules/rust/kb-worker/types/cache.md +0 -90
  129. package/docs/modules/rust/kb-worker/types/context.md +0 -26
  130. package/docs/modules/rust/kb-worker/types/module.md +0 -16
  131. package/docs/modules/rust/kb-worker/types/status.md +0 -29
  132. package/docs/modules/rust/kb-worker/types/token.md +0 -50
  133. package/docs/modules/rust/overview.md +0 -531
  134. package/docs/modules/rust/query-parser/functions/extract.md +0 -56
  135. package/docs/modules/rust/query-parser/functions/module.md +0 -18
  136. package/docs/modules/rust/query-parser/functions/parse.md +0 -33
  137. package/docs/modules/rust/query-parser/functions/pipeline.md +0 -9
  138. package/docs/modules/rust/query-parser/functions/rank.md +0 -85
  139. package/docs/modules/rust/query-parser/module.md +0 -131
  140. package/docs/modules/rust/query-parser/types/cache.md +0 -39
  141. package/docs/modules/rust/query-parser/types/keyphrase.md +0 -71
  142. package/docs/modules/rust/query-parser/types/module.md +0 -18
  143. package/docs/modules/rust/query-parser/types/token.md +0 -46
  144. package/docs/modules/rust/shared/content-composer/functions.md +0 -114
  145. package/docs/modules/rust/shared/content-composer/module.md +0 -147
  146. package/docs/modules/rust/shared/content-composer/types.md +0 -93
  147. package/docs/modules/rust/shared/content-parser/functions.md +0 -72
  148. package/docs/modules/rust/shared/content-parser/module.md +0 -99
  149. package/docs/modules/rust/shared/content-parser/types.md +0 -71
  150. package/docs/modules/rust/shared/corpus/module.md +0 -24
  151. package/docs/modules/rust/shared/corpus/types.md +0 -141
  152. package/docs/modules/rust/shared/document/module.md +0 -25
  153. package/docs/modules/rust/shared/document/types.md +0 -154
  154. package/docs/modules/rust/shared/encode/module.md +0 -22
  155. package/docs/modules/rust/shared/encode/traits.md +0 -304
  156. package/docs/modules/rust/shared/error/module.md +0 -28
  157. package/docs/modules/rust/shared/error/types.md +0 -302
  158. package/docs/modules/rust/shared/kbid/module.md +0 -24
  159. package/docs/modules/rust/shared/kbid/types.md +0 -147
  160. package/docs/modules/rust/shared/memory/functions.md +0 -209
  161. package/docs/modules/rust/shared/memory/module.md +0 -24
  162. package/docs/modules/rust/shared/module.md +0 -196
  163. package/docs/modules/rust/shared/pipeline/functions.md +0 -141
  164. package/docs/modules/rust/shared/pipeline/module.md +0 -62
  165. package/docs/modules/rust/shared/pipeline/types.md +0 -43
  166. package/docs/modules/rust/shared/query/module.md +0 -27
  167. package/docs/modules/rust/shared/query/types.md +0 -236
  168. package/docs/modules/rust/shared/section/module.md +0 -25
  169. package/docs/modules/rust/shared/section/types.md +0 -294
  170. package/docs/modules/rust/shared/term/module.md +0 -25
  171. package/docs/modules/rust/shared/term/types.md +0 -139
  172. package/docs/modules/typescript/cli.md +0 -131
  173. package/docs/modules/typescript/kbdb-worker.md +0 -150
  174. package/docs/modules/typescript/overview.md +0 -400
  175. package/docs/modules/typescript/shared/auto-capture/module.md +0 -73
  176. package/docs/modules/typescript/shared/cli/constants.md +0 -23
  177. package/docs/modules/typescript/shared/cli/functions.md +0 -809
  178. package/docs/modules/typescript/shared/cli/module.md +0 -138
  179. package/docs/modules/typescript/shared/cli/typings.md +0 -197
  180. package/docs/modules/typescript/shared/embedding/functions.md +0 -200
  181. package/docs/modules/typescript/shared/embedding/module.md +0 -77
  182. package/docs/modules/typescript/shared/embedding/typings.md +0 -124
  183. package/docs/modules/typescript/shared/hash/functions.md +0 -20
  184. package/docs/modules/typescript/shared/hash/module.md +0 -21
  185. package/docs/modules/typescript/shared/log/constants.md +0 -82
  186. package/docs/modules/typescript/shared/log/functions.md +0 -131
  187. package/docs/modules/typescript/shared/log/module.md +0 -153
  188. package/docs/modules/typescript/shared/log/typings.md +0 -82
  189. package/docs/modules/typescript/shared/mcp/classes.md +0 -179
  190. package/docs/modules/typescript/shared/mcp/functions.md +0 -386
  191. package/docs/modules/typescript/shared/mcp/module.md +0 -160
  192. package/docs/modules/typescript/shared/mcp/typings.md +0 -529
  193. package/docs/modules/typescript/shared/module.md +0 -110
  194. package/docs/modules/typescript/shared/platform/functions.md +0 -42
  195. package/docs/modules/typescript/shared/platform/module.md +0 -25
  196. package/docs/modules/typescript/shared/runtime/functions.md +0 -26
  197. package/docs/modules/typescript/shared/runtime/module.md +0 -27
  198. package/docs/modules/typescript/shared/runtime/typings.md +0 -13
  199. package/docs/modules/typescript/shared/version/module.md +0 -27
  200. package/docs/modules/typescript/shared/wasm-codec/functions.md +0 -391
  201. package/docs/modules/typescript/shared/wasm-codec/module.md +0 -98
  202. package/docs/modules/typescript/shared/worker-client/classes.md +0 -264
  203. package/docs/modules/typescript/shared/worker-client/functions.md +0 -175
  204. package/docs/modules/typescript/shared/worker-client/module.md +0 -92
  205. package/docs/modules/typescript/shared/worker-client/typings.md +0 -511
  206. package/docs/modules/typescript/shared/worker-daemon/classes.md +0 -239
  207. package/docs/modules/typescript/shared/worker-daemon/constants.md +0 -37
  208. package/docs/modules/typescript/shared/worker-daemon/functions.md +0 -234
  209. package/docs/modules/typescript/shared/worker-daemon/module.md +0 -118
  210. package/docs/modules/typescript/shared/worker-daemon/typings.md +0 -132
  211. package/docs/overview.md +0 -191
  212. package/docs/release-notes/0.1.0.md +0 -189
  213. package/docs/release-notes/0.1.1.md +0 -46
  214. package/docs/release-notes/0.1.2.md +0 -38
  215. package/docs/release-notes/0.1.3.md +0 -42
  216. package/docs/release-notes/0.2.0.md +0 -147
  217. package/docs/release-notes/0.3.0.md +0 -89
  218. package/docs/release-notes/0.3.1.md +0 -121
  219. package/docs/release-notes/0.3.2.md +0 -64
  220. package/docs/release-notes/0.4.0.md +0 -80
  221. package/docs/release-notes/0.4.1.md +0 -149
  222. package/docs/release-notes/0.4.3.md +0 -60
  223. package/docs/release-notes/0.5.0.md +0 -41
  224. package/docs/release-notes/README.md +0 -16
@@ -1,531 +0,0 @@
1
- # Storage Architecture
2
-
3
- kbdb stores everything in a `.kbdb` folder inside the
4
- target directory. There is no external database, no
5
- cloud dependency, and no running server required for
6
- data persistence. All metadata files use TOML for
7
- human inspectability; indexes are binary but derived
8
- and rebuildable from source data. The entire
9
- directory is portable -- it can be copied, moved, or
10
- version-controlled.
11
-
12
- ## Directory Layout
13
-
14
- ```
15
- .kbdb/
16
- +-- catalog.toml
17
- +-- sections/
18
- | +-- {ab}/
19
- | | +-- {cdef...}.sec
20
- | +-- ...
21
- +-- documents/
22
- | +-- {docid}.toml
23
- +-- indexes/
24
- | +-- meta.toml
25
- | +-- terms.idx
26
- | +-- positions.idx
27
- | +-- references.idx
28
- | +-- corpus.dat
29
- +-- worker.toml
30
- +-- .gitignore
31
- ```
32
-
33
- | Path | Format | Description |
34
- |-------------------------------|--------|-------------------------------|
35
- | `catalog.toml` | TOML | Database table of contents: section count, document count, timestamps, integrity checksums |
36
- | `sections/{ab}/{cdef...}.sec` | TOML + raw | Section files: TOML header + content body, sharded by first two characters of kbid |
37
- | `documents/{docid}.toml` | TOML | Document manifests: title + ordered section list |
38
- | `indexes/meta.toml` | TOML | Index metadata: rebuild timestamp, term count, statistics summary |
39
- | `indexes/terms.idx` | Binary | Inverted index (B+ tree): maps terms to posting lists with per-field term frequencies |
40
- | `indexes/positions.idx` | Binary | Positional index (B+ tree): maps (term, kbid) to token offset arrays |
41
- | `indexes/references.idx` | Binary | Reference graph index (B+ tree): bidirectional content marker cross-references between sections |
42
- | `indexes/corpus.dat` | Binary | Corpus statistics: section count, average lengths per field, per-term document frequencies |
43
- | `worker.toml` | TOML | Cache daemon configuration |
44
- | `.gitignore` | Text | Excludes `indexes/` from version control |
45
-
46
- The layout mirrors a PostgreSQL directory-format
47
- dump: a human-readable catalog at the root, one
48
- subdirectory per data table, and a separate directory
49
- for binary indexes.
50
-
51
- ## Content-Addressed IDs (kbid)
52
-
53
- Every section is identified by a deterministic hash
54
- of its content. The same content always produces the
55
- same ID, enabling automatic deduplication.
56
-
57
- ### Hashing Process
58
-
59
- ```
60
- Input content
61
- |
62
- v
63
- Preprocess (text/code only)
64
- |
65
- v
66
- Construct typed header:
67
- "section <mime-type> <byte-size>\0<content>"
68
- |
69
- v
70
- SHA-256 hash
71
- |
72
- v
73
- Truncate to first 16 bytes (128 bits)
74
- |
75
- v
76
- Base32 lowercase encoding (no padding)
77
- |
78
- v
79
- 26-character alphanumeric kbid
80
- ```
81
-
82
- ### Hash Input Format
83
-
84
- The hash input follows the same pattern as Git
85
- objects (`blob <size>\0<content>`):
86
-
87
- ```
88
- section <mime-type> <byte-size>\0<preprocessed-content>
89
- ```
90
-
91
- - `section` -- literal string prefix (type tag)
92
- - `<mime-type>` -- the section's MIME type string
93
- (e.g. `text/markdown`, `text/typescript`,
94
- `image/png`)
95
- - `<byte-size>` -- byte length of the preprocessed
96
- content, as a decimal ASCII string
97
- - `\0` -- literal null byte separator
98
- - `<preprocessed-content>` -- the content after
99
- preprocessing (text/code) or the base64 string
100
- as-is (images)
101
-
102
- ### Worked Example
103
-
104
- ```
105
- Given:
106
- type = "text/markdown"
107
- content = "Hello, world!" (13 bytes after preprocessing)
108
-
109
- Hash input (41 bytes):
110
- section text/markdown 13\0Hello, world!
111
-
112
- +-- header: "section text/markdown 13"
113
- +-- null byte: \0
114
- +-- content: "Hello, world!"
115
-
116
- kbid = base32(sha256(hash_input)[..16])
117
- = 26-character lowercase alphanumeric string
118
- ```
119
-
120
- ### Properties
121
-
122
- - **Deterministic** -- identical content with the
123
- same MIME type always produces the same kbid.
124
- - **Type-aware** -- the MIME type is part of the hash
125
- input, so identical raw content stored as different
126
- types (e.g. `text/markdown` vs `text/typescript`)
127
- produces different kbids.
128
- - **Collision-resistant** -- SHA-256 truncated to 128
129
- bits provides sufficient collision resistance for a
130
- local knowledge base.
131
- - **URL-safe** -- base32 lowercase encoding uses only
132
- alphanumeric characters.
133
-
134
- ## Content Preprocessing
135
-
136
- Before computing the kbid, text and code sections
137
- pass through a preprocessing pipeline that
138
- normalizes encoding artifacts. This ensures that
139
- semantically identical content -- differing only in
140
- BOM, line endings, Unicode representation, or
141
- surrounding whitespace -- produces the same kbid.
142
-
143
- ### Pipeline Steps (Applied in Order)
144
-
145
- 1. **BOM removal** -- Strip the UTF-8 byte order mark
146
- (U+FEFF) if present at the start of the content.
147
- The BOM is an encoding artifact, not meaningful
148
- content.
149
-
150
- 2. **Line ending normalization** -- Convert all
151
- `\r\n` (Windows) and bare `\r` (old Mac) sequences
152
- to `\n` (Unix). Content created on different
153
- platforms produces the same kbid.
154
-
155
- 3. **Unicode NFC normalization** -- Compose decomposed
156
- Unicode sequences into their canonical form. For
157
- example, `e` + combining acute accent becomes `e`
158
- (U+00E9). This is the same normalization used in
159
- the tokenization pipeline.
160
-
161
- 4. **Whitespace trimming** -- Remove all leading and
162
- trailing whitespace characters (spaces, tabs,
163
- newlines, carriage returns, and other Unicode
164
- whitespace and control characters).
165
-
166
- ### Scope
167
-
168
- This pipeline applies to **text and code sections
169
- only**. Image sections use the base64-encoded string
170
- as-is -- no preprocessing is applied.
171
-
172
- The preprocessed content is what gets stored on disk.
173
- The pipeline runs once at ingest time; subsequent
174
- reads return the already-preprocessed content. The
175
- `<byte-size>` in the hash header is computed from the
176
- content after preprocessing.
177
-
178
- ## Section File Format
179
-
180
- Each section file has a TOML header followed by a
181
- `---` separator and the raw content body. The header
182
- is human-readable; the content after the separator is
183
- stored verbatim.
184
-
185
- ### Header Fields
186
-
187
- | Field | Type | Required | Description |
188
- |-----------------------|--------|----------|-----------------------|
189
- | `kbid` | string | Yes | 26-character content hash |
190
- | `docids` | array | Yes | Document IDs referencing this section |
191
- | `type` | string | Yes | MIME type (`text/markdown`, `text/typescript`, `image/png`, etc.) |
192
- | `title` | string | Images: yes, others: no | Short descriptive title. Indexed with heading weight (2.0x) |
193
- | `description` | string | No | Longer description. Indexed with body weight (1.0x) |
194
- | `size` | u32 | Yes | Content byte size |
195
- | `token_count` | u32 | Yes | Total tokens after tokenization |
196
- | `heading_token_count` | u32 | Yes | Tokens from `title` |
197
- | `body_token_count` | u32 | Yes | Tokens from body text + `description` |
198
- | `code_token_count` | u32 | Yes | Tokens from code content |
199
- | `created_at` | string | Yes | ISO 8601 timestamp |
200
- | `checksum` | string | Yes | Integrity checksum |
201
-
202
- The `title` and `description` fields are not included
203
- in the kbid hash -- changing them does not change the
204
- section's identity.
205
-
206
- Token count fields are pre-computed at insertion time
207
- by `query-parser.wasm` and stored for reuse at query
208
- time. This trades a small write-time cost for
209
- significant search speed.
210
-
211
- ### Example: Text Section
212
-
213
- File: `sections/ab/cdef1234...sec`
214
-
215
- ```
216
- kbid = "abcdef1234567890abcdef1234"
217
- docids = ["doc-5678"]
218
- type = "text/markdown"
219
- title = "Architecture Overview"
220
- description = "High-level overview of the system"
221
- size = 1234
222
- token_count = 187
223
- heading_token_count = 2
224
- body_token_count = 187
225
- code_token_count = 0
226
- created_at = "2026-06-15T10:00:00Z"
227
- checksum = "sha256:abcdef..."
228
- ---
229
- Section body text here.
230
-
231
- $(image: 7fa93b2e4c8d1076a93b2e4c8d)
232
-
233
- $(code: c4e8a91d3f7b20564e8a91d3f7)
234
-
235
- This content continues after the embedded sections.
236
- No escaping or encoding is applied.
237
- ```
238
-
239
- ### Example: Code Section
240
-
241
- File: `sections/c4/e8a91d...sec`
242
-
243
- ```
244
- kbid = "c4e8a91d3f7b20564e8a91d3f7"
245
- docids = ["doc-5678"]
246
- type = "text/typescript"
247
- title = "greet function"
248
- size = 256
249
- token_count = 22
250
- heading_token_count = 2
251
- body_token_count = 0
252
- code_token_count = 22
253
- created_at = "2026-06-15T10:15:00Z"
254
- checksum = "sha256:1a2b3c..."
255
- ---
256
- export function greet(name: string): string {
257
- return `Hello, ${name}!`;
258
- }
259
- ```
260
-
261
- ### Example: Image Section
262
-
263
- File: `sections/7f/a93b2e...sec`
264
-
265
- ```
266
- kbid = "7fa93b2e4c8d1076a93b2e4c8d"
267
- docids = ["doc-5678"]
268
- type = "image/png"
269
- title = "Architecture diagram"
270
- description = "Five-layer stack diagram"
271
- size = 48576
272
- token_count = 5
273
- heading_token_count = 2
274
- body_token_count = 3
275
- code_token_count = 0
276
- created_at = "2026-06-15T10:30:00Z"
277
- checksum = "sha256:fedcba..."
278
- ---
279
- iVBORw0KGgoAAAANSUhEUgAA...base64 data...
280
- ```
281
-
282
- The image section has `token_count = 5` from title
283
- and description tokens only. Binary content produces
284
- zero tokens.
285
-
286
- ### Section Types
287
-
288
- | Type | Content after `---` | Indexed? |
289
- |---------------------|------------------------|----------|
290
- | `text/markdown` | Raw markdown text | Yes (body field) |
291
- | `text/*` (code) | Raw source code | Yes (code field) |
292
- | `application/json` | Raw JSON | Yes (code field) |
293
- | `image/*` | Base64-encoded binary | No (metadata only) |
294
-
295
- Code sections are processed through the same
296
- tokenization pipeline as text, including identifier
297
- splitting for camelCase and snake_case terms. Image
298
- binary content is skipped, but `title` (required) and
299
- `description` (optional) are tokenized and indexed.
300
-
301
- ## Document Manifests
302
-
303
- A document groups sections under a title with a
304
- defined order. Documents do not contain content
305
- directly -- they reference sections by kbid. The
306
- relationship is many-to-many: a section may appear in
307
- multiple documents, and a document contains multiple
308
- sections.
309
-
310
- ### Format
311
-
312
- ```toml
313
- [document]
314
- docid = "doc-5678"
315
- title = "Getting Started Guide"
316
- created_at = "2026-06-15T10:00:00Z"
317
-
318
- [[sections]]
319
- kbid = "abcdef1234567890abcdef1234"
320
- position = 0
321
-
322
- [[sections]]
323
- kbid = "fedcba4321098765fedcba4321"
324
- position = 1
325
- ```
326
-
327
- ### Fields
328
-
329
- | Field | Description |
330
- |--------------------------|--------------------------|
331
- | `document.docid` | Document identifier |
332
- | `document.title` | Human-readable title |
333
- | `document.created_at` | ISO 8601 timestamp |
334
- | `sections[].kbid` | Section content hash |
335
- | `sections[].position` | Zero-based display order |
336
-
337
- Documents are human-readable and diffable in git.
338
- When a document is retrieved, its sections are
339
- returned in position order with full content.
340
-
341
- ## Catalog (`catalog.toml`)
342
-
343
- The catalog is the database's table of contents --
344
- the first file read when opening a database. It
345
- records high-level state without requiring a
346
- directory scan.
347
-
348
- ```toml
349
- [database]
350
- version = 1
351
- created_at = "2026-06-15T10:00:00Z"
352
- last_modified = "2026-06-15T12:00:00Z"
353
-
354
- [counts]
355
- sections = 42
356
- documents = 5
357
-
358
- [integrity]
359
- checksum = "sha256:abcdef..."
360
- ```
361
-
362
- Updated on every write operation. If a crash occurs
363
- mid-write, the catalog remains consistent with the
364
- last complete state (see Write Safety below).
365
-
366
- ## MIME Types
367
-
368
- kbdb uses standard MIME type strings to identify
369
- section content:
370
-
371
- | Category | MIME types | Canonical |
372
- |-----------|-------------------------------------|-----------------|
373
- | Text | `text/markdown` | `text/markdown` |
374
- | Code | `text/typescript`, `text/javascript`, `text/html`, `text/css`, `text/xml`, `text/plain`, `application/json` | Varies |
375
- | Image | `image/png`, `image/jpeg`, `image/webp` | Varies |
376
-
377
- The bare string `"text"` is not used. Text sections
378
- use `text/markdown` as their canonical type. The MIME
379
- type is part of the kbid hash, so the same raw
380
- content stored under different types produces
381
- different section files.
382
-
383
- ## Write Safety
384
-
385
- All write operations are designed to be crash-safe:
386
-
387
- - **Atomic writes** -- New files are written to a
388
- temporary path and then renamed into place. A crash
389
- during the write leaves no partial files -- either
390
- the old file remains or the new file is complete.
391
-
392
- - **Catalog updated last** -- The catalog is written
393
- after all data files. A crash mid-write leaves the
394
- catalog consistent with the last fully committed
395
- state. The worst case is an unreferenced section
396
- file on disk, which garbage collection handles.
397
-
398
- - **Indexes rebuildable** -- Index files are derived
399
- data. If index files are corrupted or lost, they
400
- can be rebuilt entirely from sections and document
401
- manifests. The `.gitignore` excludes indexes from
402
- version control because they are not source data.
403
-
404
- ### Write Sequence
405
-
406
- ```
407
- 1. Write section file to temp path
408
- |
409
- v
410
- 2. Rename temp file into sections/{ab}/{kbid}.sec
411
- |
412
- v
413
- 3. Update document manifest (if docid provided)
414
- |
415
- v
416
- 4. Update indexes (inverted + positional + corpus)
417
- |
418
- v
419
- 5. Update catalog.toml (counts, timestamp, checksum)
420
- ```
421
-
422
- Each step is atomic. The catalog update in step 5
423
- commits the entire operation. Steps 1-4 can fail
424
- without corrupting the database.
425
-
426
- ## Content Markers
427
-
428
- Text sections can contain markers -- escape sequences
429
- that embed or link to other sections and documents.
430
- Markers are stored verbatim in the content body and
431
- resolved at read time, not at write time.
432
-
433
- ### Marker Types
434
-
435
- | Marker | Category | Target type | Render behavior |
436
- |-----------------------------|-----------|--------------------------|------------------------|
437
- | `$(image: {kbid})` | Embedding | `image/*` section | Inline image |
438
- | `$(code: {kbid})` | Embedding | `text/*` or `application/json` section | Fenced code block |
439
- | `$(text: {kbid})` | Embedding | `text/markdown` section | Inline markdown (recursive) |
440
- | `$(document: {docid})` | Embedding | Document manifest | All sections expanded (recursive) |
441
- | `$(link: {kbid})` | Link | Any section | Cross-reference |
442
- | `$(doc-link: {docid})` | Link | Document manifest | Cross-reference |
443
-
444
- ### Syntax
445
-
446
- Markers use the format `$(type: value)`:
447
-
448
- ```
449
- $(image: 7fa93b2e4c8d1076a93b2e4c8d)
450
- $(code: c4e8a91d3f7b20564e8a91d3f7)
451
- $(text: a1b2c3d4e5f6a1b2c3d4e5f6a1)
452
- $(document: api-reference-v2)
453
- $(link: d5e6f7a8b9c0d5e6f7a8b9c0d5)
454
- $(doc-link: getting-started-guide)
455
- ```
456
-
457
- Rules:
458
- - A colon and a space separate type from value.
459
- - Markers cannot be nested.
460
- - Unrecognized types pass through unchanged.
461
- - Unclosed markers are treated as plain text.
462
-
463
- ### Recursive Resolution
464
-
465
- The `$(text:)` and `$(document:)` markers trigger
466
- recursive expansion -- the embedded content may
467
- itself contain markers that must be resolved.
468
-
469
- Circular references are detected using a visited set:
470
-
471
- ```
472
- Expand marker $(text: A)
473
- |
474
- v
475
- Add A to visited set: {A}
476
- |
477
- v
478
- Section A contains $(text: B)
479
- |
480
- v
481
- Add B to visited set: {A, B}
482
- |
483
- v
484
- Section B contains $(text: A)
485
- |
486
- v
487
- A is already in visited set -> STOP (circular)
488
- ```
489
-
490
- Circular references are reported as errors during
491
- both integrity checks and render-time expansion.
492
-
493
- ### Tokenization
494
-
495
- All six marker types are stripped from content before
496
- tokenization and indexing (stage 1 of the
497
- tokenization pipeline). Markers are structural
498
- references, not searchable text -- they do not appear
499
- in the search index.
500
-
501
- ## Deduplication
502
-
503
- Sections are content-addressable. When identical
504
- content (after preprocessing) is added with the same
505
- MIME type:
506
-
507
- | Scenario | Result |
508
- |-----------------------|-----------------------------|
509
- | Different `docid` | Existing section's `docids` array updated to include the new docid. No new file created. |
510
- | No `docid` | Section skipped entirely. |
511
- | Same `docid` already present | Idempotent -- no change. |
512
-
513
- A section can belong to zero or more documents.
514
- Updating a section's content creates a new file with
515
- a new kbid; the old file becomes eligible for garbage
516
- collection.
517
-
518
- ## Storage Performance
519
-
520
- The directory layout is optimized for read speed:
521
-
522
- | Operation | Complexity | Mechanism |
523
- |-------------------|------------|-------------------------|
524
- | Section lookup | O(1) | Hash-sharded directories allow direct file access by kbid |
525
- | Term lookup | O(log n) | B+ tree indexes |
526
- | Catalog discovery | O(1) | `catalog.toml` provides counts without scanning |
527
- | Document listing | O(1) | Direct file access by docid |
528
-
529
- Write operations prioritize safety over speed. The
530
- atomic write + catalog-last pattern ensures no
531
- partial state is visible after a crash.