@dikolab/kbdb 0.1.5 → 0.2.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 (193) hide show
  1. package/README.md +30 -9
  2. package/dist/cli.cjs +181 -50
  3. package/dist/cli.cjs.map +3 -3
  4. package/dist/cli.mjs +181 -50
  5. package/dist/cli.mjs.map +3 -3
  6. package/dist/kbdb-worker.cjs +283 -29
  7. package/dist/kbdb-worker.cjs.map +4 -4
  8. package/dist/mod.cjs +13 -2
  9. package/dist/mod.cjs.map +2 -2
  10. package/dist/mod.mjs +13 -2
  11. package/dist/mod.mjs.map +2 -2
  12. package/dist/src/shared/cli/functions/format-output.function.d.ts +7 -7
  13. package/dist/src/shared/cli/functions/run-search.function.d.ts +25 -16
  14. package/dist/src/shared/cli/index.d.ts +1 -1
  15. package/dist/src/shared/cli/typings/cli-options.interface.d.ts +2 -0
  16. package/dist/src/shared/cli/typings/search-display.model.d.ts +25 -7
  17. package/dist/src/shared/mcp/functions/handle-recall.function.d.ts +29 -0
  18. package/dist/src/shared/mcp/typings/mcp-client.interface.d.ts +30 -11
  19. package/dist/src/shared/version/constants/version.constant.d.ts +1 -1
  20. package/dist/src/shared/wasm-codec/functions/decode-recall-result.function.d.ts +28 -0
  21. package/dist/src/shared/wasm-codec/functions/decode-scored-results.function.d.ts +14 -7
  22. package/dist/src/shared/wasm-codec/functions/encode-recall-params.function.d.ts +21 -0
  23. package/dist/src/shared/wasm-codec/functions/encode-search-params.function.d.ts +1 -1
  24. package/dist/src/shared/wasm-codec/index.d.ts +5 -2
  25. package/dist/src/shared/worker-client/classes/worker-client.class.d.ts +13 -3
  26. package/dist/src/shared/worker-client/index.d.ts +2 -1
  27. package/dist/src/shared/worker-client/typings/recall-result.model.d.ts +94 -0
  28. package/dist/src/shared/worker-client/typings/search-params.model.d.ts +2 -0
  29. package/dist/src/shared/worker-client/typings/search-result.model.d.ts +23 -7
  30. package/dist/src/shared/worker-daemon/classes/worker-daemon.class.d.ts +1 -0
  31. package/dist/wasm/fs-database/kbdb_fs_database.d.ts +18 -0
  32. package/dist/wasm/fs-database/kbdb_fs_database.js +30 -0
  33. package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
  34. package/dist/wasm/fs-database/kbdb_fs_database_bg.wasm.d.ts +2 -0
  35. package/dist/wasm/kb-worker/kbdb_worker.d.ts +38 -0
  36. package/dist/wasm/kb-worker/kbdb_worker.js +56 -0
  37. package/dist/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
  38. package/dist/wasm/kb-worker/kbdb_worker_bg.wasm.d.ts +3 -0
  39. package/dist/worker.mjs +283 -29
  40. package/dist/worker.mjs.map +4 -4
  41. package/docs/details/README.md +26 -0
  42. package/docs/details/cli.md +608 -0
  43. package/docs/details/library-api.md +406 -0
  44. package/docs/details/mcp-server.md +430 -0
  45. package/docs/details/search-and-ranking.md +457 -0
  46. package/docs/details/storage.md +529 -0
  47. package/docs/goals/agents.md +751 -0
  48. package/docs/goals/architecture.svg +198 -0
  49. package/docs/goals/cli.md +2308 -0
  50. package/docs/goals/content-composer.md +609 -0
  51. package/docs/goals/content-parser.md +279 -0
  52. package/docs/goals/database.md +1452 -0
  53. package/docs/goals/document.md +368 -0
  54. package/docs/goals/mcp.md +1467 -0
  55. package/docs/goals/overview.md +124 -0
  56. package/docs/goals/query-parser.md +271 -0
  57. package/docs/goals/query-result.md +693 -0
  58. package/docs/goals/skills.md +738 -0
  59. package/docs/goals/worker-client.md +944 -0
  60. package/docs/goals/worker-daemon.md +1447 -0
  61. package/docs/modules/overview.md +298 -0
  62. package/docs/modules/rust/fs-database/functions/document.md +48 -0
  63. package/docs/modules/rust/fs-database/functions/integrity.md +68 -0
  64. package/docs/modules/rust/fs-database/functions/io.md +87 -0
  65. package/docs/modules/rust/fs-database/functions/module.md +22 -0
  66. package/docs/modules/rust/fs-database/functions/query-exec.md +44 -0
  67. package/docs/modules/rust/fs-database/functions/section.md +59 -0
  68. package/docs/modules/rust/fs-database/indexes/btree.md +35 -0
  69. package/docs/modules/rust/fs-database/indexes/corpus.md +61 -0
  70. package/docs/modules/rust/fs-database/indexes/inverted.md +60 -0
  71. package/docs/modules/rust/fs-database/indexes/module.md +64 -0
  72. package/docs/modules/rust/fs-database/indexes/positional.md +39 -0
  73. package/docs/modules/rust/fs-database/module.md +149 -0
  74. package/docs/modules/rust/fs-database/types/catalog.md +53 -0
  75. package/docs/modules/rust/fs-database/types/module.md +12 -0
  76. package/docs/modules/rust/fs-database/types/section.md +101 -0
  77. package/docs/modules/rust/kb-worker/functions/compose.md +57 -0
  78. package/docs/modules/rust/kb-worker/functions/module.md +20 -0
  79. package/docs/modules/rust/kb-worker/functions/retrieve.md +194 -0
  80. package/docs/modules/rust/kb-worker/functions/search.md +173 -0
  81. package/docs/modules/rust/kb-worker/functions/write.md +172 -0
  82. package/docs/modules/rust/kb-worker/module.md +171 -0
  83. package/docs/modules/rust/kb-worker/types/cache.md +90 -0
  84. package/docs/modules/rust/kb-worker/types/context.md +26 -0
  85. package/docs/modules/rust/kb-worker/types/module.md +16 -0
  86. package/docs/modules/rust/kb-worker/types/status.md +29 -0
  87. package/docs/modules/rust/kb-worker/types/token.md +50 -0
  88. package/docs/modules/rust/overview.md +495 -0
  89. package/docs/modules/rust/query-parser/functions/extract.md +56 -0
  90. package/docs/modules/rust/query-parser/functions/module.md +16 -0
  91. package/docs/modules/rust/query-parser/functions/parse.md +33 -0
  92. package/docs/modules/rust/query-parser/functions/pipeline.md +103 -0
  93. package/docs/modules/rust/query-parser/functions/rank.md +85 -0
  94. package/docs/modules/rust/query-parser/module.md +136 -0
  95. package/docs/modules/rust/query-parser/types/cache.md +39 -0
  96. package/docs/modules/rust/query-parser/types/keyphrase.md +60 -0
  97. package/docs/modules/rust/query-parser/types/module.md +17 -0
  98. package/docs/modules/rust/query-parser/types/token.md +42 -0
  99. package/docs/modules/rust/shared/content-composer/functions.md +114 -0
  100. package/docs/modules/rust/shared/content-composer/module.md +147 -0
  101. package/docs/modules/rust/shared/content-composer/types.md +93 -0
  102. package/docs/modules/rust/shared/content-parser/functions.md +72 -0
  103. package/docs/modules/rust/shared/content-parser/module.md +99 -0
  104. package/docs/modules/rust/shared/content-parser/types.md +71 -0
  105. package/docs/modules/rust/shared/corpus/module.md +24 -0
  106. package/docs/modules/rust/shared/corpus/types.md +141 -0
  107. package/docs/modules/rust/shared/document/module.md +25 -0
  108. package/docs/modules/rust/shared/document/types.md +154 -0
  109. package/docs/modules/rust/shared/encode/module.md +22 -0
  110. package/docs/modules/rust/shared/encode/traits.md +304 -0
  111. package/docs/modules/rust/shared/error/module.md +28 -0
  112. package/docs/modules/rust/shared/error/types.md +302 -0
  113. package/docs/modules/rust/shared/kbid/module.md +24 -0
  114. package/docs/modules/rust/shared/kbid/types.md +147 -0
  115. package/docs/modules/rust/shared/memory/functions.md +209 -0
  116. package/docs/modules/rust/shared/memory/module.md +24 -0
  117. package/docs/modules/rust/shared/module.md +168 -0
  118. package/docs/modules/rust/shared/query/module.md +27 -0
  119. package/docs/modules/rust/shared/query/types.md +236 -0
  120. package/docs/modules/rust/shared/section/module.md +25 -0
  121. package/docs/modules/rust/shared/section/types.md +294 -0
  122. package/docs/modules/rust/shared/term/module.md +25 -0
  123. package/docs/modules/rust/shared/term/types.md +139 -0
  124. package/docs/modules/typescript/cli.md +129 -0
  125. package/docs/modules/typescript/kbdb-worker.md +135 -0
  126. package/docs/modules/typescript/overview.md +378 -0
  127. package/docs/modules/typescript/shared/cli/constants.md +23 -0
  128. package/docs/modules/typescript/shared/cli/functions.md +630 -0
  129. package/docs/modules/typescript/shared/cli/module.md +125 -0
  130. package/docs/modules/typescript/shared/cli/typings.md +172 -0
  131. package/docs/modules/typescript/shared/hash/functions.md +20 -0
  132. package/docs/modules/typescript/shared/hash/module.md +21 -0
  133. package/docs/modules/typescript/shared/mcp/classes.md +179 -0
  134. package/docs/modules/typescript/shared/mcp/functions.md +386 -0
  135. package/docs/modules/typescript/shared/mcp/module.md +160 -0
  136. package/docs/modules/typescript/shared/mcp/typings.md +522 -0
  137. package/docs/modules/typescript/shared/module.md +94 -0
  138. package/docs/modules/typescript/shared/platform/functions.md +42 -0
  139. package/docs/modules/typescript/shared/platform/module.md +25 -0
  140. package/docs/modules/typescript/shared/runtime/functions.md +26 -0
  141. package/docs/modules/typescript/shared/runtime/module.md +27 -0
  142. package/docs/modules/typescript/shared/runtime/typings.md +13 -0
  143. package/docs/modules/typescript/shared/version/module.md +27 -0
  144. package/docs/modules/typescript/shared/wasm-codec/functions.md +391 -0
  145. package/docs/modules/typescript/shared/wasm-codec/module.md +98 -0
  146. package/docs/modules/typescript/shared/worker-client/classes.md +264 -0
  147. package/docs/modules/typescript/shared/worker-client/functions.md +175 -0
  148. package/docs/modules/typescript/shared/worker-client/module.md +84 -0
  149. package/docs/modules/typescript/shared/worker-client/typings.md +508 -0
  150. package/docs/modules/typescript/shared/worker-daemon/classes.md +239 -0
  151. package/docs/modules/typescript/shared/worker-daemon/constants.md +37 -0
  152. package/docs/modules/typescript/shared/worker-daemon/functions.md +221 -0
  153. package/docs/modules/typescript/shared/worker-daemon/module.md +112 -0
  154. package/docs/modules/typescript/shared/worker-daemon/typings.md +126 -0
  155. package/docs/overview.md +188 -0
  156. package/docs/release-notes/0.1.0.md +189 -0
  157. package/docs/release-notes/0.1.1.md +46 -0
  158. package/docs/release-notes/0.1.2.md +38 -0
  159. package/docs/release-notes/0.1.3.md +42 -0
  160. package/docs/release-notes/0.2.0.md +147 -0
  161. package/docs/release-notes/README.md +9 -0
  162. package/package.json +8 -2
  163. package/src/shared/cli/functions/dispatch-command.function.ts +3 -3
  164. package/src/shared/cli/functions/format-output.function.ts +41 -34
  165. package/src/shared/cli/functions/parse-args.function.ts +7 -0
  166. package/src/shared/cli/functions/run-search.function.ts +53 -27
  167. package/src/shared/cli/index.ts +4 -1
  168. package/src/shared/cli/typings/cli-options.interface.ts +2 -0
  169. package/src/shared/cli/typings/search-display.model.ts +26 -7
  170. package/src/shared/mcp/functions/create-tool-definitions.function.ts +64 -4
  171. package/src/shared/mcp/functions/handle-recall.function.ts +66 -0
  172. package/src/shared/mcp/functions/handle-tool-call.function.ts +11 -1
  173. package/src/shared/mcp/typings/mcp-client.interface.ts +33 -15
  174. package/src/shared/version/constants/version.constant.ts +1 -1
  175. package/src/shared/wasm-codec/functions/decode-recall-result.function.ts +267 -0
  176. package/src/shared/wasm-codec/functions/decode-scored-results.function.ts +81 -27
  177. package/src/shared/wasm-codec/functions/encode-recall-params.function.ts +68 -0
  178. package/src/shared/wasm-codec/functions/encode-search-params.function.ts +4 -1
  179. package/src/shared/wasm-codec/index.ts +11 -3
  180. package/src/shared/worker-client/classes/worker-client.class.ts +24 -4
  181. package/src/shared/worker-client/index.ts +11 -1
  182. package/src/shared/worker-client/typings/recall-result.model.ts +98 -0
  183. package/src/shared/worker-client/typings/search-params.model.ts +2 -0
  184. package/src/shared/worker-client/typings/search-result.model.ts +24 -7
  185. package/src/shared/worker-daemon/classes/worker-daemon.class.ts +25 -4
  186. package/src/wasm/fs-database/kbdb_fs_database.d.ts +18 -0
  187. package/src/wasm/fs-database/kbdb_fs_database.js +30 -0
  188. package/src/wasm/fs-database/kbdb_fs_database_bg.wasm +0 -0
  189. package/src/wasm/fs-database/kbdb_fs_database_bg.wasm.d.ts +2 -0
  190. package/src/wasm/kb-worker/kbdb_worker.d.ts +38 -0
  191. package/src/wasm/kb-worker/kbdb_worker.js +56 -0
  192. package/src/wasm/kb-worker/kbdb_worker_bg.wasm +0 -0
  193. package/src/wasm/kb-worker/kbdb_worker_bg.wasm.d.ts +3 -0
@@ -0,0 +1,141 @@
1
+ # types::corpus -- Corpus Statistics
2
+
3
+ *Lightweight corpus statistics struct passed between
4
+ modules for IDF computation and BM25F length
5
+ normalization.*
6
+
7
+ ## File
8
+
9
+ `engine/crates/shared/src/corpus/corpus.rs`
10
+
11
+ ## Overview
12
+
13
+ Ranking functions need corpus-wide statistics to
14
+ compute inverse document frequency (IDF) and
15
+ normalize for section length. The full corpus data
16
+ (including the per-term document frequency map) lives
17
+ in `fs-database`'s `CorpusStats` struct in the
18
+ `index::corpus` module. This shared type is a
19
+ **lightweight view** -- just the scalar values needed
20
+ by `query-parser`'s ranking exports.
21
+
22
+ `kb-worker` reads the full stats from `fs-database`,
23
+ extracts the fields needed for ranking, and passes
24
+ this struct to `query-parser`.
25
+
26
+ See [Query Parser -- Ranking](
27
+ ../../../../../goals/query-parser.md) for how these
28
+ values are used in BM25F scoring.
29
+
30
+ ## Type Definition
31
+
32
+ ```rust
33
+ pub struct CorpusStats {
34
+ pub total_sections: u32,
35
+ pub total_terms: u32,
36
+ pub avg_section_length: f32,
37
+ pub avg_heading_length: f32,
38
+ pub avg_body_length: f32,
39
+ pub avg_code_length: f32,
40
+ }
41
+ ```
42
+
43
+ | Field | Description |
44
+ |----------------------|--------------------------------|
45
+ | `total_sections` | Number of sections with at least one indexed term |
46
+ | `total_terms` | Total number of distinct terms in the inverted index |
47
+ | `avg_section_length` | Average total token count per indexed section |
48
+ | `avg_heading_length` | Average heading-field token count per indexed section |
49
+ | `avg_body_length` | Average body-field token count per indexed section |
50
+ | `avg_code_length` | Average code-field token count per indexed section |
51
+
52
+ ### `total_sections`
53
+
54
+ Count of sections that have at least one indexed
55
+ term. Image sections are included when their
56
+ `title` or `description` produces indexed terms.
57
+ Used as the `N` value in IDF:
58
+ `idf(t) = ln((N - df(t) + 0.5) / (df(t) + 0.5) + 1)`.
59
+
60
+ ### `total_terms`
61
+
62
+ Number of unique terms across the entire index.
63
+ Informational -- not directly used in ranking, but
64
+ useful for status reporting and diagnostics.
65
+
66
+ ### `avg_section_length`
67
+
68
+ Average number of tokens per indexed section. Used
69
+ by BM25F for overall length normalization.
70
+
71
+ Computed as:
72
+ `sum(token_count for each indexed section) / total_sections`
73
+
74
+ ### `avg_heading_length`
75
+
76
+ Average heading-field token count per indexed
77
+ section. Used by BM25F for per-field length
78
+ normalization of the heading component (title
79
+ content).
80
+
81
+ Computed as:
82
+ `sum(heading_token_count for each indexed section) / total_sections`
83
+
84
+ ### `avg_body_length`
85
+
86
+ Average body-field token count per indexed section.
87
+ Used by BM25F for per-field length normalization
88
+ of the body component (body text + description).
89
+
90
+ Computed as:
91
+ `sum(body_token_count for each indexed section) / total_sections`
92
+
93
+ ### `avg_code_length`
94
+
95
+ Average code-field token count per indexed section.
96
+ Used by BM25F for per-field length normalization
97
+ of the code component (source code content).
98
+
99
+ Computed as:
100
+ `sum(code_token_count for each indexed section) / total_sections`
101
+
102
+ ## Why a Separate Shared Type
103
+
104
+ `fs-database`'s internal `CorpusStats` struct (in
105
+ `index::corpus`) contains additional fields -- the
106
+ full `HashMap<Term, u32>` of per-term document
107
+ frequencies, incremental update methods, and
108
+ serialization logic for the `corpus.dat` binary file.
109
+ That struct is private to `fs-database`.
110
+
111
+ The shared `CorpusStats` here contains only the
112
+ scalar fields that cross module boundaries. This
113
+ keeps the shared type small and avoids exposing
114
+ `fs-database` internals to `query-parser`.
115
+
116
+ When `kb-worker` needs per-term IDF values, it calls
117
+ `db_corpus_stats` (which returns this shared struct)
118
+ and separately calls `db_execute_plan` (which returns
119
+ per-term frequencies in `RawMatch`). The full
120
+ document frequency map never leaves `fs-database`.
121
+
122
+ ## Trait Implementations
123
+
124
+ | Trait | Purpose |
125
+ |----------|----------------------------------|
126
+ | `Clone` | Cached alongside index segments |
127
+ | `Debug` | Diagnostic output |
128
+ | `Copy` | Small struct, stack-friendly |
129
+ | `Encode` | Binary serialization for shared memory (see [encode](../encode/traits.md)) |
130
+
131
+ ## Testing
132
+
133
+ Unit tests:
134
+
135
+ - Construction with valid values.
136
+ - `Copy` semantics: assignment creates independent
137
+ value.
138
+ - `Encode` round-trip preserves all six fields
139
+ including `f32` precision.
140
+ - Edge cases: `total_sections = 0` (empty database),
141
+ all average lengths `0.0`.
@@ -0,0 +1,25 @@
1
+ # document -- Document Records
2
+
3
+ *Data structures for document manifests and document-
4
+ level retrieval results.*
5
+
6
+ ## Source
7
+
8
+ `engine/crates/shared/src/document/`
9
+
10
+ ## Responsibility
11
+
12
+ Defines the document manifest and record types that
13
+ group sections under a title with a defined order.
14
+ Shared across `fs-database` (manifest storage),
15
+ `kb-worker` (cache entries and retrieval), and the
16
+ IPC boundary.
17
+
18
+ See [Database -- Documents](
19
+ ../../../../goals/database.md) for the behavioral
20
+ specification of document manifests.
21
+
22
+ ## Exports
23
+
24
+ - **[types.md](types.md)** -- `DocumentManifest`,
25
+ `DocumentSection`, `DocumentRecord`.
@@ -0,0 +1,154 @@
1
+ # types::document -- Document Records
2
+
3
+ *Data structures for document manifests and document-
4
+ level retrieval results shared across WASM modules.*
5
+
6
+ ## File
7
+
8
+ `engine/crates/shared/src/document/document.rs`
9
+
10
+ ## Overview
11
+
12
+ A **document** groups sections under a title with a
13
+ defined order. The document itself contains no content
14
+ -- it references sections by kb-id. These types are
15
+ shared across `fs-database` (manifest storage),
16
+ `kb-worker` (cache entries and retrieval), and
17
+ the IPC boundary (JSON-RPC responses).
18
+
19
+ See [Database -- Documents](
20
+ ../../../../../goals/database.md) for the behavioral
21
+ specification of document manifests.
22
+
23
+ ## Type Definitions
24
+
25
+ ### `DocumentManifest`
26
+
27
+ ```rust
28
+ pub struct DocumentManifest {
29
+ pub docid: String,
30
+ pub title: String,
31
+ pub created_at: String,
32
+ pub sections: Vec<DocumentSection>,
33
+ }
34
+ ```
35
+
36
+ Represents the TOML manifest file at
37
+ `documents/{docid}.toml`. Contains metadata and an
38
+ ordered list of section references.
39
+
40
+ `sections` is ordered by `position` -- the manifest
41
+ preserves the original section order within the
42
+ document.
43
+
44
+ ### `DocumentSection`
45
+
46
+ ```rust
47
+ pub struct DocumentSection {
48
+ pub kbid: KbId,
49
+ pub position: u32,
50
+ }
51
+ ```
52
+
53
+ A reference from a document to a section. `position`
54
+ is a zero-based ordinal that determines the section's
55
+ display order when the document is retrieved.
56
+
57
+ ### `DocumentRecord`
58
+
59
+ ```rust
60
+ pub struct DocumentRecord {
61
+ pub docid: String,
62
+ pub title: String,
63
+ pub created_at: String,
64
+ pub sections: Vec<SectionRecord>,
65
+ }
66
+ ```
67
+
68
+ A fully resolved document -- the manifest plus the
69
+ actual content of each referenced section. Produced
70
+ by `kb-worker` when a caller requests a document
71
+ via `worker_retrieve_doc`. The `sections` vector
72
+ contains full `SectionRecord` entries (with content
73
+ bodies) in position order.
74
+
75
+ This type is used at the IPC boundary for the
76
+ `retrieve document` endpoint and in the `get_result`
77
+ response with `type: "content"`.
78
+
79
+ ## Methods
80
+
81
+ ### `DocumentManifest`
82
+
83
+ ```rust
84
+ impl DocumentManifest {
85
+ pub fn section_count(&self) -> u32;
86
+
87
+ pub fn contains(&self, kbid: &KbId) -> bool;
88
+
89
+ pub fn replace_section(
90
+ &mut self,
91
+ old_kbid: &KbId,
92
+ new_kbid: &KbId,
93
+ ) -> bool;
94
+
95
+ pub fn remove_section(
96
+ &mut self,
97
+ kbid: &KbId,
98
+ ) -> bool;
99
+
100
+ pub fn reposition(&mut self);
101
+ }
102
+ ```
103
+
104
+ #### `section_count`
105
+
106
+ Returns the number of section references.
107
+
108
+ #### `contains`
109
+
110
+ Checks whether a kb-id is in the section list.
111
+
112
+ #### `replace_section`
113
+
114
+ Replaces `old_kbid` with `new_kbid` in the section
115
+ list, preserving position. Returns `true` if the
116
+ replacement was made, `false` if `old_kbid` was not
117
+ found. Used by `fs-database` during section updates
118
+ (content-addressable storage means a content change
119
+ produces a new kb-id).
120
+
121
+ #### `remove_section`
122
+
123
+ Removes a section reference by kb-id. Returns `true`
124
+ if removed. Does **not** reposition remaining
125
+ sections -- call `reposition()` afterward if
126
+ contiguous positions are required.
127
+
128
+ #### `reposition`
129
+
130
+ Reassigns `position` values to `0, 1, 2, ...` based
131
+ on current vector order. Called after
132
+ `remove_section` to close gaps.
133
+
134
+ ## Trait Implementations
135
+
136
+ | Trait | Types |
137
+ |----------|-----------------------------------------|
138
+ | `Clone` | All three types |
139
+ | `Debug` | All three types |
140
+ | `Encode` | All three types (see [encode](../encode/traits.md)) |
141
+
142
+ ## Testing
143
+
144
+ Unit tests:
145
+
146
+ - `replace_section` swaps kb-ids correctly and
147
+ preserves position.
148
+ - `replace_section` returns `false` for missing
149
+ kb-ids.
150
+ - `remove_section` + `reposition` closes position
151
+ gaps.
152
+ - `contains` matches on kb-id.
153
+ - `Encode` round-trip for `DocumentManifest` and
154
+ `DocumentRecord` with multiple sections.
@@ -0,0 +1,22 @@
1
+ # encode -- Binary Encoding
2
+
3
+ *Compact binary serialization for structured data
4
+ passed through shared `WebAssembly.Memory` between
5
+ WASM modules.*
6
+
7
+ ## Source
8
+
9
+ `engine/crates/shared/src/encode/`
10
+
11
+ ## Responsibility
12
+
13
+ Defines the `Encode` trait and its implementations
14
+ for all shared types. Provides the wire format used
15
+ whenever structured data crosses a WASM module
16
+ boundary through shared memory.
17
+
18
+ ## Exports
19
+
20
+ - **[traits.md](traits.md)** -- `Encode` trait
21
+ definition, wire format specification, per-type
22
+ implementations, `DecodeError`.
@@ -0,0 +1,304 @@
1
+ # traits::encode -- Binary Encoding Trait
2
+
3
+ *Compact binary serialization trait for structured
4
+ data passed through shared `WebAssembly.Memory`
5
+ between WASM modules.*
6
+
7
+ ## File
8
+
9
+ `engine/crates/shared/src/encode/encode.rs`
10
+
11
+ ## Overview
12
+
13
+ When `kb-worker.wasm` passes a `QueryPlan` to
14
+ `fs-database.wasm`, or receives a `Vec<RawMatch>`
15
+ back, the data crosses a module boundary through
16
+ shared memory. JSON would work but adds parsing
17
+ overhead on every call. The `Encode` trait provides
18
+ a minimal, zero-copy-friendly binary format that
19
+ both sides compile from the same type definitions --
20
+ no schema negotiation, no version headers, no
21
+ self-description.
22
+
23
+ This is **not** a general-purpose serializer. It
24
+ handles only the specific data shapes defined in
25
+ `kbdb-shared`'s types. If a type changes, both the
26
+ encoder and decoder are recompiled from the same
27
+ source, so wire compatibility is guaranteed by the
28
+ build system.
29
+
30
+ ## Trait Definition
31
+
32
+ ```rust
33
+ pub trait Encode: Sized {
34
+ fn encode(&self, buf: &mut Vec<u8>);
35
+
36
+ fn decode(buf: &[u8])
37
+ -> Result<Self, DecodeError>;
38
+
39
+ fn encoded_size(&self) -> usize;
40
+ }
41
+ ```
42
+
43
+ ### `encode`
44
+
45
+ Appends the binary representation of `self` to
46
+ `buf`. The caller pre-allocates or grows the buffer.
47
+ Encoding is deterministic -- the same value always
48
+ produces the same bytes.
49
+
50
+ ### `decode`
51
+
52
+ Reads a value from the beginning of `buf`. Returns
53
+ the decoded value and advances past the consumed
54
+ bytes (via the return value's size). Returns
55
+ `DecodeError` if the buffer is too short or contains
56
+ invalid data.
57
+
58
+ ### `encoded_size`
59
+
60
+ Returns the number of bytes `encode` will append.
61
+ Used to pre-allocate buffers for write helpers in
62
+ [memory/functions](../memory/functions.md).
63
+
64
+ ## Wire Format
65
+
66
+ ### Scalars
67
+
68
+ | Rust type | Wire format | Bytes |
69
+ |-----------|---------------------|-------|
70
+ | `u8` | Raw byte | 1 |
71
+ | `u16` | Little-endian | 2 |
72
+ | `u32` | Little-endian | 4 |
73
+ | `u64` | Little-endian | 8 |
74
+ | `i32` | Little-endian | 4 |
75
+ | `f32` | Little-endian IEEE 754 | 4 |
76
+ | `bool` | `0x00` / `0x01` | 1 |
77
+
78
+ ### Strings
79
+
80
+ ```
81
+ [len: u32] [utf8_bytes: len]
82
+ ```
83
+
84
+ Length-prefixed. `len` is the byte count (not
85
+ character count). Empty strings encode as
86
+ `[0x00 0x00 0x00 0x00]` (4 bytes, zero length).
87
+
88
+ ### `Vec<T>`
89
+
90
+ ```
91
+ [count: u32] [item_0] [item_1] ... [item_n]
92
+ ```
93
+
94
+ Count-prefixed. Each item is encoded using `T`'s
95
+ `Encode` implementation. Empty vecs encode as
96
+ `[0x00 0x00 0x00 0x00]`.
97
+
98
+ ### `Option<T>`
99
+
100
+ ```
101
+ [tag: u8] [value: T]?
102
+ ```
103
+
104
+ - `0x00` = `None` (no value bytes follow).
105
+ - `0x01` = `Some` (value bytes follow).
106
+
107
+ ### Tuples `(A, B)`
108
+
109
+ ```
110
+ [a: A] [b: B]
111
+ ```
112
+
113
+ Concatenated, no separator. Both sides know the
114
+ types from the schema.
115
+
116
+ ### Enums
117
+
118
+ ```
119
+ [variant: u8] [fields...]
120
+ ```
121
+
122
+ One-byte discriminant followed by the variant's
123
+ fields (if any). Variant numbering follows
124
+ declaration order (`0, 1, 2, ...`).
125
+
126
+ ## Implementations
127
+
128
+ ### `KbId`
129
+
130
+ ```
131
+ [len: u32] [utf8_bytes: 26]
132
+ ```
133
+
134
+ Always 30 bytes (4-byte length prefix + 26-byte
135
+ identifier). The length prefix is always `26` but
136
+ included for consistency with the string format.
137
+
138
+ ### `Term`
139
+
140
+ ```
141
+ [len: u32] [utf8_bytes: len]
142
+ ```
143
+
144
+ Standard string encoding. Variable length.
145
+
146
+ ### `SectionType`
147
+
148
+ ```
149
+ [variant: u8] [mime_str...]?
150
+ ```
151
+
152
+ - `0x00` = `Text` (no additional data).
153
+ - `0x01` = `Code` + MIME string encoding.
154
+ - `0x02` = `Image` + MIME string encoding.
155
+
156
+ ### `QueryPlan`
157
+
158
+ ```
159
+ [terms: Vec<Term>]
160
+ [phrases: Vec<Vec<Term>>]
161
+ [exclusions: Vec<Term>]
162
+ [mode: u8]
163
+ ```
164
+
165
+ `mode`: `0x00` = `And`, `0x01` = `Or`.
166
+
167
+ ### `FieldTf`
168
+
169
+ ```
170
+ [heading: f32]
171
+ [body: f32]
172
+ [code: f32]
173
+ ```
174
+
175
+ Fixed 12 bytes.
176
+
177
+ ### `FieldTokenCounts`
178
+
179
+ ```
180
+ [heading: u32]
181
+ [body: u32]
182
+ [code: u32]
183
+ ```
184
+
185
+ Fixed 12 bytes.
186
+
187
+ ### `RawMatch`
188
+
189
+ ```
190
+ [kbid: KbId]
191
+ [field_tfs: Vec<(Term, FieldTf)>]
192
+ [positions: Vec<(Term, Vec<u32>)>]
193
+ [token_count: u32]
194
+ [field_token_counts: FieldTokenCounts]
195
+ ```
196
+
197
+ ### `SectionRecord`
198
+
199
+ ```
200
+ [kbid: KbId]
201
+ [docids: Vec<String>]
202
+ [section_type: SectionType]
203
+ [title: Option<String>]
204
+ [description: Option<String>]
205
+ [content: Vec<u8>] -- as [len: u32] [bytes]
206
+ [size: u32]
207
+ [created_at: String]
208
+ [checksum: String]
209
+ [token_count: u32]
210
+ [heading_token_count: u32]
211
+ [body_token_count: u32]
212
+ [code_token_count: u32]
213
+ ```
214
+
215
+ ### `DocumentManifest`
216
+
217
+ ```
218
+ [docid: String]
219
+ [title: String]
220
+ [created_at: String]
221
+ [sections: Vec<DocumentSection>]
222
+ ```
223
+
224
+ ### `DocumentSection`
225
+
226
+ ```
227
+ [kbid: KbId]
228
+ [position: u32]
229
+ ```
230
+
231
+ ### `CorpusStats`
232
+
233
+ ```
234
+ [total_sections: u32]
235
+ [total_terms: u32]
236
+ [avg_section_length: f32]
237
+ [avg_heading_length: f32]
238
+ [avg_body_length: f32]
239
+ [avg_code_length: f32]
240
+ ```
241
+
242
+ Fixed 24 bytes.
243
+
244
+ ## Error Type
245
+
246
+ ```rust
247
+ #[derive(Debug)]
248
+ pub enum DecodeError {
249
+ BufferTooShort {
250
+ expected: usize,
251
+ available: usize,
252
+ },
253
+ InvalidUtf8(usize),
254
+ InvalidVariant(u8),
255
+ }
256
+ ```
257
+
258
+ | Variant | Cause |
259
+ |------------------|--------------------------------|
260
+ | `BufferTooShort` | Not enough bytes to read the next field |
261
+ | `InvalidUtf8` | String bytes are not valid UTF-8 at the given offset |
262
+ | `InvalidVariant` | Enum discriminant is out of range |
263
+
264
+ ## Design Decisions
265
+
266
+ **Why not serde + bincode?** The `serde` ecosystem
267
+ adds significant binary size to WASM modules.
268
+ `bincode` pulls in `serde` as a dependency. The data
269
+ shapes here are small and known at compile time --
270
+ a hand-rolled trait with ~200 lines of impl is
271
+ lighter than the dependency tree.
272
+
273
+ **Why not JSON?** JSON parsing on every cross-module
274
+ call adds CPU overhead. The inverted index may
275
+ return thousands of `RawMatch` entries per query.
276
+ Binary encoding avoids string escaping, number
277
+ parsing, and allocation overhead.
278
+
279
+ **Why length-prefixed?** Simplicity. No delimiters
280
+ to escape, no backtracking. The decoder reads the
281
+ length, allocates, reads the payload, advances. Each
282
+ field is independent.
283
+
284
+ **Why little-endian?** WASM is little-endian. Native
285
+ byte order avoids byte-swapping.
286
+
287
+ ## Testing
288
+
289
+ Unit tests:
290
+
291
+ - Round-trip for every `Encode` implementation:
292
+ encode then decode produces an equal value.
293
+ - `encoded_size` matches actual `encode` output
294
+ length for all types.
295
+ - `DecodeError::BufferTooShort` when buffer is
296
+ truncated mid-field.
297
+ - `DecodeError::InvalidVariant` when enum
298
+ discriminant is out of range.
299
+ - `DecodeError::InvalidUtf8` when string bytes are
300
+ not valid UTF-8.
301
+ - Edge cases: empty `Vec`, `None` options, zero-
302
+ length strings, maximum `u32` values.
303
+ - Large payloads: `Vec<RawMatch>` with 1000 entries
304
+ encodes and decodes correctly.
@@ -0,0 +1,28 @@
1
+ # error -- Error Types
2
+
3
+ *Hierarchical error enums shared across all three
4
+ WASM modules, mapping to JSON-RPC 2.0 error codes at
5
+ the IPC boundary.*
6
+
7
+ ## Source
8
+
9
+ `engine/crates/shared/src/error/`
10
+
11
+ ## Responsibility
12
+
13
+ Defines the unified error hierarchy so that errors
14
+ originating in `fs-database` or `query-parser`
15
+ propagate through `kb-worker` to the TypeScript
16
+ daemon with consistent `From` conversions and
17
+ JSON-RPC 2.0 code mapping.
18
+
19
+ See [Worker Daemon -- Error Responses](
20
+ ../../../../goals/worker-daemon.md) for the JSON-RPC
21
+ 2.0 error codes at the IPC boundary.
22
+
23
+ ## Exports
24
+
25
+ - **[types.md](types.md)** -- `FsError`,
26
+ `IndexError`, `ParseError`, `WorkerError`. `From`
27
+ conversions, `Display`/`Error` implementations,
28
+ JSON-RPC 2.0 code mapping.