pikelet-wasm 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +340 -4
- package/NOTICE +5 -0
- package/README.md +226 -475
- package/complete/builder.d.ts +4 -4
- package/complete/builder.mjs +26 -9
- package/complete/encoder-kernels/encoder.node.wasm +0 -0
- package/complete/encoder-kernels/encoder.wasm +0 -0
- package/complete/fusion.mjs +72 -0
- package/complete/index.d.ts +34 -7
- package/complete/index.mjs +258 -129
- package/complete/inline-transformer.mjs +119 -10
- package/complete/lexical.mjs +11 -11
- package/complete/retrieval-abstention.mjs +136 -31
- package/complete/sources.mjs +22 -1
- package/complete/wordpiece.mjs +22 -0
- package/dist/engine.js +1 -1
- package/dist/engine.scalar.js +1 -1
- package/dist/engine.scalar.wasm +0 -0
- package/dist/engine.wasm +0 -0
- package/package.json +47 -82
- package/{pancake-artifact-common.js → src/artifact/pikelet-artifact-common.js} +42 -42
- package/{pancake-artifact-range.js → src/artifact/pikelet-artifact-range.js} +43 -36
- package/{pancake-artifact-sketch.js → src/artifact/pikelet-artifact-sketch.js} +105 -68
- package/{pancake-artifact.d.ts → src/artifact/pikelet-artifact.d.ts} +11 -11
- package/{pancake-artifact.js → src/artifact/pikelet-artifact.js} +10 -10
- package/{pancake-core.js → src/core/pikelet-core.js} +141 -140
- package/{pancake-errors.js → src/errors/pikelet-errors.js} +9 -8
- package/{pancake.d.ts → src/pikelet.d.ts} +55 -55
- package/{pancake.js → src/pikelet.js} +47 -47
- package/{pancake.node.mjs → src/pikelet.node.mjs} +49 -49
- package/{pancake.web.d.ts → src/pikelet.web.d.ts} +13 -13
- package/{pancake.web.mjs → src/pikelet.web.mjs} +24 -24
- package/{pancake.workerd.mjs → src/pikelet.workerd.mjs} +22 -22
- /package/{pancake-loader.js → src/loader/pikelet-loader.js} +0 -0
package/README.md
CHANGED
|
@@ -1,589 +1,340 @@
|
|
|
1
1
|
# Pikelet
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Knowledge that ships as a file.**
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
> existing `.pancake` artifacts and their identities remain valid, and the
|
|
7
|
-
> old package names are deprecated pointers to `pikelet-wasm` and
|
|
8
|
-
> `pikelet`.
|
|
5
|
+
Pikelet compiles a corpus into one self-contained, queryable artifact.
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
anywhere JavaScript does — Node, browsers, Cloudflare Workers — with no
|
|
12
|
-
native dependencies. On top of it sit immutable search artifact formats:
|
|
13
|
-
files that package an index, corpus records, query interpretation,
|
|
14
|
-
calibration, and evaluation data, and that can be served from any storage
|
|
15
|
-
that answers byte-range requests.
|
|
7
|
+
A model can interrogate a 456,153-record knowledge base whose backend is a static file.
|
|
16
8
|
|
|
17
|
-
|
|
18
|
-
`.pikelet` file that answers natural-language queries with hydrated,
|
|
19
|
-
confidence-scored results, using nothing but the file, range reads, and a
|
|
20
|
-
reader.
|
|
9
|
+
A `.pikelet` can carry the source text, semantic index, keyword index, query encoder, integrity commitments, retrieval calibration, and evaluation fixtures needed to interrogate that corpus. Put the file on disk, S3, R2, a CDN, or any static HTTP host. A reader can mount it locally or over HTTP Range and search it without a vector database, embedding API, or retrieval server.
|
|
21
10
|
|
|
22
|
-
|
|
23
|
-
query text
|
|
24
|
-
-> artifact-carried query interpreter
|
|
25
|
-
-> vector search over compressed sketch/index data
|
|
26
|
-
+ BM25 over the embedded lexical index, rank-fused
|
|
27
|
-
-> lazy range reads for records
|
|
28
|
-
-> calibrated hydrated results
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
The `pikelet-wasm` package carries both the vector engine and the artifact
|
|
32
|
-
runtime.
|
|
33
|
-
|
|
34
|
-
## Knowledge Packs
|
|
35
|
-
|
|
36
|
-
The same file doubles as a **knowledge pack** for LLMs. A `.pikelet` is a
|
|
37
|
-
portable, immutable corpus that contains its own query encoder, semantic
|
|
38
|
-
and lexical indexes, calibrated abstention, provenance, and integrity
|
|
39
|
-
metadata. Publish it as a static file; an MCP client attaches and queries
|
|
40
|
-
it directly over HTTP range requests — no index to rebuild, no vector
|
|
41
|
-
database to run, no embedding service to call:
|
|
11
|
+
The `pikelet` CLI requires Node 20+; the `pikelet-wasm` library runs on Node 18+ (CI tests 18, 20, 22), browsers, and Cloudflare Workers.
|
|
42
12
|
|
|
43
13
|
```bash
|
|
44
|
-
npx pikelet
|
|
45
|
-
--pack https://github.com/mcn92/pancake/releases/download/artifact-wiki-inline-v4/pancake-wiki-inline.pancake#1b180adf4c6cebb2dcd5615256df6a25dac5fda8738dbbc11d60af86046f97f3
|
|
14
|
+
npx pikelet compile --source ./docs --out docs.pikelet
|
|
46
15
|
```
|
|
47
16
|
|
|
48
|
-
Then ask questions. That line pins 456,153 passages of Simple English
|
|
49
|
-
Wikipedia by content hash: the mount transfers a ~52 MiB resident slice
|
|
50
|
-
of the 649 MiB file, each question costs ~127 range reads, results carry
|
|
51
|
-
their provenance (pack identity, title, section, source), and a pack that
|
|
52
|
-
cannot answer says so instead of guessing. Details in the
|
|
53
|
-
pikelet README ("Attaching packs to an LLM") and `packs/`.
|
|
54
|
-
|
|
55
|
-
## What's in This Repo
|
|
56
|
-
|
|
57
|
-
Three layers, bottom to top:
|
|
58
|
-
|
|
59
|
-
1. **WASM vector engine**
|
|
60
|
-
- In-memory HNSW index with float32 and row-wise affine uint8 backends.
|
|
61
|
-
- JavaScript API: `Pikelet.create()`, `add()`, `search()`, `export()`,
|
|
62
|
-
`restore()`.
|
|
63
|
-
- Source in `src/`, package entrypoints at `pancake.js`,
|
|
64
|
-
`pancake.node.mjs`, `pancake.web.mjs`.
|
|
65
|
-
|
|
66
|
-
2. **Search artifacts**
|
|
67
|
-
- Immutable, integrity-checked files built from indexes and corpus data,
|
|
68
|
-
range-readable from local files, R2, S3, CDNs — anything that serves
|
|
69
|
-
byte ranges.
|
|
70
|
-
- One product format, one index layer beneath it:
|
|
71
|
-
- `.pikelet`: the complete one-file search artifact — the product.
|
|
72
|
-
- `.pancake-sketch`: its index segment (resident sketch plus lazy
|
|
73
|
-
rerank rows), also usable standalone; format 2 (the builder's
|
|
74
|
-
default) interleaves per-row digests with the rows, so every row a
|
|
75
|
-
query fetches is verified on that read.
|
|
76
|
-
- Two adjacent formats that are not search artifacts in the contract
|
|
77
|
-
sense:
|
|
78
|
-
- `.pnck`: the engine's snapshot envelope (`export()`/`restore()`
|
|
79
|
-
serialization), consumed by the compilers and by layer-1 users.
|
|
80
|
-
- `.pancake-range`: **deprecated** range-readable index profile. The
|
|
81
|
-
sketch geometry replaced it (5x faster over real networks at a
|
|
82
|
-
third of the size); readers stay supported for existing artifacts,
|
|
83
|
-
but no new ones should be built.
|
|
84
|
-
- Specs: [spec/SEARCH_ARTIFACT_CONTRACT.md](spec/SEARCH_ARTIFACT_CONTRACT.md),
|
|
85
|
-
[spec/SKETCH_PROFILE.md](spec/SKETCH_PROFILE.md), and
|
|
86
|
-
[spec/COMPLETE_PROFILE.md](spec/COMPLETE_PROFILE.md).
|
|
87
|
-
|
|
88
|
-
3. **Products and compilers**
|
|
89
|
-
- `pikelet/`: the fast path. One command compiles a docs
|
|
90
|
-
folder or a live site into a complete `.pikelet` file:
|
|
91
|
-
```bash
|
|
92
|
-
npx pikelet compile --source ./docs --out search.pikelet
|
|
93
|
-
```
|
|
94
|
-
or scaffolds a deployable search app:
|
|
95
|
-
```bash
|
|
96
|
-
npx pikelet create --name my-docs-search --source ./docs --no-deploy --yes
|
|
97
|
-
```
|
|
98
|
-
- `examples/05-one-file-search/`: the flagship path — the complete
|
|
99
|
-
`.pikelet` container, its compilers, and acceptance tests.
|
|
100
|
-
- `examples/04-static-wiki-pack/`: wiki-scale corpus preparation and the
|
|
101
|
-
sketch artifact pipeline.
|
|
102
|
-
- `examples/03-edge-docs-search/`: a Worker search app with a bundled
|
|
103
|
-
snapshot, distilled query encoder, and calibrated abstention.
|
|
104
|
-
|
|
105
|
-
## Why Pikelet Exists
|
|
106
|
-
|
|
107
|
-
Most vector search libraries assume a server process, native binaries, or a
|
|
108
|
-
database service. Pikelet is built for a different deployment shape:
|
|
109
|
-
|
|
110
|
-
- static files instead of always-on index servers;
|
|
111
|
-
- byte-range reads instead of whole-index downloads;
|
|
112
|
-
- readers for browsers, Workers, and Node;
|
|
113
|
-
- explicit artifact identity and digest verification;
|
|
114
|
-
- query interpretation and evaluation data carried inside the artifact;
|
|
115
|
-
- compact corpus-side vector representations that keep memory and transfer
|
|
116
|
-
costs sane.
|
|
117
|
-
|
|
118
|
-
The result is search you can host like an asset instead of operating like a
|
|
119
|
-
database.
|
|
120
|
-
|
|
121
|
-
## The Flagship: One-File Search
|
|
122
|
-
|
|
123
|
-
The complete profile (`.pikelet`) packs the five components of a search
|
|
124
|
-
application into one content-addressed file:
|
|
125
|
-
|
|
126
17
|
```text
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
lexical BM25 inverted index for hybrid retrieval (optional; readers
|
|
133
|
-
that predate it serve vector-only from the same file)
|
|
18
|
+
Ingested 3 docs -> 3 chunks
|
|
19
|
+
Embedded 3/3 chunks with inline transformer
|
|
20
|
+
Built complete .pikelet artifact with 24.5 MB
|
|
21
|
+
Compiled docs.pikelet
|
|
22
|
+
24.5 MB, 3 records, identity 8d731a...
|
|
134
23
|
```
|
|
135
24
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
Query interpretation comes in three kinds. Each picks two of
|
|
141
|
-
**self-contained**, **small**, and **teacher-quality**, and gives up the
|
|
142
|
-
third — that trade-off, not history, is why all three exist:
|
|
143
|
-
|
|
144
|
-
- **kind 3: `inline-transformer-v1`** — self-contained + teacher quality.
|
|
145
|
-
The artifact carries the WordPiece vocab and quantized MiniLM teacher
|
|
146
|
-
weights as verified data; the reader ships the execution kernels. Costs
|
|
147
|
-
~25 MB of encoder no matter how small the corpus. This is the default:
|
|
148
|
-
`pikelet compile` builds kind 3.
|
|
149
|
-
- **kind 1: `student-inline-v1`** — self-contained + small. A
|
|
150
|
-
corpus-distilled student encoder (~1 MiB), pure-JS execution. The only
|
|
151
|
-
way a small docs corpus compiles to a file measured in single-digit MB;
|
|
152
|
-
quality is bounded by the distillation.
|
|
153
|
-
- **kind 2: `external-transformers-v1`** — small + teacher quality, but
|
|
154
|
-
not self-contained: the artifact pins a host-supplied encoder (model id,
|
|
155
|
-
pooling, normalization, max tokens) and verifies it against embedded
|
|
156
|
-
test vectors before serving. The escape hatch for encoders too big to
|
|
157
|
-
inline and hosts that already run one.
|
|
158
|
-
|
|
159
|
-
Kind 3 is the flagship: the file carries the corpus, index, tokenizer,
|
|
160
|
-
encoder weights, calibration, and evaluation data — the reader supplies
|
|
161
|
-
code, the artifact supplies everything else. Ask it about volcanoes and no
|
|
162
|
-
service, model host, or network dependency is involved beyond range reads
|
|
163
|
-
of the file itself.
|
|
25
|
+
First run fetches the ~25 MiB query encoder from a GitHub release and caches it; every `.pikelet` file is at least that size regardless of corpus, because the encoder ships inside it — a 5-file folder and a 500-file folder both start around 25 MiB.
|
|
26
|
+
|
|
27
|
+
Then query it from an LLM — Claude Code, Claude Desktop, or any MCP client:
|
|
164
28
|
|
|
165
29
|
```bash
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
node test-inline.mjs
|
|
30
|
+
npx pikelet mcp install --client claude-code --pack ./docs.pikelet
|
|
31
|
+
# or --client claude-desktop; any other MCP client can run
|
|
32
|
+
# `npx pikelet mcp --pack ./docs.pikelet` directly, no install step
|
|
170
33
|
```
|
|
171
34
|
|
|
172
|
-
Where the inline wiki artifact currently stands:
|
|
173
|
-
|
|
174
35
|
```text
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
manifest identity: 1b180adf4c6cebb2dcd5615256df6a25dac5fda8738dbbc11d60af86046f97f3
|
|
178
|
-
recall@10: 95.2% at the recommended rerank (97.0% at C=600), against exact
|
|
179
|
-
fp32 brute-force ground truth on the 200-query pre-registered eval —
|
|
180
|
-
98.5% on hand-written natural-language questions, 94.8% on single-title
|
|
181
|
-
lookups (augmented retrieval: hybrid candidates, distance order)
|
|
182
|
-
serves over HTTP range reads: opens on ~52 MiB of the file, ~127 range
|
|
183
|
-
requests per query (cluster-ordered row layout + manifest fetch hints)
|
|
184
|
-
natural-language query with no host encoder option, ~110 ms/query end to
|
|
185
|
-
end locally (the resident scan auto-stages the engine's SIMD kernel at
|
|
186
|
-
this scale; ~540 ms on the pure-JS scan it falls back to)
|
|
36
|
+
Wrote MCP server "knowledge-packs" to ./.mcp.json
|
|
37
|
+
Claude Code picks it up on the next session in this project.
|
|
187
38
|
```
|
|
188
39
|
|
|
189
|
-
|
|
190
|
-
cluster-ordered rows and the 192-dim 2:1-pooled sketch, where v1–v3
|
|
191
|
-
embedded a 96-dim 4:1 sketch in unpermuted order and measured 82.4%; adds
|
|
192
|
-
the hybrid BM25 lexical segment and a format-2 sketch with per-row read
|
|
193
|
-
verification; earlier versions stay published for older checkouts):
|
|
194
|
-
`https://github.com/mcn92/pancake/releases/download/artifact-wiki-inline-v4/pancake-wiki-inline.pancake`
|
|
40
|
+
Claude now has a `search` tool over your docs. Or query it directly from code:
|
|
195
41
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
42
|
+
```js
|
|
43
|
+
import { openPikeletFile } from 'pikelet-wasm/complete';
|
|
44
|
+
const pack = await openPikeletFile('docs.pikelet');
|
|
45
|
+
const out = await pack.query('how do workers restore snapshots', { k: 5 });
|
|
46
|
+
console.log(out.matchQuality, out.results[0]?.title);
|
|
47
|
+
// 'strong' 'Snapshot restore'
|
|
48
|
+
```
|
|
202
49
|
|
|
203
|
-
|
|
50
|
+
That's the whole loop. `compile` also takes a live URL (`--source https://docs.example.com`) instead of a directory. If you want a deployed search app — a Worker + UI, not a file — use `npx pikelet create` instead; see [`packages/pikelet/README.md`](packages/pikelet/README.md) for the full CLI reference and the tradeoffs between the two. `compile` never needs the scaffold path's `@xenova/transformers` dependency; skip its ~140 MB install with `npm install -g pikelet --omit=optional` if you only need `compile`/`mcp`.
|
|
204
51
|
|
|
205
|
-
|
|
206
|
-
uint8:
|
|
52
|
+
Under the hood, the file is one container for everything a reader needs:
|
|
207
53
|
|
|
208
54
|
```text
|
|
209
|
-
|
|
55
|
+
documents
|
|
56
|
+
│
|
|
57
|
+
▼
|
|
58
|
+
┌──────────────────┐
|
|
59
|
+
│ docs.pikelet │
|
|
60
|
+
│ │
|
|
61
|
+
│ corpus │
|
|
62
|
+
│ semantic index │
|
|
63
|
+
│ lexical index │
|
|
64
|
+
│ query encoder │
|
|
65
|
+
│ integrity │
|
|
66
|
+
│ calibration │
|
|
67
|
+
│ evaluation │
|
|
68
|
+
└──────────────────┘
|
|
69
|
+
│
|
|
70
|
+
├── local file
|
|
71
|
+
└── static HTTP / object storage
|
|
72
|
+
│
|
|
73
|
+
▼
|
|
74
|
+
browser / Node / edge / agent
|
|
210
75
|
```
|
|
211
76
|
|
|
212
|
-
|
|
77
|
+
Search is the interface. **The file is the knowledge deployment unit.**
|
|
213
78
|
|
|
214
|
-
|
|
215
|
-
corpus rows.
|
|
216
|
-
- Distance kernels fuse dequantization with dot/L2 accumulation.
|
|
217
|
-
- SIMD paths load bytes, widen lanes, apply scale/offset, and accumulate.
|
|
218
|
-
- Graph maintenance uses symmetric node-to-node distances derived from the
|
|
219
|
-
compressed rows and row statistics.
|
|
220
|
-
- Snapshots serialize compact scale/offset/qdata arrays.
|
|
221
|
-
- Sketch artifacts scan compressed resident rows and fetch only rerank
|
|
222
|
-
candidates.
|
|
223
|
-
- Range-backed readers keep the large corpus side compressed while queries
|
|
224
|
-
stay precise and transient.
|
|
79
|
+
---
|
|
225
80
|
|
|
226
|
-
|
|
227
|
-
the same corpus-side representation serves in-memory search, serialized
|
|
228
|
-
snapshots, resident sketches, range reads, and reranking.
|
|
81
|
+
## The shortest demonstration
|
|
229
82
|
|
|
230
|
-
|
|
83
|
+
A real Pikelet pack contains **456,153 Simple English Wikipedia records** in a **648.5 MiB** artifact.
|
|
231
84
|
|
|
232
|
-
|
|
85
|
+
Try the live browser demo:
|
|
233
86
|
|
|
234
|
-
```
|
|
235
|
-
|
|
87
|
+
```text
|
|
88
|
+
https://pikelet-wiki-playground.pages.dev/
|
|
236
89
|
```
|
|
237
90
|
|
|
238
|
-
|
|
91
|
+
The page is static HTML/JS on Cloudflare Pages. It mounts the pack from R2:
|
|
239
92
|
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
cd pancake
|
|
243
|
-
npm install
|
|
93
|
+
```text
|
|
94
|
+
https://pub-6da2384a3bca4a44b2b2fa29a94cc811.r2.dev/wikipedia.pikelet
|
|
244
95
|
```
|
|
245
96
|
|
|
246
|
-
|
|
247
|
-
|
|
97
|
+
There is no `/search`, `/embed`, `/query`, or `/api` backend behind the demo.
|
|
98
|
+
The browser opens the `.pikelet` file over HTTP Range, verifies the artifact,
|
|
99
|
+
loads the embedded query encoder, and shows the byte ranges it reads.
|
|
248
100
|
|
|
249
|
-
|
|
101
|
+
That file was served by a deliberately dumb HTTP server whose only relevant capability was:
|
|
250
102
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
```js
|
|
254
|
-
// Node.js CJS
|
|
255
|
-
const Pikelet = require('pikelet-wasm');
|
|
256
|
-
|
|
257
|
-
// Node.js ESM
|
|
258
|
-
import Pikelet from 'pikelet-wasm';
|
|
259
|
-
|
|
260
|
-
// Explicit Node/browser entries
|
|
261
|
-
import Pikelet from 'pikelet-wasm/node';
|
|
262
|
-
import Pikelet from 'pikelet-wasm/web';
|
|
263
|
-
|
|
264
|
-
// Search Artifact layer (sketch readers/builders; the deprecated
|
|
265
|
-
// .pancake-range reader stays exported for existing artifacts)
|
|
266
|
-
import { PancakeSketchArtifact, buildSketchArtifact } from 'pikelet-wasm/artifact';
|
|
267
|
-
|
|
268
|
-
// Complete one-file profile: reader (any runtime) and builder (Node)
|
|
269
|
-
import { openPikeletFile } from 'pikelet-wasm/complete';
|
|
270
|
-
import { assemblePancakeFile } from 'pikelet-wasm/complete/builder';
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
Repository checkout:
|
|
274
|
-
|
|
275
|
-
```js
|
|
276
|
-
const Pikelet = require('./pancake.js');
|
|
277
|
-
import Pikelet from './pancake.node.mjs';
|
|
278
|
-
import Pikelet from './pancake.web.mjs';
|
|
103
|
+
```text
|
|
104
|
+
fs.createReadStream + HTTP Range
|
|
279
105
|
```
|
|
280
106
|
|
|
281
|
-
|
|
282
|
-
`dist/engine.wasm`.
|
|
107
|
+
There was no vector database, no search service, no embedding service, no application server that understood the pack, no index process on the server.
|
|
283
108
|
|
|
284
|
-
|
|
109
|
+
The pack was mounted by URL and exposed to a real headless Claude process through MCP. Each invocation was restricted with `--strict-mcp-config` to only:
|
|
285
110
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
const index = await Pikelet.create({
|
|
293
|
-
dim: 384,
|
|
294
|
-
maxElements: 100000,
|
|
295
|
-
metric: 'cosine',
|
|
296
|
-
quantized: true,
|
|
297
|
-
});
|
|
111
|
+
```text
|
|
112
|
+
mcp__wiki-pack__search
|
|
113
|
+
mcp__wiki-pack__list_packs
|
|
114
|
+
mcp__wiki-pack__get_record
|
|
115
|
+
```
|
|
298
116
|
|
|
299
|
-
|
|
300
|
-
const queryVector = new Float32Array(384).fill(0.1); // your query embedding here
|
|
117
|
+
No web tool. No filesystem tool. No alternate retrieval tool.
|
|
301
118
|
|
|
302
|
-
|
|
119
|
+
One of the actual responses:
|
|
303
120
|
|
|
304
|
-
|
|
305
|
-
|
|
121
|
+
> **Q: What causes earthquakes?**
|
|
122
|
+
>
|
|
123
|
+
> Earthquakes are caused by the movement of tectonic plates in the Earth's crust. Stress builds up along fault boundaries where plates grind against or ride over one another; when that stress exceeds the friction holding the locked fault in place, it suddenly releases as shock waves (seismic waves) that shake the ground [record 429637].
|
|
124
|
+
>
|
|
125
|
+
> There are three main fault types that can produce quakes — normal, reverse (thrust), and strike-slip — and some quakes have less clear-cut causes, like deep shifts in ancient rock or mine-collapse "tremors" [record 429638].
|
|
126
|
+
>
|
|
127
|
+
> Two related mechanisms compound this:
|
|
128
|
+
>
|
|
129
|
+
> * Subduction, where one plate is forced under another into the mantle, produces the most powerful earthquakes and can trigger tsunamis [record 132833].
|
|
130
|
+
> * More broadly, the slow convection-driven movement of crustal plates over the hot mantle is the underlying driver of quakes, volcanoes, and mountain formation [record 132267].
|
|
131
|
+
>
|
|
132
|
+
> Volcanic eruptions can also cause earthquakes, though these are localized to areas near active volcanoes [record 429637].
|
|
306
133
|
|
|
307
|
-
|
|
308
|
-
index.compact();
|
|
134
|
+
The model did not just repeat the first search hit. It retrieved multiple records and synthesized them into a sourced answer.
|
|
309
135
|
|
|
310
|
-
|
|
311
|
-
const restored = await Pikelet.restore(snapshot, { maxElements: 100000 });
|
|
136
|
+
Other runs produced:
|
|
312
137
|
|
|
313
|
-
|
|
314
|
-
|
|
138
|
+
```text
|
|
139
|
+
Who was the first person on the moon? → Neil Armstrong (records 408686, 408684)
|
|
140
|
+
How do volcanoes form? → plates + subduction + hotspots
|
|
141
|
+
(records 132770, 132765, 132852, 132853)
|
|
142
|
+
How does photosynthesis work? → two-phase reaction, cited (5 records: 114219, 114220, 114222, 114223, 269279)
|
|
143
|
+
What is the capital of France? → Paris (records 454641, 302684)
|
|
315
144
|
```
|
|
316
145
|
|
|
317
|
-
|
|
146
|
+
That is the product in one demonstration:
|
|
318
147
|
|
|
319
|
-
|
|
320
|
-
const rows = [
|
|
321
|
-
{ id: 'doc-1', vector: embedding1 },
|
|
322
|
-
{ id: 'doc-2', vector: embedding2 },
|
|
323
|
-
];
|
|
324
|
-
|
|
325
|
-
const { index, idMap } = await Pikelet.fromVectors(rows, {
|
|
326
|
-
metric: 'cosine',
|
|
327
|
-
quantized: true,
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
const hits = index.search(queryEmbedding, 5);
|
|
331
|
-
console.log(idMap.get(hits[0].id));
|
|
332
|
-
```
|
|
148
|
+
> **A model is interrogating a 456,153-record knowledge base whose backend is a static file.**
|
|
333
149
|
|
|
334
|
-
|
|
150
|
+
The model may already contain some of these facts in its pretrained parameters. This test demonstrates the retrieval, synthesis, citation, and deployment path; the [Veyra ablation](docs/veyra-ablation.md) tests whether support changes when evidence is removed from the pack.
|
|
335
151
|
|
|
336
|
-
|
|
337
|
-
const { index, idMap } = await Pikelet.loadJsonFile('vectors.jsonl', {
|
|
338
|
-
metric: 'cosine',
|
|
339
|
-
vectorKey: 'embedding',
|
|
340
|
-
idKey: 'docId',
|
|
341
|
-
maxFileBytes: 64 * 1024 * 1024,
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
const restored = await Pikelet.loadSnapshotFile('index.pnck', {
|
|
345
|
-
dim: 384,
|
|
346
|
-
maxElements: 100000,
|
|
347
|
-
metric: 'cosine',
|
|
348
|
-
quantized: true,
|
|
349
|
-
});
|
|
350
|
-
```
|
|
152
|
+
**Network cost.** In a single persistent session (one mount, five queries, one repeat):
|
|
351
153
|
|
|
352
|
-
|
|
154
|
+
| Operation | Bytes transferred | Requests |
|
|
155
|
+
| ------------------------------- | ----------------: | -------: |
|
|
156
|
+
| Initial mount | 51.7 MiB | 11 |
|
|
157
|
+
| Query 1 + one-time encoder load | 25.9 MiB | 77 |
|
|
158
|
+
| Query 2 | 504.4 KiB | 37 |
|
|
159
|
+
| Query 3 | 499.4 KiB | 46 |
|
|
160
|
+
| Query 4 | 968.9 KiB | 75 |
|
|
161
|
+
| Query 5 | 1.1 MiB | 116 |
|
|
162
|
+
| Repeated query 1 | 238.4 KiB | 4 |
|
|
163
|
+
| **Total** | **80.8 MiB** | **366** |
|
|
353
164
|
|
|
354
|
-
|
|
355
|
-
application data plane. To build one from your own docs, see the compile
|
|
356
|
-
command above (`npx pikelet compile`).
|
|
165
|
+
Roughly **12.5% of the 648.5 MiB artifact** crossed the wire across that whole session. Excluding the one-time ~25 MiB encoder load, fresh-query traffic ran **~0.5–1.1 MiB per query**. The complete artifact was never downloaded.
|
|
357
166
|
|
|
358
|
-
|
|
359
|
-
|
|
167
|
+
The headless-Claude test above used a fresh process per question, so each invocation repaid the ~52 MiB mount and ~25 MiB encoder cost — about 78 MiB per cold query. That's a real operational distinction: **persistent sessions amortize mount and encoder cost; independent cold processes do not.**
|
|
168
|
+
|
|
169
|
+
*(The large benchmark fixture still carries its historical `.pancake` filename from before the Pikelet rename; current artifacts use `.pikelet`.)*
|
|
360
170
|
|
|
361
|
-
|
|
171
|
+
---
|
|
362
172
|
|
|
363
|
-
|
|
173
|
+
## Attach a pack to an LLM
|
|
364
174
|
|
|
365
|
-
|
|
366
|
-
console.log(out.results[0].title);
|
|
175
|
+
`pikelet mcp` exposes one or more packs through the Model Context Protocol:
|
|
367
176
|
|
|
368
|
-
|
|
177
|
+
```bash
|
|
178
|
+
npx pikelet mcp install \
|
|
179
|
+
--client claude-code \
|
|
180
|
+
--pack https://example.com/docs.pikelet#<sha256>
|
|
369
181
|
```
|
|
370
182
|
|
|
371
|
-
|
|
183
|
+
The agent gets `search`, `get_record`, `list_packs`, `verify_pack`. A search result carries the identity of the pack and the location of the source record, so an agent can work against `product-docs.pikelet`, `rust-reference.pikelet`, `policy-2026-09.pikelet`, `customer-manual-v4.pikelet` without each publisher operating a retrieval API. The artifact can be local, private, public, behind authenticated object storage, or distributed like any other static asset.
|
|
372
184
|
|
|
373
|
-
|
|
374
|
-
const search = await openPikeletFile('pancake-wiki-inline.pancake');
|
|
375
|
-
const out = await search.query('how do volcanoes form', { k: 5 });
|
|
376
|
-
```
|
|
185
|
+
A pack mounted with a content hash has a stable identity — `https://example.com/docs.pikelet#8d731...` — so "what body of knowledge did this agent query?" has a reproducible answer.
|
|
377
186
|
|
|
378
|
-
|
|
379
|
-
against the declaration's verification vectors before serving and refuses
|
|
380
|
-
the open if they disagree (`info().encoderVerified` reports the outcome).
|
|
187
|
+
**A mounted pack's content reaches the model as tool output.** `verify_pack` proves the bytes are intact and match their pinned identity; it does not prove the corpus itself is trustworthy. Mounting a pack from a source you don't control is the same trust decision as giving an agent any other untrusted-content tool — treat pack text the way you'd treat search results or fetched web pages, not as instructions.
|
|
381
188
|
|
|
382
|
-
The
|
|
383
|
-
a CDN gets queried without downloading it:
|
|
189
|
+
**Try it with your own questions.** The three Veyra packs from the [ablation](docs/veyra-ablation.md) are published as pinned GitHub release assets. Fetch and verify them first:
|
|
384
190
|
|
|
385
|
-
```
|
|
386
|
-
|
|
387
|
-
size,
|
|
388
|
-
async read(offset, length) {
|
|
389
|
-
// return bytes for [offset, offset + length)
|
|
390
|
-
},
|
|
391
|
-
});
|
|
191
|
+
```bash
|
|
192
|
+
npm run demo:veyra
|
|
392
193
|
```
|
|
393
194
|
|
|
394
|
-
|
|
395
|
-
(`maxReadBytes`, `maxRecordBytes`). Format-2 files (`pancake-complete-v2`,
|
|
396
|
-
the builder's default) verify each hydrated record against a per-record
|
|
397
|
-
digest on its own range read (`info().corpusIntegrity`), and an embedded
|
|
398
|
-
format-2 sketch verifies each lazily fetched index row the same way
|
|
399
|
-
(`info().indexRowIntegrity`) — so a tampered transport fails the query
|
|
400
|
-
instead of skewing its results. Older files with a format-1 sketch commit
|
|
401
|
-
the lazy index rows to the identity but don't verify them per read; for
|
|
402
|
-
those, pass `verifyIndexVectors: true` (or call `verifyVectors()`) to
|
|
403
|
-
authenticate them in one full pass before trusting results from an
|
|
404
|
-
untrusted transport (spec/COMPLETE_PROFILE.md section 6).
|
|
405
|
-
|
|
406
|
-
### Attaching packs to an LLM
|
|
407
|
-
|
|
408
|
-
A complete artifact doubles as a portable knowledge pack: everything an
|
|
409
|
-
LLM needs to query a body of knowledge — corpus, indexes, encoder,
|
|
410
|
-
calibrated abstention, integrity commitments — in one immutable,
|
|
411
|
-
identity-pinned file. `pikelet mcp` serves packs over the
|
|
412
|
-
Model Context Protocol so Claude Code, Claude Desktop, or any agent
|
|
413
|
-
framework can attach them as a retrieval tool with one config line — no
|
|
414
|
-
vector database, no embedding service, no retrieval backend. Results
|
|
415
|
-
carry full provenance (pack, manifest identity, title, heading path,
|
|
416
|
-
source), and a pack that cannot answer says so instead of returning
|
|
417
|
-
plausible noise. See the pikelet README's
|
|
418
|
-
"Attaching packs to an LLM (MCP)" section.
|
|
419
|
-
|
|
420
|
-
## Demos
|
|
421
|
-
|
|
422
|
-
Start with [DEMOS.md](DEMOS.md) for the maintained demo path.
|
|
423
|
-
|
|
424
|
-
Useful commands:
|
|
195
|
+
Then mount all three through Pikelet's MCP server:
|
|
425
196
|
|
|
426
197
|
```bash
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
node examples/05-one-file-search/test-file.mjs
|
|
432
|
-
node examples/05-one-file-search/test-wiki.mjs
|
|
433
|
-
node examples/05-one-file-search/test-inline.mjs
|
|
198
|
+
claude -p "your question here" \
|
|
199
|
+
--mcp-config examples/one-file-search/web/public/veyra.mcp.json \
|
|
200
|
+
--strict-mcp-config \
|
|
201
|
+
--allowedTools "mcp__veyra-demo__search,mcp__veyra-demo__list_packs,mcp__veyra-demo__get_record"
|
|
434
202
|
```
|
|
435
203
|
|
|
436
|
-
|
|
437
|
-
of gravity:
|
|
204
|
+
For an interactive session, use the same config without `-p`:
|
|
438
205
|
|
|
439
206
|
```bash
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
node test-file.mjs
|
|
443
|
-
node serve.mjs
|
|
207
|
+
claude \
|
|
208
|
+
--mcp-config examples/one-file-search/web/public/veyra.mcp.json
|
|
444
209
|
```
|
|
445
210
|
|
|
446
|
-
|
|
211
|
+
All three packs derive from the same small synthetic Station Veyra corpus, with controlled differences in the Tovash evidence. Ask where the Tovash project is housed: the full pack supports Chamber 17, the modified pack supports Chamber 43, and the ablated pack should abstain.
|
|
447
212
|
|
|
448
|
-
|
|
213
|
+
---
|
|
449
214
|
|
|
450
|
-
|
|
451
|
-
const index = await Pikelet.create(options);
|
|
452
|
-
index.add(vector);
|
|
453
|
-
index.addBatch(vectors);
|
|
454
|
-
index.search(query, k, options?);
|
|
455
|
-
index.searchFiltered(query, k, allowedIds, options?); // allowedIds: Set of ids
|
|
456
|
-
index.delete(id);
|
|
457
|
-
index.compact();
|
|
458
|
-
index.export();
|
|
459
|
-
index.dispose();
|
|
460
|
-
```
|
|
215
|
+
## Match quality and abstention
|
|
461
216
|
|
|
462
|
-
|
|
217
|
+
A nearest neighbour is not automatically evidence that a corpus answers a question. Pikelet can calibrate retrieval signals at build time (best semantic distance, distance margin, lexical coverage, retrieval agreement). When the corpus supports a reliable classifier, results carry `matchQuality: strong | weak | none`. When calibration can't separate supported from unsupported reliably — a single novel may be semantically homogeneous enough that the fit isn't trustworthy — Pikelet reports `matchQuality: unscored` and records why calibration was skipped, rather than manufacturing confidence. A `none` verdict withholds `results` by default; pass `query(text, { showAbstained: true })` to see the raw retrieval anyway — `matchQuality` and `confidence` are unaffected either way.
|
|
463
218
|
|
|
464
|
-
|
|
465
|
-
{
|
|
466
|
-
dim: 384,
|
|
467
|
-
maxElements: 100000,
|
|
468
|
-
metric: 'cosine', // 'cosine' or 'l2'
|
|
469
|
-
quantized: true,
|
|
470
|
-
M: 12,
|
|
471
|
-
efConstruction: 75,
|
|
472
|
-
efSearch: 100,
|
|
473
|
-
seed: 108
|
|
474
|
-
}
|
|
475
|
-
```
|
|
219
|
+
`matchQuality` is evidence about retrieval support. It is **not** a guarantee that an LLM will never hallucinate.
|
|
476
220
|
|
|
477
|
-
|
|
221
|
+
---
|
|
478
222
|
|
|
479
|
-
|
|
480
|
-
await Pikelet.restore(bytes, options);
|
|
481
|
-
await Pikelet.loadSnapshotFile(path, options);
|
|
482
|
-
await Pikelet.loadJsonFile(path, options);
|
|
483
|
-
await Pikelet.fromVectors(rows, options);
|
|
484
|
-
```
|
|
223
|
+
## Deeper dives
|
|
485
224
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
225
|
+
- [How a `.pikelet` query runs](docs/how-a-query-runs.md) — what is inside the file, what a query costs on the wire, remote execution, and the integrity checks on the read path.
|
|
226
|
+
- [The Veyra ablation](docs/veyra-ablation.md) — what happens to answers when the supporting record is edited or removed from the pack, with the reproduction commands.
|
|
227
|
+
- [Why make knowledge a file](docs/why-a-file.md) — the reasoning behind the single-artifact design, and what it commits to.
|
|
228
|
+
- [Architecture](docs/architecture.md) — the engine, the C ABI and the JavaScript wrapper; the artifact formats are specified in [`spec/`](spec/).
|
|
490
229
|
|
|
491
|
-
##
|
|
230
|
+
## What this is not
|
|
492
231
|
|
|
493
|
-
|
|
232
|
+
**Not a claim that vector databases are obsolete.** If your corpus changes continuously, needs transactional updates, serves many tenants, or already lives comfortably in a database, use a database. Pikelet targets `build → publish → query many times → replace on release`.
|
|
494
233
|
|
|
495
|
-
|
|
234
|
+
**Not state-of-the-art embedding research.** The bundled model is MiniLM-L6, chosen for being small enough to live inside the artifact. ArguAna demonstrates a real quality cost from the compact encoder.
|
|
496
235
|
|
|
497
|
-
|
|
498
|
-
- Emscripten SDK
|
|
236
|
+
**Not "LLMs can no longer hallucinate."** The artifact exposes retrieved evidence, provenance, integrity, and an explicit support signal. Whether an agent obeys those signals is an agent behavior question.
|
|
499
237
|
|
|
500
|
-
|
|
238
|
+
**Not a new HNSW algorithm.** HNSW is HNSW. HTTP Range is HTTP Range. BM25 is BM25. MiniLM is MiniLM. Affine quantization is not new either. The project is about what becomes possible when those pieces are arranged around one constraint: **the knowledge base itself must be distributable as a file and remain useful without dedicated retrieval infrastructure.**
|
|
501
239
|
|
|
502
|
-
|
|
503
|
-
npm run build
|
|
504
|
-
```
|
|
240
|
+
---
|
|
505
241
|
|
|
506
|
-
|
|
242
|
+
## When Pikelet is a good fit — and when it isn't
|
|
507
243
|
|
|
508
|
-
|
|
509
|
-
npm run build:all
|
|
510
|
-
```
|
|
244
|
+
**Use it when:**
|
|
511
245
|
|
|
512
|
-
|
|
246
|
+
- your corpus is static or changes on a release cycle
|
|
247
|
+
- you want semantic search without operating search infrastructure
|
|
248
|
+
- you want search inside a browser, Node process, edge worker, Electron app, or offline tool
|
|
249
|
+
- you want to distribute a searchable corpus to someone else
|
|
250
|
+
- you want an LLM agent to query a frozen, versioned body of knowledge
|
|
251
|
+
- static/object storage is easier to deploy than a database
|
|
252
|
+
- provenance and reproducibility matter
|
|
253
|
+
- a content-addressed knowledge snapshot is useful
|
|
513
254
|
|
|
514
|
-
|
|
255
|
+
Examples: documentation, SDK/API references, technical manuals, research corpora, standards, legal texts, books, product knowledge, code/documentation snapshots, evaluation corpora, agent reference packs.
|
|
515
256
|
|
|
516
|
-
|
|
517
|
-
suites):
|
|
257
|
+
**Don't use it if:**
|
|
518
258
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
```
|
|
259
|
+
- your corpus has heavy online writes
|
|
260
|
+
- you need transactional mutation
|
|
261
|
+
- you need a multi-tenant authoritative search service
|
|
262
|
+
- you need exact nearest-neighbour search at very large scale
|
|
263
|
+
- your corpus is so large that a linear resident sketch scan is inappropriate
|
|
264
|
+
- you already operate a vector database happily and portability buys you nothing
|
|
526
265
|
|
|
527
|
-
|
|
266
|
+
The resident remote scan is linear in row count. The current architecture targets corpora through the low millions of records, not arbitrary web scale.
|
|
528
267
|
|
|
529
|
-
|
|
530
|
-
node examples/05-one-file-search/test-file.mjs
|
|
531
|
-
node examples/05-one-file-search/test-wiki.mjs
|
|
532
|
-
node examples/05-one-file-search/test-inline.mjs
|
|
533
|
-
```
|
|
268
|
+
---
|
|
534
269
|
|
|
535
|
-
|
|
536
|
-
demand when `examples/05-one-file-search/pancake-wiki-inline.pancake` is
|
|
537
|
-
missing.
|
|
270
|
+
## Repository map
|
|
538
271
|
|
|
539
|
-
|
|
272
|
+
```text
|
|
273
|
+
packages/pikelet-wasm/ The published pikelet-wasm package:
|
|
274
|
+
engine/ C++ vector engine (HNSW, float32 and
|
|
275
|
+
affine-u8 backends, mutation, compaction,
|
|
276
|
+
snapshot import/export), compiled to WASM
|
|
277
|
+
in dist/. Used at compile time to build and
|
|
278
|
+
quantize the index; query time does not load
|
|
279
|
+
it (see complete/index.mjs's header comment)
|
|
280
|
+
— .pikelet reads run a pure-JS sketch scan,
|
|
281
|
+
optionally SIMD-accelerated.
|
|
282
|
+
src/ Engine wrapper and artifact readers/builders
|
|
283
|
+
(the entrypoints, core/, artifact/, errors/)
|
|
284
|
+
complete/ Reader and builder for the complete
|
|
285
|
+
range-readable .pikelet artifact
|
|
286
|
+
native/ N-API build of the same engine (benchmarks)
|
|
287
|
+
packages/pikelet/ The published pikelet CLI: compiler, MCP
|
|
288
|
+
server, encoder integration, Docusaurus plugin
|
|
289
|
+
docs/ Deeper dives (how a query runs, the Veyra
|
|
290
|
+
ablation, why a file), architecture notes,
|
|
291
|
+
rename history, measurement reports
|
|
292
|
+
spec/ Byte-level artifact contracts
|
|
293
|
+
benchmarks/beir/ Frozen BEIR ablation harness (encoder,
|
|
294
|
+
quantization, HNSW quality)
|
|
295
|
+
benchmarks/range-proof/ The deliberately boring static-HTTP proof:
|
|
296
|
+
dumb-server.mjs, proof.mjs, mcp-proof.mjs,
|
|
297
|
+
llm-proof.mjs, failure-modes.mjs
|
|
298
|
+
examples/one-file-search/ Large single-artifact search and embedded
|
|
299
|
+
encoder work
|
|
300
|
+
examples/mcp-knowledge-pack/ Compile, mount, search, and hydrate
|
|
301
|
+
records through MCP
|
|
302
|
+
local-packs/ Prebuilt example .pikelet artifacts used
|
|
303
|
+
by the demo commands above
|
|
304
|
+
packs/ Pack hosting and distribution examples
|
|
305
|
+
```
|
|
540
306
|
|
|
541
|
-
|
|
307
|
+
---
|
|
542
308
|
|
|
543
|
-
|
|
544
|
-
- `efSearch` for the recall/latency tradeoff.
|
|
545
|
-
- sketch artifacts for depth-1 candidate selection before lazy rerank
|
|
546
|
-
reads.
|
|
547
|
-
- corpus layout and clustering for fewer remote read rounds.
|
|
548
|
-
- kind-3 inline encoders when deployment shouldn't depend on an external
|
|
549
|
-
ML runtime.
|
|
309
|
+
## Reproduce the proofs
|
|
550
310
|
|
|
551
|
-
|
|
552
|
-
newer artifact-level benchmarks are more representative of what the project
|
|
553
|
-
is actually for: search from static files and range-readable storage.
|
|
311
|
+
**Range proof** (`benchmarks/range-proof/`) is built around a server that does not understand Pikelet. It checks: static HTTP + Range + Pikelet client = remote semantic retrieval, without a full download. The main script reports artifact size, records, mount bytes/requests, per-query bytes/requests, cache behavior. `failure-modes.mjs` independently exercises Range supported / ignored / tampered bytes / truncated response. `mcp-proof.mjs` and `llm-proof.mjs` use a real MCP client and a real headless Claude process rather than a mocked model response.
|
|
554
312
|
|
|
555
|
-
|
|
556
|
-
hnswlib-node, usearch) are not dependencies of `pikelet-wasm`; install
|
|
557
|
-
them on demand with `cd benchmarks && npm install` before running those
|
|
558
|
-
scripts. See `benchmarks/`, `benchmark_results/`, and the example READMEs
|
|
559
|
-
for current numbers.
|
|
313
|
+
**BEIR evaluation** (`benchmarks/beir/`) keeps stages separate so a quality change can be attributed to the component that caused it, plus a standalone conformance fixture checking the JS benchmark path against the actual C++ affine-u8 representation. Don't read the latency columns as a universal native-performance comparison — they measure the benchmark paths under the stated harness. The quality deltas are the important part.
|
|
560
314
|
|
|
561
|
-
|
|
315
|
+
---
|
|
562
316
|
|
|
563
|
-
|
|
317
|
+
## Status
|
|
564
318
|
|
|
565
|
-
|
|
566
|
-
- you want static-file or edge deployment;
|
|
567
|
-
- you need reproducible, inspectable search artifacts;
|
|
568
|
-
- your corpus can be built offline;
|
|
569
|
-
- byte-range reads are cheaper than operating a dedicated search service.
|
|
319
|
+
Pikelet is early. The implementation is real; the format is not frozen. One primary author. Draft 2 artifact format.
|
|
570
320
|
|
|
571
|
-
|
|
321
|
+
- prebuilt WASM included
|
|
322
|
+
- local and HTTP readers
|
|
323
|
+
- affine-u8 and float HNSW backends for compile-time indexing/quantization
|
|
324
|
+
- embedded query encoder
|
|
325
|
+
- BM25 hybrid retrieval
|
|
326
|
+
- content identity and lazy-read integrity verification
|
|
327
|
+
- calibration/abstention support
|
|
328
|
+
- MCP mounting
|
|
329
|
+
- BEIR retrieval evaluation
|
|
330
|
+
- range-read and failure-mode tests
|
|
331
|
+
- a large 456k-record example artifact
|
|
572
332
|
|
|
573
|
-
|
|
574
|
-
- you need a multi-tenant database server;
|
|
575
|
-
- you require exact nearest-neighbor search at large scale;
|
|
576
|
-
- your deployment can already use a mature native ANN service with no
|
|
577
|
-
portability constraints.
|
|
333
|
+
`npm test` exercises the engine, artifact profiles, MCP, ingestion, format hardening, and related conformance suites.
|
|
578
334
|
|
|
579
|
-
|
|
335
|
+
Previously known as **Pancake** (renamed September 2026); artifacts, profile strings and files from before the rename remain readable — see [`docs/history.md`](docs/history.md) for what kept the old name and why. Pikelet is unrelated to the pre-existing Pikelet programming language.
|
|
580
336
|
|
|
581
|
-
|
|
582
|
-
today (`pikelet-wasm`, with `pikelet` as the app scaffold).
|
|
583
|
-
The complete `.pikelet` profile's spec is still marked draft — Draft 2,
|
|
584
|
-
under review, not frozen — but its reader and builder ship in the package,
|
|
585
|
-
and it is the clearest expression of where the project is going: a search
|
|
586
|
-
engine packaged as one verified, range-readable file.
|
|
337
|
+
---
|
|
587
338
|
|
|
588
339
|
## License
|
|
589
340
|
|