@dzhechkov/memory 0.2.9 → 0.2.11
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.
- package/.dz-manifest.json +253 -0
- package/README.md +35 -0
- package/dist/json-backend.d.ts.map +1 -1
- package/dist/json-backend.js +26 -4
- package/dist/json-backend.js.map +1 -1
- package/dist/sqlite-backend.d.ts.map +1 -1
- package/dist/sqlite-backend.js +25 -4
- package/dist/sqlite-backend.js.map +1 -1
- package/package.json +4 -2
- package/sbom.json +623 -0
- package/src/json-backend.ts +26 -4
- package/src/sqlite-backend.ts +25 -4
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest": {
|
|
3
|
+
"version": 1,
|
|
4
|
+
"pack": "memory",
|
|
5
|
+
"files": [
|
|
6
|
+
{
|
|
7
|
+
"path": "CHANGELOG.md",
|
|
8
|
+
"sha256": "bbdfa5df5277b9f8a6d30c6f63e70494f54998ab49ce2b60fab55f544f960440"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"path": "README.md",
|
|
12
|
+
"sha256": "536160fdb176de86b5bf005b640c93a002ee7084c346917c56a5a4d28a16eb37"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"path": "coverage/coverage-final.json",
|
|
16
|
+
"sha256": "c024d84c706519bcb3128e9fde07b894046af6a523d3945512584d2c8d3f686d"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"path": "coverage/coverage-summary.json",
|
|
20
|
+
"sha256": "feda9defafb15fc97d6cbc6b8462e87dfd5b029c2dbb1446e0cd0a3a0c8f5de5"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"path": "dist/backend.d.ts",
|
|
24
|
+
"sha256": "fe8a5ec858b83c2b6a8f7f242e212bb2e59acda775609e27ef37f5146eb5c455"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"path": "dist/backend.d.ts.map",
|
|
28
|
+
"sha256": "f41fade4e6b8d3dcbb730359683d75cb3de2ff9b83b2c8a8c6cfaee1b6f3b514"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"path": "dist/backend.js",
|
|
32
|
+
"sha256": "63af272c41a95713da9c544ff91e186e1e215e66ce938b8b046279ae94a8b919"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"path": "dist/backend.js.map",
|
|
36
|
+
"sha256": "45d1a1632bc5c276514608c3a77615b78c314d9addd632352c60dc565389d74c"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"path": "dist/bridge.d.ts",
|
|
40
|
+
"sha256": "94ae009717c9829eaa1e1526130592b1b68a86033f82ccb92686d13bc741bbcc"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"path": "dist/bridge.d.ts.map",
|
|
44
|
+
"sha256": "b29708fe02bd55d36d09e192954a6d648f42097f0870dcd43db3edf83e69512d"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"path": "dist/bridge.js",
|
|
48
|
+
"sha256": "9ae4a6d5baca14014d2857196af06ea7b6d2cde721707951cdeadad547c79b89"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"path": "dist/bridge.js.map",
|
|
52
|
+
"sha256": "f767581b00912afc6786cf3791ba561ba3b047cd89ba38e66e6b9ef590bb7b9c"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"path": "dist/cascade.d.ts",
|
|
56
|
+
"sha256": "0b7c8c4609a418bebc1645b8b253003d978c6353472e2bbdc942074f28923103"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"path": "dist/cascade.d.ts.map",
|
|
60
|
+
"sha256": "69665ba798f8a935200dd8e0e68276a8c6ed5154bb6a0b0d0cd420d6e0b90ae3"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"path": "dist/cascade.js",
|
|
64
|
+
"sha256": "9cb0c217388c6b35006cec6ab559b3c541f0420a3a16e07e9d783d5e4a4699ee"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"path": "dist/cascade.js.map",
|
|
68
|
+
"sha256": "f1783db779e9d3bbbfaafddce954a05a2b90d5bdd5e92afe18592e48d4858516"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"path": "dist/dreaming.d.ts",
|
|
72
|
+
"sha256": "54aa894782dead661ae22c0febcb3a59d48bb4820bb9e7432857b742cd802276"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"path": "dist/dreaming.d.ts.map",
|
|
76
|
+
"sha256": "c6e730ce87ac42632ef9eb4bb3a504b3c270eb6e7cf02e327394840f15092826"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"path": "dist/dreaming.js",
|
|
80
|
+
"sha256": "393e22def63f23eca261f965567ba58ffc90eded8fbc24e6448aa5e828fdbc78"
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"path": "dist/dreaming.js.map",
|
|
84
|
+
"sha256": "6b192b2bb1a73016d0741365c3c44e129f06a616ae9a0e90d12a90af8c3cb0bb"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"path": "dist/index.d.ts",
|
|
88
|
+
"sha256": "9d855df88b28e860102b42a0b899f7a5a561c3e3d8cf3fc48cb3366a15049c30"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"path": "dist/index.d.ts.map",
|
|
92
|
+
"sha256": "5a0b747b1858bdaacab8c086a24005ce0ec98d8d4ca60ea42e8c5f79ce9c3719"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"path": "dist/index.js",
|
|
96
|
+
"sha256": "8b73ac944a586829e8d73e81d9c3c210dc13124067fb5742c953cc4fda1fcba9"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"path": "dist/index.js.map",
|
|
100
|
+
"sha256": "a86663fb3aeccf123b6b2adbc6a9a4a70da9a3887c75514a49d1bf95837253d3"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"path": "dist/json-backend.d.ts",
|
|
104
|
+
"sha256": "80d304c83f8a6c0e6b3e91dc02e291cb3e744ee0b7d7bc273b40bd16ad2cb449"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"path": "dist/json-backend.d.ts.map",
|
|
108
|
+
"sha256": "79f7681f3b05119c6db9d59da05da8598dd82a60cc028e70c3954394e1a1601e"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"path": "dist/json-backend.js",
|
|
112
|
+
"sha256": "7d0e715ee1e0c93904e15abaec70a17b82333e2f9ac55894f0ca675279454821"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"path": "dist/json-backend.js.map",
|
|
116
|
+
"sha256": "c34734f7386e902a76d78aeec3930ce5b68796392559e9a22efbc4cc5de90650"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"path": "dist/reflexion.d.ts",
|
|
120
|
+
"sha256": "01ceaaee37c402a323cd9afa258ac505f9458048c75c40f2d0f9b5465b784a02"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"path": "dist/reflexion.d.ts.map",
|
|
124
|
+
"sha256": "faf6c875ec80a392ddee2d1a38e4ceca33d1c82477b48488a35de0050818aa0e"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"path": "dist/reflexion.js",
|
|
128
|
+
"sha256": "97a16866c30a79f6e2e9b0ae43a2d60b3e70c922a78d3325f729e98f8fbbfc0d"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"path": "dist/reflexion.js.map",
|
|
132
|
+
"sha256": "c784199286137919544d9fbe957cf8405109111a8748e2409555d408e56e05f0"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"path": "dist/sqlite-backend.d.ts",
|
|
136
|
+
"sha256": "bcee527422ab9692082ad26f6276f47f9bce86ed5279439f67a0823da1b93387"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"path": "dist/sqlite-backend.d.ts.map",
|
|
140
|
+
"sha256": "1d8187924617dc91f55c23c624d4d4bc7ce82dc6059c33e87cf78c2c3837547b"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"path": "dist/sqlite-backend.js",
|
|
144
|
+
"sha256": "056c9dd4f11234c2e4a2af906ccbd9022cc3f11c20fdddd2465eca260f93b104"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"path": "dist/sqlite-backend.js.map",
|
|
148
|
+
"sha256": "a34bdb236db9d469e6c4dde6d50832438aca0d085f47a12a9ad43258a4524e12"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"path": "dist/sqlite-probe.d.ts",
|
|
152
|
+
"sha256": "6a649e48cbaad5c900e2bb95e11f4a1f4e33dc9dd8165cab290659c37dcdb1d6"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"path": "dist/sqlite-probe.d.ts.map",
|
|
156
|
+
"sha256": "982ea953e1a80deb38c6c80e1f150f1bd410e97ba83480b7d4f7249e98763562"
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"path": "dist/sqlite-probe.js",
|
|
160
|
+
"sha256": "b6aaa054f32385874b50bcce779d98c33d16dc2fab73a8bf48691b18fdc25e3e"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"path": "dist/sqlite-probe.js.map",
|
|
164
|
+
"sha256": "083e083ff09058e6802bae5d1415b53d39218a6bf1f31cd6d041e10dbeae9c61"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"path": "package.json",
|
|
168
|
+
"sha256": "b287a6ceae333b4a88beea011de37eb2fe580841c925d57fa4378c1d7225168d"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"path": "src/backend.ts",
|
|
172
|
+
"sha256": "77fe67ce082757e38117e8d6a2598d705f6f665a696474608bcfb0f7739ef15e"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"path": "src/bridge.ts",
|
|
176
|
+
"sha256": "f1fce2221d78a9cae4063e46cd87d2120aeaad5d31d9c3845cb2a01dd420ae6a"
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
"path": "src/cascade.ts",
|
|
180
|
+
"sha256": "e34c41de72524417a60a530aa988b33b7be7ebc33a4ac415595f448652882ced"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"path": "src/dreaming.ts",
|
|
184
|
+
"sha256": "f23084fe7ba68bdf8e913da65c12704a2d2a33ae66e120c712c3c2d59ca83ec8"
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"path": "src/index.ts",
|
|
188
|
+
"sha256": "34c68dbea4be8c8108dd6aff0e49690484894c56f53967e07c92205b8d57ff64"
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"path": "src/json-backend.ts",
|
|
192
|
+
"sha256": "a42aae75c2760818b7f206c194db3328e2d339d455cca0d8b656c1bbb394335c"
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"path": "src/reflexion.ts",
|
|
196
|
+
"sha256": "1e22f854d7f7f216be8b1062f2264be241f3cf46ddd5b0d3b39cd4941c43890c"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"path": "src/sqlite-backend.ts",
|
|
200
|
+
"sha256": "85159ceb6b5dbd21f66b39a8e522097b363c699986b8209acf90281fb490c7ac"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"path": "src/sqlite-probe.ts",
|
|
204
|
+
"sha256": "28bc13308f61bc553fc36a9c0efcf382522769de20769f3fcef8c3bbb4734b7e"
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"path": "stryker.config.json",
|
|
208
|
+
"sha256": "2f8f92b4368e876e88113bc49b13a46a705d9ba0f64b6852ae111b48c77fd16f"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"path": "test/bridge.test.ts",
|
|
212
|
+
"sha256": "4369595f468d204d32bb561a6cc00e096092dcfff0d1693417741c3a0281f647"
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"path": "test/cascade.test.ts",
|
|
216
|
+
"sha256": "c7b429025794a914674b8cace13ccc1c53dae4ac6b4ed16620c75a4c9ab7d8df"
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"path": "test/dreaming.test.ts",
|
|
220
|
+
"sha256": "c189e9313e4c45ea0302ee31f2b5b3952b6e71cc3b9e3d2c3b1dd396db66d58e"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"path": "test/json-backend.test.ts",
|
|
224
|
+
"sha256": "6914ddc262e515c4763d097871eb8a5ec9a0667b379fa61a214c10f2f26898b3"
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"path": "test/reflexion.test.ts",
|
|
228
|
+
"sha256": "e013324ab5d227c501f5a24944f0caca915b4cafffcc6aacccbe5010685f30a4"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"path": "test/sqlite-backend.test.ts",
|
|
232
|
+
"sha256": "ce44f28c4607facbf23e0528d1d4c12a7b755fe4eda37ce547081d786e77e44a"
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"path": "test/sqlite-probe.test.ts",
|
|
236
|
+
"sha256": "05320e156305d3e706df5bcc288661e1258abbb827cf86b888351c98696457a5"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"path": "test/tokenize-unicode.test.ts",
|
|
240
|
+
"sha256": "05d66ccd90004382910ed106f884d3fa99af90cb427501583c0e373d37df3bc4"
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"path": "tsconfig.json",
|
|
244
|
+
"sha256": "e80ef2911c3347a713dc3dca6a5f6034d91e938e58e71345ea920dd9833bcdbb"
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"path": "vitest.config.ts",
|
|
248
|
+
"sha256": "a6ffc6172b50a3a59010f8f8c66e2204e7d298b62a7f2bc5de33cbf39c99899d"
|
|
249
|
+
}
|
|
250
|
+
]
|
|
251
|
+
},
|
|
252
|
+
"signature": "V5qdESB+Xc5cG1EEDwHhOxdDKy+4zdcQhCGosI/UFANKtYrfowhl6+YViflo3Ps01ApEkhW6SOJwg2cEy3xeDQ=="
|
|
253
|
+
}
|
package/README.md
CHANGED
|
@@ -13,6 +13,25 @@ host memory files.
|
|
|
13
13
|
| `reflexion` | `Reflexion` | Record skill outcomes (`record(skillId, outcome, score)`); rank skills |
|
|
14
14
|
| `bridge` | `MemoryBridge`, `importMemoryMarkdown` | Import a host memory markdown file into `MemoryRecord`s |
|
|
15
15
|
|
|
16
|
+
## A query that matched nothing returns nothing
|
|
17
|
+
|
|
18
|
+
Both backends' keyword path used to RANK by term overlap and never EXCLUDE, so every query came back
|
|
19
|
+
with the whole store, reordered. MEASURED on two records (`hello world`, `another record`):
|
|
20
|
+
`zebrafish` returned both, and so did `hello`, which matches exactly one. With no matches the sort
|
|
21
|
+
degenerates into confidence order — which is how it looked like "ranking by confidence".
|
|
22
|
+
|
|
23
|
+
Now the two situations are separated:
|
|
24
|
+
|
|
25
|
+
| The query | What comes back |
|
|
26
|
+
|---|---|
|
|
27
|
+
| has usable terms and matches nothing | nothing |
|
|
28
|
+
| has usable terms and matches some records | only those |
|
|
29
|
+
| has NO usable terms (punctuation, single characters, no text) | the whole store, ranked by confidence — unchanged, because no filter was expressible |
|
|
30
|
+
|
|
31
|
+
The filter is `overlap > 0`, never a tuned threshold: a weak match is still a match, and zero overlap
|
|
32
|
+
is not a weak match. Both backends take the same rule, so a store's answers never depend on which one
|
|
33
|
+
is installed. Note that "matched" is measured over the record's TEXT and its `skillId`.
|
|
34
|
+
|
|
16
35
|
## Backend strategy
|
|
17
36
|
|
|
18
37
|
The default `JsonFileBackend` is **pure JavaScript with zero dependencies** — no
|
|
@@ -28,3 +47,19 @@ are intentionally *not* hard dependencies — see
|
|
|
28
47
|
## Status
|
|
29
48
|
|
|
30
49
|
`0.1.0` — alpha, part of the `extended-a-migration` feature (Phase 7).
|
|
50
|
+
|
|
51
|
+
## Status
|
|
52
|
+
|
|
53
|
+
`0.2.11` — a query that matched nothing returns nothing (see above). `0.2.10` — the lexical tokenizer is Unicode-aware. It split on `[^a-z0-9]+`, so every non-Latin letter
|
|
54
|
+
was a separator and a Cyrillic query produced **zero terms**: the FTS5 branch was skipped, relevance
|
|
55
|
+
degenerated to a constant for every record, and the confidence tie-break decided the order. MEASURED
|
|
56
|
+
2026-08-21 on a 267-record store — RU top-1 **0/10** against EN **10/10**, while 63% of real recall
|
|
57
|
+
traffic is Cyrillic. The class is now `[^\p{L}\p{N}]+/u` in both backends, and the one-character
|
|
58
|
+
floor counts code points rather than UTF-16 units.
|
|
59
|
+
|
|
60
|
+
No migration is needed: FTS5's own tokenizer always indexed the text correctly — only the query was
|
|
61
|
+
being stripped of its terms on the way out.
|
|
62
|
+
|
|
63
|
+
**Unchanged on purpose:** a query that yields no terms still returns the store. That behaviour is
|
|
64
|
+
pinned by four existing tests which comment it as intended, so it is a contract to be changed by
|
|
65
|
+
decision, not folded into an alphabet fix.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-backend.d.ts","sourceRoot":"","sources":["../src/json-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"json-backend.d.ts","sourceRoot":"","sources":["../src/json-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAuC7E,2CAA2C;AAC3C,MAAM,WAAW,sBAAsB;IACrC,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,sFAAsF;AACtF,qBAAa,eAAgB,YAAW,aAAa;IACnD,QAAQ,CAAC,IAAI,eAAe;IAE5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAC3D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;gBAElC,OAAO,GAAE,sBAA2B;IAIhD,6EAA6E;WAChE,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAM7D;;;;OAIG;IACH,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe;IAMlD,GAAG,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAKxC,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAIlD,4EAA4E;IAC5E,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,EAAE;IAwB7C,GAAG,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAI9B,+CAA+C;IAC/C,OAAO,IAAI,YAAY,EAAE;IAIzB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjC,gFAAgF;IAChF,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI5B,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAIxB;;;;;;;OAOG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAerB,qFAAqF;IACrF,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrB,gDAAgD;IAChD,QAAQ,IAAI,IAAI;CAMjB"}
|
package/dist/json-backend.js
CHANGED
|
@@ -10,12 +10,28 @@
|
|
|
10
10
|
import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
11
11
|
import { dirname } from 'node:path';
|
|
12
12
|
const DEFAULT_LIMIT = 20;
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Split text into lowercase word tokens of length > 1.
|
|
15
|
+
*
|
|
16
|
+
* The class is `\p{L}\p{N}`, not `a-z0-9`. Until 2026-08-21 it was ASCII-only, so every non-Latin
|
|
17
|
+
* letter was a SEPARATOR and a Cyrillic query produced ZERO tokens — the FTS5 branch was then skipped
|
|
18
|
+
* entirely, `relevanceOf` returned 0 for every record, and the sort collapsed onto its confidence
|
|
19
|
+
* tie-break. MEASURED on a 267-record clone of the real brain: RU top-1 0/10 against EN 10/10, while
|
|
20
|
+
* 63% of real recall traffic is Cyrillic. The INDEX was never wrong — FTS5's own tokenizer handles
|
|
21
|
+
* Cyrillic — so nothing on disk needed migrating; only the query was being stripped of its terms.
|
|
22
|
+
*
|
|
23
|
+
* `\p{L}` admits letters and `\p{N}` digits; it does NOT admit `"`, `*`, `(` or any other FTS5
|
|
24
|
+
* operator, which is what keeps the joined terms safe to interpolate into a MATCH expression.
|
|
25
|
+
*/
|
|
14
26
|
function tokenize(text) {
|
|
15
27
|
return text
|
|
16
28
|
.toLowerCase()
|
|
17
|
-
.split(/[
|
|
18
|
-
.
|
|
29
|
+
.split(/[^\p{L}\p{N}]+/u)
|
|
30
|
+
// Count CODE POINTS, not UTF-16 units. `token.length` counts units, so a single astral letter
|
|
31
|
+
// (`𐐀`, one character, two units) would slip past a floor meant to reject one-character words —
|
|
32
|
+
// an accidental threshold change smuggled in by the alphabet change (cross-family review,
|
|
33
|
+
// 2026-08-21). The promise was "the alphabet, not the thresholds"; this keeps it.
|
|
34
|
+
.filter((token) => [...token].length > 1);
|
|
19
35
|
}
|
|
20
36
|
/** Count how many query terms appear in a record's text/skillId. */
|
|
21
37
|
function relevanceOf(record, terms) {
|
|
@@ -73,7 +89,13 @@ export class JsonFileBackend {
|
|
|
73
89
|
.sort((a, b) => b.relevance - a.relevance ||
|
|
74
90
|
b.record.score - a.record.score ||
|
|
75
91
|
b.record.timestamp.localeCompare(a.record.timestamp));
|
|
76
|
-
|
|
92
|
+
// ASKING and finding nothing returns nothing. Without this the keyword path RANKS by overlap and
|
|
93
|
+
// never EXCLUDES, so every query returned the whole store reordered — MEASURED on two records:
|
|
94
|
+
// `zebrafish` (matches neither) AND `hello` (matches one) both returned both. With no usable
|
|
95
|
+
// terms there was nothing to match on, and returning the store ranked by confidence stays the
|
|
96
|
+
// right answer; that distinction is the whole decision (ADR-001).
|
|
97
|
+
const filtered = terms.length > 0 ? ranked.filter((entry) => entry.relevance > 0) : ranked;
|
|
98
|
+
return filtered.slice(0, limit).map((entry) => entry.record);
|
|
77
99
|
}
|
|
78
100
|
all() {
|
|
79
101
|
return Promise.resolve(this.allSync());
|
package/dist/json-backend.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-backend.js","sourceRoot":"","sources":["../src/json-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACjG,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB
|
|
1
|
+
{"version":3,"file":"json-backend.js","sourceRoot":"","sources":["../src/json-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-backend.d.ts","sourceRoot":"","sources":["../src/sqlite-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"sqlite-backend.d.ts","sourceRoot":"","sources":["../src/sqlite-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAsG7E,iCAAiC;AACjC,MAAM,WAAW,oBAAoB;IACnC,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,qBAAa,aAAc,YAAW,aAAa;IACjD,QAAQ,CAAC,IAAI,YAAY;IAEzB,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAM;IACzB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAM;IACjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAM;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAM;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAM;IAChC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAM;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkB;IAChD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAkB;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;gBAEtB,EAAE,EAAE,GAAG;IAyBnB,4DAA4D;IAC5D,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa;IAW5C,GAAG,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAaxC,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAIlD;;;;OAIG;IACH,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,EAAE;IA4D7C,GAAG,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAI9B,6CAA6C;IAC7C,OAAO,IAAI,YAAY,EAAE;IAIzB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjC,sIAAsI;IACtI,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI5B,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAIxB,oEAAoE;IACpE,OAAO,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI;IAiB/C,qCAAqC;IACrC,KAAK,IAAI,IAAI;CAGd"}
|
package/dist/sqlite-backend.js
CHANGED
|
@@ -12,12 +12,28 @@ import { mkdirSync } from 'node:fs';
|
|
|
12
12
|
import { dirname } from 'node:path';
|
|
13
13
|
const require = createRequire(import.meta.url);
|
|
14
14
|
const DEFAULT_LIMIT = 20;
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Split text into lowercase word tokens of length > 1.
|
|
17
|
+
*
|
|
18
|
+
* The class is `\p{L}\p{N}`, not `a-z0-9`. Until 2026-08-21 it was ASCII-only, so every non-Latin
|
|
19
|
+
* letter was a SEPARATOR and a Cyrillic query produced ZERO tokens — the FTS5 branch was then skipped
|
|
20
|
+
* entirely, `relevanceOf` returned 0 for every record, and the sort collapsed onto its confidence
|
|
21
|
+
* tie-break. MEASURED on a 267-record clone of the real brain: RU top-1 0/10 against EN 10/10, while
|
|
22
|
+
* 63% of real recall traffic is Cyrillic. The INDEX was never wrong — FTS5's own tokenizer handles
|
|
23
|
+
* Cyrillic — so nothing on disk needed migrating; only the query was being stripped of its terms.
|
|
24
|
+
*
|
|
25
|
+
* `\p{L}` admits letters and `\p{N}` digits; it does NOT admit `"`, `*`, `(` or any other FTS5
|
|
26
|
+
* operator, which is what keeps the joined terms safe to interpolate into a MATCH expression.
|
|
27
|
+
*/
|
|
16
28
|
function tokenize(text) {
|
|
17
29
|
return text
|
|
18
30
|
.toLowerCase()
|
|
19
|
-
.split(/[
|
|
20
|
-
.
|
|
31
|
+
.split(/[^\p{L}\p{N}]+/u)
|
|
32
|
+
// Count CODE POINTS, not UTF-16 units. `token.length` counts units, so a single astral letter
|
|
33
|
+
// (`𐐀`, one character, two units) would slip past a floor meant to reject one-character words —
|
|
34
|
+
// an accidental threshold change smuggled in by the alphabet change (cross-family review,
|
|
35
|
+
// 2026-08-21). The promise was "the alphabet, not the thresholds"; this keeps it.
|
|
36
|
+
.filter((token) => [...token].length > 1);
|
|
21
37
|
}
|
|
22
38
|
/** Count how many query terms appear in a record's text/skillId. */
|
|
23
39
|
function relevanceOf(record, terms) {
|
|
@@ -193,7 +209,12 @@ export class SqliteBackend {
|
|
|
193
209
|
.sort((a, b) => b.relevance - a.relevance ||
|
|
194
210
|
b.record.score - a.record.score ||
|
|
195
211
|
b.record.timestamp.localeCompare(a.record.timestamp));
|
|
196
|
-
|
|
212
|
+
// The SAME guard the JSON backend applies, so a store's answers never depend on which backend is
|
|
213
|
+
// installed. This is the keyword FALLBACK; the FTS5 path above already returns zero honestly and
|
|
214
|
+
// is untouched. With no usable terms there was nothing to match on, so the store still comes back
|
|
215
|
+
// ranked by confidence — that distinction is the whole decision (ADR-001).
|
|
216
|
+
const filtered = terms.length > 0 ? ranked.filter((entry) => entry.relevance > 0) : ranked;
|
|
217
|
+
return filtered.slice(0, limit).map((entry) => entry.record);
|
|
197
218
|
}
|
|
198
219
|
all() {
|
|
199
220
|
return Promise.resolve(this.allSync());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-backend.js","sourceRoot":"","sources":["../src/sqlite-backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB
|
|
1
|
+
{"version":3,"file":"sqlite-backend.js","sourceRoot":"","sources":["../src/sqlite-backend.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dzhechkov/memory",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"description": "Harness memory layer - backend cascade, Reflexion feedback, and the host-memory bridge.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
"files": [
|
|
23
23
|
"dist",
|
|
24
24
|
"src",
|
|
25
|
-
"README.md"
|
|
25
|
+
"README.md",
|
|
26
|
+
".dz-manifest.json",
|
|
27
|
+
"sbom.json"
|
|
26
28
|
],
|
|
27
29
|
"optionalDependencies": {
|
|
28
30
|
"better-sqlite3": "^11.0.0"
|
package/sbom.json
ADDED
|
@@ -0,0 +1,623 @@
|
|
|
1
|
+
{
|
|
2
|
+
"bomFormat": "CycloneDX",
|
|
3
|
+
"specVersion": "1.5",
|
|
4
|
+
"version": 1,
|
|
5
|
+
"metadata": {
|
|
6
|
+
"component": {
|
|
7
|
+
"type": "library",
|
|
8
|
+
"name": "memory"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"components": [
|
|
12
|
+
{
|
|
13
|
+
"type": "file",
|
|
14
|
+
"name": "CHANGELOG.md",
|
|
15
|
+
"hashes": [
|
|
16
|
+
{
|
|
17
|
+
"alg": "SHA-256",
|
|
18
|
+
"content": "bbdfa5df5277b9f8a6d30c6f63e70494f54998ab49ce2b60fab55f544f960440"
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"type": "file",
|
|
24
|
+
"name": "README.md",
|
|
25
|
+
"hashes": [
|
|
26
|
+
{
|
|
27
|
+
"alg": "SHA-256",
|
|
28
|
+
"content": "536160fdb176de86b5bf005b640c93a002ee7084c346917c56a5a4d28a16eb37"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"type": "file",
|
|
34
|
+
"name": "coverage/coverage-final.json",
|
|
35
|
+
"hashes": [
|
|
36
|
+
{
|
|
37
|
+
"alg": "SHA-256",
|
|
38
|
+
"content": "c024d84c706519bcb3128e9fde07b894046af6a523d3945512584d2c8d3f686d"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"type": "file",
|
|
44
|
+
"name": "coverage/coverage-summary.json",
|
|
45
|
+
"hashes": [
|
|
46
|
+
{
|
|
47
|
+
"alg": "SHA-256",
|
|
48
|
+
"content": "feda9defafb15fc97d6cbc6b8462e87dfd5b029c2dbb1446e0cd0a3a0c8f5de5"
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"type": "file",
|
|
54
|
+
"name": "dist/backend.d.ts",
|
|
55
|
+
"hashes": [
|
|
56
|
+
{
|
|
57
|
+
"alg": "SHA-256",
|
|
58
|
+
"content": "fe8a5ec858b83c2b6a8f7f242e212bb2e59acda775609e27ef37f5146eb5c455"
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"type": "file",
|
|
64
|
+
"name": "dist/backend.d.ts.map",
|
|
65
|
+
"hashes": [
|
|
66
|
+
{
|
|
67
|
+
"alg": "SHA-256",
|
|
68
|
+
"content": "f41fade4e6b8d3dcbb730359683d75cb3de2ff9b83b2c8a8c6cfaee1b6f3b514"
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"type": "file",
|
|
74
|
+
"name": "dist/backend.js",
|
|
75
|
+
"hashes": [
|
|
76
|
+
{
|
|
77
|
+
"alg": "SHA-256",
|
|
78
|
+
"content": "63af272c41a95713da9c544ff91e186e1e215e66ce938b8b046279ae94a8b919"
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"type": "file",
|
|
84
|
+
"name": "dist/backend.js.map",
|
|
85
|
+
"hashes": [
|
|
86
|
+
{
|
|
87
|
+
"alg": "SHA-256",
|
|
88
|
+
"content": "45d1a1632bc5c276514608c3a77615b78c314d9addd632352c60dc565389d74c"
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"type": "file",
|
|
94
|
+
"name": "dist/bridge.d.ts",
|
|
95
|
+
"hashes": [
|
|
96
|
+
{
|
|
97
|
+
"alg": "SHA-256",
|
|
98
|
+
"content": "94ae009717c9829eaa1e1526130592b1b68a86033f82ccb92686d13bc741bbcc"
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"type": "file",
|
|
104
|
+
"name": "dist/bridge.d.ts.map",
|
|
105
|
+
"hashes": [
|
|
106
|
+
{
|
|
107
|
+
"alg": "SHA-256",
|
|
108
|
+
"content": "b29708fe02bd55d36d09e192954a6d648f42097f0870dcd43db3edf83e69512d"
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"type": "file",
|
|
114
|
+
"name": "dist/bridge.js",
|
|
115
|
+
"hashes": [
|
|
116
|
+
{
|
|
117
|
+
"alg": "SHA-256",
|
|
118
|
+
"content": "9ae4a6d5baca14014d2857196af06ea7b6d2cde721707951cdeadad547c79b89"
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"type": "file",
|
|
124
|
+
"name": "dist/bridge.js.map",
|
|
125
|
+
"hashes": [
|
|
126
|
+
{
|
|
127
|
+
"alg": "SHA-256",
|
|
128
|
+
"content": "f767581b00912afc6786cf3791ba561ba3b047cd89ba38e66e6b9ef590bb7b9c"
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"type": "file",
|
|
134
|
+
"name": "dist/cascade.d.ts",
|
|
135
|
+
"hashes": [
|
|
136
|
+
{
|
|
137
|
+
"alg": "SHA-256",
|
|
138
|
+
"content": "0b7c8c4609a418bebc1645b8b253003d978c6353472e2bbdc942074f28923103"
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"type": "file",
|
|
144
|
+
"name": "dist/cascade.d.ts.map",
|
|
145
|
+
"hashes": [
|
|
146
|
+
{
|
|
147
|
+
"alg": "SHA-256",
|
|
148
|
+
"content": "69665ba798f8a935200dd8e0e68276a8c6ed5154bb6a0b0d0cd420d6e0b90ae3"
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"type": "file",
|
|
154
|
+
"name": "dist/cascade.js",
|
|
155
|
+
"hashes": [
|
|
156
|
+
{
|
|
157
|
+
"alg": "SHA-256",
|
|
158
|
+
"content": "9cb0c217388c6b35006cec6ab559b3c541f0420a3a16e07e9d783d5e4a4699ee"
|
|
159
|
+
}
|
|
160
|
+
]
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"type": "file",
|
|
164
|
+
"name": "dist/cascade.js.map",
|
|
165
|
+
"hashes": [
|
|
166
|
+
{
|
|
167
|
+
"alg": "SHA-256",
|
|
168
|
+
"content": "f1783db779e9d3bbbfaafddce954a05a2b90d5bdd5e92afe18592e48d4858516"
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"type": "file",
|
|
174
|
+
"name": "dist/dreaming.d.ts",
|
|
175
|
+
"hashes": [
|
|
176
|
+
{
|
|
177
|
+
"alg": "SHA-256",
|
|
178
|
+
"content": "54aa894782dead661ae22c0febcb3a59d48bb4820bb9e7432857b742cd802276"
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"type": "file",
|
|
184
|
+
"name": "dist/dreaming.d.ts.map",
|
|
185
|
+
"hashes": [
|
|
186
|
+
{
|
|
187
|
+
"alg": "SHA-256",
|
|
188
|
+
"content": "c6e730ce87ac42632ef9eb4bb3a504b3c270eb6e7cf02e327394840f15092826"
|
|
189
|
+
}
|
|
190
|
+
]
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"type": "file",
|
|
194
|
+
"name": "dist/dreaming.js",
|
|
195
|
+
"hashes": [
|
|
196
|
+
{
|
|
197
|
+
"alg": "SHA-256",
|
|
198
|
+
"content": "393e22def63f23eca261f965567ba58ffc90eded8fbc24e6448aa5e828fdbc78"
|
|
199
|
+
}
|
|
200
|
+
]
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"type": "file",
|
|
204
|
+
"name": "dist/dreaming.js.map",
|
|
205
|
+
"hashes": [
|
|
206
|
+
{
|
|
207
|
+
"alg": "SHA-256",
|
|
208
|
+
"content": "6b192b2bb1a73016d0741365c3c44e129f06a616ae9a0e90d12a90af8c3cb0bb"
|
|
209
|
+
}
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
"type": "file",
|
|
214
|
+
"name": "dist/index.d.ts",
|
|
215
|
+
"hashes": [
|
|
216
|
+
{
|
|
217
|
+
"alg": "SHA-256",
|
|
218
|
+
"content": "9d855df88b28e860102b42a0b899f7a5a561c3e3d8cf3fc48cb3366a15049c30"
|
|
219
|
+
}
|
|
220
|
+
]
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"type": "file",
|
|
224
|
+
"name": "dist/index.d.ts.map",
|
|
225
|
+
"hashes": [
|
|
226
|
+
{
|
|
227
|
+
"alg": "SHA-256",
|
|
228
|
+
"content": "5a0b747b1858bdaacab8c086a24005ce0ec98d8d4ca60ea42e8c5f79ce9c3719"
|
|
229
|
+
}
|
|
230
|
+
]
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"type": "file",
|
|
234
|
+
"name": "dist/index.js",
|
|
235
|
+
"hashes": [
|
|
236
|
+
{
|
|
237
|
+
"alg": "SHA-256",
|
|
238
|
+
"content": "8b73ac944a586829e8d73e81d9c3c210dc13124067fb5742c953cc4fda1fcba9"
|
|
239
|
+
}
|
|
240
|
+
]
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
"type": "file",
|
|
244
|
+
"name": "dist/index.js.map",
|
|
245
|
+
"hashes": [
|
|
246
|
+
{
|
|
247
|
+
"alg": "SHA-256",
|
|
248
|
+
"content": "a86663fb3aeccf123b6b2adbc6a9a4a70da9a3887c75514a49d1bf95837253d3"
|
|
249
|
+
}
|
|
250
|
+
]
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
"type": "file",
|
|
254
|
+
"name": "dist/json-backend.d.ts",
|
|
255
|
+
"hashes": [
|
|
256
|
+
{
|
|
257
|
+
"alg": "SHA-256",
|
|
258
|
+
"content": "80d304c83f8a6c0e6b3e91dc02e291cb3e744ee0b7d7bc273b40bd16ad2cb449"
|
|
259
|
+
}
|
|
260
|
+
]
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"type": "file",
|
|
264
|
+
"name": "dist/json-backend.d.ts.map",
|
|
265
|
+
"hashes": [
|
|
266
|
+
{
|
|
267
|
+
"alg": "SHA-256",
|
|
268
|
+
"content": "79f7681f3b05119c6db9d59da05da8598dd82a60cc028e70c3954394e1a1601e"
|
|
269
|
+
}
|
|
270
|
+
]
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"type": "file",
|
|
274
|
+
"name": "dist/json-backend.js",
|
|
275
|
+
"hashes": [
|
|
276
|
+
{
|
|
277
|
+
"alg": "SHA-256",
|
|
278
|
+
"content": "7d0e715ee1e0c93904e15abaec70a17b82333e2f9ac55894f0ca675279454821"
|
|
279
|
+
}
|
|
280
|
+
]
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
"type": "file",
|
|
284
|
+
"name": "dist/json-backend.js.map",
|
|
285
|
+
"hashes": [
|
|
286
|
+
{
|
|
287
|
+
"alg": "SHA-256",
|
|
288
|
+
"content": "c34734f7386e902a76d78aeec3930ce5b68796392559e9a22efbc4cc5de90650"
|
|
289
|
+
}
|
|
290
|
+
]
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"type": "file",
|
|
294
|
+
"name": "dist/reflexion.d.ts",
|
|
295
|
+
"hashes": [
|
|
296
|
+
{
|
|
297
|
+
"alg": "SHA-256",
|
|
298
|
+
"content": "01ceaaee37c402a323cd9afa258ac505f9458048c75c40f2d0f9b5465b784a02"
|
|
299
|
+
}
|
|
300
|
+
]
|
|
301
|
+
},
|
|
302
|
+
{
|
|
303
|
+
"type": "file",
|
|
304
|
+
"name": "dist/reflexion.d.ts.map",
|
|
305
|
+
"hashes": [
|
|
306
|
+
{
|
|
307
|
+
"alg": "SHA-256",
|
|
308
|
+
"content": "faf6c875ec80a392ddee2d1a38e4ceca33d1c82477b48488a35de0050818aa0e"
|
|
309
|
+
}
|
|
310
|
+
]
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"type": "file",
|
|
314
|
+
"name": "dist/reflexion.js",
|
|
315
|
+
"hashes": [
|
|
316
|
+
{
|
|
317
|
+
"alg": "SHA-256",
|
|
318
|
+
"content": "97a16866c30a79f6e2e9b0ae43a2d60b3e70c922a78d3325f729e98f8fbbfc0d"
|
|
319
|
+
}
|
|
320
|
+
]
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
"type": "file",
|
|
324
|
+
"name": "dist/reflexion.js.map",
|
|
325
|
+
"hashes": [
|
|
326
|
+
{
|
|
327
|
+
"alg": "SHA-256",
|
|
328
|
+
"content": "c784199286137919544d9fbe957cf8405109111a8748e2409555d408e56e05f0"
|
|
329
|
+
}
|
|
330
|
+
]
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
"type": "file",
|
|
334
|
+
"name": "dist/sqlite-backend.d.ts",
|
|
335
|
+
"hashes": [
|
|
336
|
+
{
|
|
337
|
+
"alg": "SHA-256",
|
|
338
|
+
"content": "bcee527422ab9692082ad26f6276f47f9bce86ed5279439f67a0823da1b93387"
|
|
339
|
+
}
|
|
340
|
+
]
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"type": "file",
|
|
344
|
+
"name": "dist/sqlite-backend.d.ts.map",
|
|
345
|
+
"hashes": [
|
|
346
|
+
{
|
|
347
|
+
"alg": "SHA-256",
|
|
348
|
+
"content": "1d8187924617dc91f55c23c624d4d4bc7ce82dc6059c33e87cf78c2c3837547b"
|
|
349
|
+
}
|
|
350
|
+
]
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
"type": "file",
|
|
354
|
+
"name": "dist/sqlite-backend.js",
|
|
355
|
+
"hashes": [
|
|
356
|
+
{
|
|
357
|
+
"alg": "SHA-256",
|
|
358
|
+
"content": "056c9dd4f11234c2e4a2af906ccbd9022cc3f11c20fdddd2465eca260f93b104"
|
|
359
|
+
}
|
|
360
|
+
]
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
"type": "file",
|
|
364
|
+
"name": "dist/sqlite-backend.js.map",
|
|
365
|
+
"hashes": [
|
|
366
|
+
{
|
|
367
|
+
"alg": "SHA-256",
|
|
368
|
+
"content": "a34bdb236db9d469e6c4dde6d50832438aca0d085f47a12a9ad43258a4524e12"
|
|
369
|
+
}
|
|
370
|
+
]
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
"type": "file",
|
|
374
|
+
"name": "dist/sqlite-probe.d.ts",
|
|
375
|
+
"hashes": [
|
|
376
|
+
{
|
|
377
|
+
"alg": "SHA-256",
|
|
378
|
+
"content": "6a649e48cbaad5c900e2bb95e11f4a1f4e33dc9dd8165cab290659c37dcdb1d6"
|
|
379
|
+
}
|
|
380
|
+
]
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
"type": "file",
|
|
384
|
+
"name": "dist/sqlite-probe.d.ts.map",
|
|
385
|
+
"hashes": [
|
|
386
|
+
{
|
|
387
|
+
"alg": "SHA-256",
|
|
388
|
+
"content": "982ea953e1a80deb38c6c80e1f150f1bd410e97ba83480b7d4f7249e98763562"
|
|
389
|
+
}
|
|
390
|
+
]
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
"type": "file",
|
|
394
|
+
"name": "dist/sqlite-probe.js",
|
|
395
|
+
"hashes": [
|
|
396
|
+
{
|
|
397
|
+
"alg": "SHA-256",
|
|
398
|
+
"content": "b6aaa054f32385874b50bcce779d98c33d16dc2fab73a8bf48691b18fdc25e3e"
|
|
399
|
+
}
|
|
400
|
+
]
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
"type": "file",
|
|
404
|
+
"name": "dist/sqlite-probe.js.map",
|
|
405
|
+
"hashes": [
|
|
406
|
+
{
|
|
407
|
+
"alg": "SHA-256",
|
|
408
|
+
"content": "083e083ff09058e6802bae5d1415b53d39218a6bf1f31cd6d041e10dbeae9c61"
|
|
409
|
+
}
|
|
410
|
+
]
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
"type": "file",
|
|
414
|
+
"name": "package.json",
|
|
415
|
+
"hashes": [
|
|
416
|
+
{
|
|
417
|
+
"alg": "SHA-256",
|
|
418
|
+
"content": "b287a6ceae333b4a88beea011de37eb2fe580841c925d57fa4378c1d7225168d"
|
|
419
|
+
}
|
|
420
|
+
]
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
"type": "file",
|
|
424
|
+
"name": "src/backend.ts",
|
|
425
|
+
"hashes": [
|
|
426
|
+
{
|
|
427
|
+
"alg": "SHA-256",
|
|
428
|
+
"content": "77fe67ce082757e38117e8d6a2598d705f6f665a696474608bcfb0f7739ef15e"
|
|
429
|
+
}
|
|
430
|
+
]
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
"type": "file",
|
|
434
|
+
"name": "src/bridge.ts",
|
|
435
|
+
"hashes": [
|
|
436
|
+
{
|
|
437
|
+
"alg": "SHA-256",
|
|
438
|
+
"content": "f1fce2221d78a9cae4063e46cd87d2120aeaad5d31d9c3845cb2a01dd420ae6a"
|
|
439
|
+
}
|
|
440
|
+
]
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
"type": "file",
|
|
444
|
+
"name": "src/cascade.ts",
|
|
445
|
+
"hashes": [
|
|
446
|
+
{
|
|
447
|
+
"alg": "SHA-256",
|
|
448
|
+
"content": "e34c41de72524417a60a530aa988b33b7be7ebc33a4ac415595f448652882ced"
|
|
449
|
+
}
|
|
450
|
+
]
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
"type": "file",
|
|
454
|
+
"name": "src/dreaming.ts",
|
|
455
|
+
"hashes": [
|
|
456
|
+
{
|
|
457
|
+
"alg": "SHA-256",
|
|
458
|
+
"content": "f23084fe7ba68bdf8e913da65c12704a2d2a33ae66e120c712c3c2d59ca83ec8"
|
|
459
|
+
}
|
|
460
|
+
]
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
"type": "file",
|
|
464
|
+
"name": "src/index.ts",
|
|
465
|
+
"hashes": [
|
|
466
|
+
{
|
|
467
|
+
"alg": "SHA-256",
|
|
468
|
+
"content": "34c68dbea4be8c8108dd6aff0e49690484894c56f53967e07c92205b8d57ff64"
|
|
469
|
+
}
|
|
470
|
+
]
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
"type": "file",
|
|
474
|
+
"name": "src/json-backend.ts",
|
|
475
|
+
"hashes": [
|
|
476
|
+
{
|
|
477
|
+
"alg": "SHA-256",
|
|
478
|
+
"content": "a42aae75c2760818b7f206c194db3328e2d339d455cca0d8b656c1bbb394335c"
|
|
479
|
+
}
|
|
480
|
+
]
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
"type": "file",
|
|
484
|
+
"name": "src/reflexion.ts",
|
|
485
|
+
"hashes": [
|
|
486
|
+
{
|
|
487
|
+
"alg": "SHA-256",
|
|
488
|
+
"content": "1e22f854d7f7f216be8b1062f2264be241f3cf46ddd5b0d3b39cd4941c43890c"
|
|
489
|
+
}
|
|
490
|
+
]
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
"type": "file",
|
|
494
|
+
"name": "src/sqlite-backend.ts",
|
|
495
|
+
"hashes": [
|
|
496
|
+
{
|
|
497
|
+
"alg": "SHA-256",
|
|
498
|
+
"content": "85159ceb6b5dbd21f66b39a8e522097b363c699986b8209acf90281fb490c7ac"
|
|
499
|
+
}
|
|
500
|
+
]
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
"type": "file",
|
|
504
|
+
"name": "src/sqlite-probe.ts",
|
|
505
|
+
"hashes": [
|
|
506
|
+
{
|
|
507
|
+
"alg": "SHA-256",
|
|
508
|
+
"content": "28bc13308f61bc553fc36a9c0efcf382522769de20769f3fcef8c3bbb4734b7e"
|
|
509
|
+
}
|
|
510
|
+
]
|
|
511
|
+
},
|
|
512
|
+
{
|
|
513
|
+
"type": "file",
|
|
514
|
+
"name": "stryker.config.json",
|
|
515
|
+
"hashes": [
|
|
516
|
+
{
|
|
517
|
+
"alg": "SHA-256",
|
|
518
|
+
"content": "2f8f92b4368e876e88113bc49b13a46a705d9ba0f64b6852ae111b48c77fd16f"
|
|
519
|
+
}
|
|
520
|
+
]
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
"type": "file",
|
|
524
|
+
"name": "test/bridge.test.ts",
|
|
525
|
+
"hashes": [
|
|
526
|
+
{
|
|
527
|
+
"alg": "SHA-256",
|
|
528
|
+
"content": "4369595f468d204d32bb561a6cc00e096092dcfff0d1693417741c3a0281f647"
|
|
529
|
+
}
|
|
530
|
+
]
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
"type": "file",
|
|
534
|
+
"name": "test/cascade.test.ts",
|
|
535
|
+
"hashes": [
|
|
536
|
+
{
|
|
537
|
+
"alg": "SHA-256",
|
|
538
|
+
"content": "c7b429025794a914674b8cace13ccc1c53dae4ac6b4ed16620c75a4c9ab7d8df"
|
|
539
|
+
}
|
|
540
|
+
]
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
"type": "file",
|
|
544
|
+
"name": "test/dreaming.test.ts",
|
|
545
|
+
"hashes": [
|
|
546
|
+
{
|
|
547
|
+
"alg": "SHA-256",
|
|
548
|
+
"content": "c189e9313e4c45ea0302ee31f2b5b3952b6e71cc3b9e3d2c3b1dd396db66d58e"
|
|
549
|
+
}
|
|
550
|
+
]
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
"type": "file",
|
|
554
|
+
"name": "test/json-backend.test.ts",
|
|
555
|
+
"hashes": [
|
|
556
|
+
{
|
|
557
|
+
"alg": "SHA-256",
|
|
558
|
+
"content": "6914ddc262e515c4763d097871eb8a5ec9a0667b379fa61a214c10f2f26898b3"
|
|
559
|
+
}
|
|
560
|
+
]
|
|
561
|
+
},
|
|
562
|
+
{
|
|
563
|
+
"type": "file",
|
|
564
|
+
"name": "test/reflexion.test.ts",
|
|
565
|
+
"hashes": [
|
|
566
|
+
{
|
|
567
|
+
"alg": "SHA-256",
|
|
568
|
+
"content": "e013324ab5d227c501f5a24944f0caca915b4cafffcc6aacccbe5010685f30a4"
|
|
569
|
+
}
|
|
570
|
+
]
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
"type": "file",
|
|
574
|
+
"name": "test/sqlite-backend.test.ts",
|
|
575
|
+
"hashes": [
|
|
576
|
+
{
|
|
577
|
+
"alg": "SHA-256",
|
|
578
|
+
"content": "ce44f28c4607facbf23e0528d1d4c12a7b755fe4eda37ce547081d786e77e44a"
|
|
579
|
+
}
|
|
580
|
+
]
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
"type": "file",
|
|
584
|
+
"name": "test/sqlite-probe.test.ts",
|
|
585
|
+
"hashes": [
|
|
586
|
+
{
|
|
587
|
+
"alg": "SHA-256",
|
|
588
|
+
"content": "05320e156305d3e706df5bcc288661e1258abbb827cf86b888351c98696457a5"
|
|
589
|
+
}
|
|
590
|
+
]
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
"type": "file",
|
|
594
|
+
"name": "test/tokenize-unicode.test.ts",
|
|
595
|
+
"hashes": [
|
|
596
|
+
{
|
|
597
|
+
"alg": "SHA-256",
|
|
598
|
+
"content": "05d66ccd90004382910ed106f884d3fa99af90cb427501583c0e373d37df3bc4"
|
|
599
|
+
}
|
|
600
|
+
]
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
"type": "file",
|
|
604
|
+
"name": "tsconfig.json",
|
|
605
|
+
"hashes": [
|
|
606
|
+
{
|
|
607
|
+
"alg": "SHA-256",
|
|
608
|
+
"content": "e80ef2911c3347a713dc3dca6a5f6034d91e938e58e71345ea920dd9833bcdbb"
|
|
609
|
+
}
|
|
610
|
+
]
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
"type": "file",
|
|
614
|
+
"name": "vitest.config.ts",
|
|
615
|
+
"hashes": [
|
|
616
|
+
{
|
|
617
|
+
"alg": "SHA-256",
|
|
618
|
+
"content": "a6ffc6172b50a3a59010f8f8c66e2204e7d298b62a7f2bc5de33cbf39c99899d"
|
|
619
|
+
}
|
|
620
|
+
]
|
|
621
|
+
}
|
|
622
|
+
]
|
|
623
|
+
}
|
package/src/json-backend.ts
CHANGED
|
@@ -15,12 +15,28 @@ import type { MemoryBackend, MemoryQuery, MemoryRecord } from './backend.js';
|
|
|
15
15
|
|
|
16
16
|
const DEFAULT_LIMIT = 20;
|
|
17
17
|
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Split text into lowercase word tokens of length > 1.
|
|
20
|
+
*
|
|
21
|
+
* The class is `\p{L}\p{N}`, not `a-z0-9`. Until 2026-08-21 it was ASCII-only, so every non-Latin
|
|
22
|
+
* letter was a SEPARATOR and a Cyrillic query produced ZERO tokens — the FTS5 branch was then skipped
|
|
23
|
+
* entirely, `relevanceOf` returned 0 for every record, and the sort collapsed onto its confidence
|
|
24
|
+
* tie-break. MEASURED on a 267-record clone of the real brain: RU top-1 0/10 against EN 10/10, while
|
|
25
|
+
* 63% of real recall traffic is Cyrillic. The INDEX was never wrong — FTS5's own tokenizer handles
|
|
26
|
+
* Cyrillic — so nothing on disk needed migrating; only the query was being stripped of its terms.
|
|
27
|
+
*
|
|
28
|
+
* `\p{L}` admits letters and `\p{N}` digits; it does NOT admit `"`, `*`, `(` or any other FTS5
|
|
29
|
+
* operator, which is what keeps the joined terms safe to interpolate into a MATCH expression.
|
|
30
|
+
*/
|
|
19
31
|
function tokenize(text: string): string[] {
|
|
20
32
|
return text
|
|
21
33
|
.toLowerCase()
|
|
22
|
-
.split(/[
|
|
23
|
-
.
|
|
34
|
+
.split(/[^\p{L}\p{N}]+/u)
|
|
35
|
+
// Count CODE POINTS, not UTF-16 units. `token.length` counts units, so a single astral letter
|
|
36
|
+
// (`𐐀`, one character, two units) would slip past a floor meant to reject one-character words —
|
|
37
|
+
// an accidental threshold change smuggled in by the alphabet change (cross-family review,
|
|
38
|
+
// 2026-08-21). The promise was "the alphabet, not the thresholds"; this keeps it.
|
|
39
|
+
.filter((token) => [...token].length > 1);
|
|
24
40
|
}
|
|
25
41
|
|
|
26
42
|
/** Count how many query terms appear in a record's text/skillId. */
|
|
@@ -94,7 +110,13 @@ export class JsonFileBackend implements MemoryBackend {
|
|
|
94
110
|
b.record.score - a.record.score ||
|
|
95
111
|
b.record.timestamp.localeCompare(a.record.timestamp),
|
|
96
112
|
);
|
|
97
|
-
|
|
113
|
+
// ASKING and finding nothing returns nothing. Without this the keyword path RANKS by overlap and
|
|
114
|
+
// never EXCLUDES, so every query returned the whole store reordered — MEASURED on two records:
|
|
115
|
+
// `zebrafish` (matches neither) AND `hello` (matches one) both returned both. With no usable
|
|
116
|
+
// terms there was nothing to match on, and returning the store ranked by confidence stays the
|
|
117
|
+
// right answer; that distinction is the whole decision (ADR-001).
|
|
118
|
+
const filtered = terms.length > 0 ? ranked.filter((entry) => entry.relevance > 0) : ranked;
|
|
119
|
+
return filtered.slice(0, limit).map((entry) => entry.record);
|
|
98
120
|
}
|
|
99
121
|
|
|
100
122
|
all(): Promise<MemoryRecord[]> {
|
package/src/sqlite-backend.ts
CHANGED
|
@@ -18,12 +18,28 @@ const require = createRequire(import.meta.url);
|
|
|
18
18
|
|
|
19
19
|
const DEFAULT_LIMIT = 20;
|
|
20
20
|
|
|
21
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Split text into lowercase word tokens of length > 1.
|
|
23
|
+
*
|
|
24
|
+
* The class is `\p{L}\p{N}`, not `a-z0-9`. Until 2026-08-21 it was ASCII-only, so every non-Latin
|
|
25
|
+
* letter was a SEPARATOR and a Cyrillic query produced ZERO tokens — the FTS5 branch was then skipped
|
|
26
|
+
* entirely, `relevanceOf` returned 0 for every record, and the sort collapsed onto its confidence
|
|
27
|
+
* tie-break. MEASURED on a 267-record clone of the real brain: RU top-1 0/10 against EN 10/10, while
|
|
28
|
+
* 63% of real recall traffic is Cyrillic. The INDEX was never wrong — FTS5's own tokenizer handles
|
|
29
|
+
* Cyrillic — so nothing on disk needed migrating; only the query was being stripped of its terms.
|
|
30
|
+
*
|
|
31
|
+
* `\p{L}` admits letters and `\p{N}` digits; it does NOT admit `"`, `*`, `(` or any other FTS5
|
|
32
|
+
* operator, which is what keeps the joined terms safe to interpolate into a MATCH expression.
|
|
33
|
+
*/
|
|
22
34
|
function tokenize(text: string): string[] {
|
|
23
35
|
return text
|
|
24
36
|
.toLowerCase()
|
|
25
|
-
.split(/[
|
|
26
|
-
.
|
|
37
|
+
.split(/[^\p{L}\p{N}]+/u)
|
|
38
|
+
// Count CODE POINTS, not UTF-16 units. `token.length` counts units, so a single astral letter
|
|
39
|
+
// (`𐐀`, one character, two units) would slip past a floor meant to reject one-character words —
|
|
40
|
+
// an accidental threshold change smuggled in by the alphabet change (cross-family review,
|
|
41
|
+
// 2026-08-21). The promise was "the alphabet, not the thresholds"; this keeps it.
|
|
42
|
+
.filter((token) => [...token].length > 1);
|
|
27
43
|
}
|
|
28
44
|
|
|
29
45
|
/** Count how many query terms appear in a record's text/skillId. */
|
|
@@ -234,7 +250,12 @@ export class SqliteBackend implements MemoryBackend {
|
|
|
234
250
|
b.record.score - a.record.score ||
|
|
235
251
|
b.record.timestamp.localeCompare(a.record.timestamp),
|
|
236
252
|
);
|
|
237
|
-
|
|
253
|
+
// The SAME guard the JSON backend applies, so a store's answers never depend on which backend is
|
|
254
|
+
// installed. This is the keyword FALLBACK; the FTS5 path above already returns zero honestly and
|
|
255
|
+
// is untouched. With no usable terms there was nothing to match on, so the store still comes back
|
|
256
|
+
// ranked by confidence — that distinction is the whole decision (ADR-001).
|
|
257
|
+
const filtered = terms.length > 0 ? ranked.filter((entry) => entry.relevance > 0) : ranked;
|
|
258
|
+
return filtered.slice(0, limit).map((entry) => entry.record);
|
|
238
259
|
}
|
|
239
260
|
|
|
240
261
|
all(): Promise<MemoryRecord[]> {
|