@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,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.