@lotargo/memory_plugin 1.6.5 → 1.6.7

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 (48) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +576 -443
  3. package/mcp-server/benchmarks/fetch_real_corpus.js +351 -0
  4. package/mcp-server/benchmarks/gpu_profile_benchmark.js +170 -0
  5. package/mcp-server/benchmarks/policy_dominance_test.js +221 -0
  6. package/mcp-server/benchmarks/quality_evaluator.js +598 -0
  7. package/mcp-server/benchmarks/raw_corpus_data.js +613 -0
  8. package/mcp-server/benchmarks/run_benchmarks.js +366 -0
  9. package/mcp-server/benchmarks/stress_ingestion.js +195 -0
  10. package/mcp-server/benchmarks/table_code_retrieval.js +453 -0
  11. package/mcp-server/benchmarks/test_dual_layer.js +141 -0
  12. package/mcp-server/cli/direct_commands.js +39 -0
  13. package/mcp-server/cli.js +16 -5
  14. package/mcp-server/cli_boot.js +4 -1
  15. package/mcp-server/client_cli.js +73 -0
  16. package/mcp-server/client_paths.js +44 -0
  17. package/mcp-server/client_registration.js +38 -0
  18. package/mcp-server/codex_config.js +86 -8
  19. package/mcp-server/db/database.js +14 -21
  20. package/mcp-server/db/migrations.js +66 -77
  21. package/mcp-server/db/rag_blob_transport.js +143 -0
  22. package/mcp-server/db/rag_sync.js +284 -0
  23. package/mcp-server/db/sync_queue.js +219 -307
  24. package/mcp-server/dev_link.js +142 -0
  25. package/mcp-server/fact_format.js +44 -12
  26. package/mcp-server/index.js +17 -7
  27. package/mcp-server/ingest/exporter.js +44 -38
  28. package/mcp-server/ingest/pipeline.js +260 -248
  29. package/mcp-server/persona_migration.js +39 -0
  30. package/mcp-server/prompt_manager.js +162 -55
  31. package/mcp-server/rag_scope.js +83 -0
  32. package/mcp-server/retrieval/retriever.js +99 -64
  33. package/mcp-server/setup.js +150 -100
  34. package/mcp-server/storage/blob_store.js +53 -1
  35. package/mcp-server/tools/core/knowledge_read_core.js +163 -0
  36. package/mcp-server/tools/core/memory_core.js +24 -4
  37. package/mcp-server/tools/core/memory_routing.js +10 -0
  38. package/mcp-server/tools/core/note_core.js +53 -0
  39. package/mcp-server/tools/core/rag_query_core.js +169 -0
  40. package/mcp-server/tools/index.js +11 -9
  41. package/mcp-server/tools/memory_tools.js +4 -1
  42. package/mcp-server/tools/note_tools.js +35 -0
  43. package/mcp-server/tools/rag_tools.js +211 -364
  44. package/mcp-server/uninstall.js +627 -0
  45. package/opencode-plugin/index.js +80 -12
  46. package/opencode-plugin/main.js +136 -0
  47. package/package.json +17 -34
  48. package/skills/using-memory/SKILL.md +28 -19
@@ -0,0 +1,613 @@
1
+ // Raw corpus for policy dominance benchmark.
2
+ // Each document is designed to produce BOTH policy chunks (table_summary,
3
+ // code_signature) AND micro_chunks (raw rows/lines) so we can measure which
4
+ // type dominates search results across BM25 / Vector / RRF / RSF modes.
5
+ //
6
+ // Categories:
7
+ // table_only — structured data in markdown tables (no code)
8
+ // code_only — code blocks (no tables)
9
+ // text_only — prose only (control: no policy chunks expected)
10
+ // mixed — tables + code + prose interleaved
11
+
12
+ export const RAW_CORPUS = [
13
+ // ──────────────────────────────────────────────────────────────
14
+ // Category: table_only
15
+ // ──────────────────────────────────────────────────────────────
16
+ {
17
+ id: "benchmark_results_table",
18
+ title: "Search Algorithm Benchmark Results",
19
+ category: "table_only",
20
+ content: `# Search Algorithm Benchmark Results
21
+
22
+ This document contains performance metrics for various search algorithms tested on our hybrid RAG system.
23
+
24
+ ## Performance Summary
25
+
26
+ The table below shows MRR@5, Recall@5, and Latency measurements across four search modes.
27
+
28
+ | Algorithm | MRR@5 | Recall@5 | NDCG@5 | Latency_ms |
29
+ |-----------|-------|----------|--------|------------|
30
+ | BM25 | 0.6706| 0.7619 | 0.6934 | 12 |
31
+ | Vector | 0.8135| 1.0000 | 0.8612 | 45 |
32
+ | RRF | 0.8810| 0.9524 | 0.8997 | 48 |
33
+ | RSF | 0.9286| 1.0000 | 0.9473 | 51 |
34
+
35
+ ## Dataset Breakdown
36
+
37
+ Results per dataset category showing how each algorithm handles different query types.
38
+
39
+ | Dataset Category | N | BM25_MRR | Vector_MRR | RRF_MRR | RSF_MRR |
40
+ |--------------------|---|----------|------------|---------|---------|
41
+ | Semantic RU->EN | 7 | 0.6190 | 0.7500 | 0.8571 | 0.8571 |
42
+ | Cross-Lingual | 7 | 0.5238 | 0.7143 | 0.8095 | 0.8571 |
43
+ | Code/Keyword | 7 | 0.8571 | 0.9524 | 0.9524 | 0.9524 |
44
+
45
+ The RSF algorithm achieves the highest MRR@5 of 0.9286 across all categories.
46
+ `,
47
+ },
48
+
49
+ {
50
+ id: "model_comparison_table",
51
+ title: "Embedding Model Comparison",
52
+ category: "table_only",
53
+ content: `# Embedding Model Comparison
54
+
55
+ Comparison of different embedding models used for vector search in the knowledge base.
56
+
57
+ ## Model Specifications
58
+
59
+ | Model | Dimensions | Size_MB | Language | Accuracy |
60
+ |--------------------------------|------------|---------|----------|----------|
61
+ | multilingual-e5-small | 384 | 117 | 100+ | 0.82 |
62
+ | paraphrase-multilingual-MiniLM | 384 | 90 | 50+ | 0.78 |
63
+ | all-MiniLM-L6-v2 | 384 | 80 | EN | 0.74 |
64
+ | bge-small-en-v1.5 | 384 | 130 | EN | 0.85 |
65
+ | distiluse-base-multilingual | 512 | 130 | 15+ | 0.76 |
66
+
67
+ ## Inference Speed
68
+
69
+ Benchmark results for ONNX quantized inference on CPU.
70
+
71
+ | Model | Tokens_Per_Second | RAM_MB | Quantization |
72
+ |------------------------------|-------------------|--------|--------------|
73
+ | multilingual-e5-small | 1250 | 95 | q8 |
74
+ | paraphrase-multilingual-MiniLM| 1480 | 78 | q8 |
75
+ | all-MiniLM-L6-v2 | 1620 | 65 | q8 |
76
+ | bge-small-en-v1.5 | 1100 | 110 | q4 |
77
+
78
+ The multilingual-e5-small model provides the best balance of accuracy and speed for multilingual retrieval.
79
+ `,
80
+ },
81
+
82
+ // ──────────────────────────────────────────────────────────────
83
+ // Category: code_only
84
+ // ──────────────────────────────────────────────────────────────
85
+ {
86
+ id: "retrieval_pipeline_code",
87
+ title: "Hybrid Retrieval Pipeline Implementation",
88
+ category: "code_only",
89
+ content: `# Hybrid Retrieval Pipeline Implementation
90
+
91
+ This document describes the core retrieval pipeline code for the memory plugin.
92
+
93
+ ## BM25 Search Function
94
+
95
+ The bm25Search function performs full-text search using SQLite FTS5.
96
+
97
+ \`\`\`javascript
98
+ async function bm25Search(db, query, limit = 30) {
99
+ const ftsQuery = sanitizeFtsQuery(query);
100
+ if (!ftsQuery) return [];
101
+
102
+ const stmt = db.prepare(\`
103
+ SELECT id, content, breadcrumbs, rank
104
+ FROM micro_chunks_fts
105
+ WHERE micro_chunks_fts MATCH ?
106
+ ORDER BY rank
107
+ LIMIT ?;
108
+ \`);
109
+ const rows = await stmt.all(ftsQuery, limit);
110
+ return rows.map((r, i) => ({
111
+ id: r.id,
112
+ content: r.content,
113
+ breadcrumbs: r.breadcrumbs,
114
+ bm25_rank: i + 1,
115
+ fts_rank: r.rank,
116
+ }));
117
+ }
118
+ \`\`\`
119
+
120
+ ## Vector Search Function
121
+
122
+ The vectorSearch function computes cosine similarity between query and document embeddings.
123
+
124
+ \`\`\`javascript
125
+ async function vectorSearch(db, queryVector, limit = 30, minSim = 0.25) {
126
+ const vectorDim = queryVector.length;
127
+ const tempBuf = new ArrayBuffer(vectorDim * 4);
128
+ const tempView = new Uint8Array(tempBuf);
129
+ const tempVec = new Float32Array(tempBuf);
130
+
131
+ const stmt = db.prepare(\`
132
+ SELECT m.id, m.section_id, m.doc_id, m.content, m.vector, s.breadcrumbs
133
+ FROM micro_chunks m
134
+ JOIN sections s ON m.section_id = s.id;
135
+ \`);
136
+ const rows = await stmt.all();
137
+ const scored = [];
138
+
139
+ for (const r of rows) {
140
+ const vecSub = toVectorBytes(r.vector);
141
+ if (!vecSub || vecSub.byteLength !== vectorDim * 4) continue;
142
+ tempView.set(vecSub.subarray(0, vectorDim * 4));
143
+ const sim = cosineSimilarity(queryVector, tempVec);
144
+ if (!isNaN(sim) && sim >= minSim) {
145
+ scored.push({ id: r.id, content: r.content, cosine_sim: sim });
146
+ }
147
+ }
148
+
149
+ scored.sort((a, b) => b.cosine_sim - a.cosine_sim);
150
+ return scored.slice(0, limit);
151
+ }
152
+ \`\`\`
153
+
154
+ ## RRF Fusion
155
+
156
+ Reciprocal Rank Fusion combines BM25 and vector results.
157
+
158
+ \`\`\`javascript
159
+ function rrfFusion(bm25Hits, vectorHits, k = 60, scoreThreshold = 0.01) {
160
+ const scoreMap = new Map();
161
+
162
+ bm25Hits.forEach((hit) => {
163
+ const existing = scoreMap.get(hit.id) || { id: hit.id, rrf_score: 0 };
164
+ existing.bm25_rank = hit.bm25_rank;
165
+ existing.rrf_score += 1.0 / (k + hit.bm25_rank);
166
+ scoreMap.set(hit.id, existing);
167
+ });
168
+
169
+ vectorHits.forEach((hit) => {
170
+ const existing = scoreMap.get(hit.id) || { id: hit.id, rrf_score: 0 };
171
+ existing.vector_rank = hit.vector_rank;
172
+ existing.rrf_score += 1.0 / (k + hit.vector_rank);
173
+ scoreMap.set(hit.id, existing);
174
+ });
175
+
176
+ const merged = Array.from(scoreMap.values());
177
+ merged.sort((a, b) => b.rrf_score - a.rrf_score);
178
+ return merged.filter((item) => item.rrf_score >= scoreThreshold);
179
+ }
180
+ \`\`\`
181
+ `,
182
+ },
183
+
184
+ {
185
+ id: "ingestion_pipeline_code",
186
+ title: "Document Ingestion Pipeline",
187
+ category: "code_only",
188
+ content: `# Document Ingestion Pipeline
189
+
190
+ The ingestion pipeline processes raw documents into searchable chunks.
191
+
192
+ ## Main Ingestion Function
193
+
194
+ \`\`\`javascript
195
+ async function ingestDocument({ content, type, title, path, generateEmbeddings, customDb, customBlobDir }) {
196
+ const db = customDb || await getDatabase();
197
+
198
+ // Step 1: Parse document into hierarchical sections
199
+ const sections = parseSections(content, { headingPattern: /^#{1,3}\s+/ });
200
+
201
+ // Step 2: Generate medium chunks (500-1000 tokens)
202
+ const mediumChunks = [];
203
+ for (const section of sections) {
204
+ const medium = createMediumChunks(section, { maxTokens: 1000, overlap: 50 });
205
+ mediumChunks.push(...medium);
206
+ }
207
+
208
+ // Step 3: Generate micro chunks (100-250 tokens)
209
+ const microChunks = [];
210
+ for (const medium of mediumChunks) {
211
+ const micro = createMicroChunks(medium, { maxTokens: 250, overlap: 25 });
212
+ microChunks.push(...micro);
213
+ }
214
+
215
+ // Step 4: Detect and create policy chunks for tables/code
216
+ const policyChunks = detectPolicyChunks(content);
217
+
218
+ // Step 5: Generate embeddings if enabled
219
+ if (generateEmbeddings) {
220
+ for (const chunk of [...microChunks, ...policyChunks]) {
221
+ chunk.vector = await embedText(chunk.content, true);
222
+ }
223
+ }
224
+
225
+ // Step 6: Store in database
226
+ await storeChunks(db, { sections, mediumChunks, microChunks, policyChunks });
227
+
228
+ return {
229
+ sectionsCount: sections.length,
230
+ microChunksCount: microChunks.length,
231
+ policyChunksCount: policyChunks.length,
232
+ };
233
+ }
234
+ \`\`\`
235
+
236
+ ## Policy Chunk Detection
237
+
238
+ \`\`\`javascript
239
+ function detectPolicyChunks(content) {
240
+ const policies = [];
241
+
242
+ // Detect markdown tables
243
+ const tableRegex = /\|.+\|[\s\S]*?(?=\n\n|\n#{1,3}|\Z)/g;
244
+ const tables = content.match(tableRegex) || [];
245
+ for (const table of tables) {
246
+ if (table.split('\n').length >= 3) {
247
+ policies.push({
248
+ type: 'table_summary',
249
+ content: summarizeTable(table),
250
+ sourceContent: table,
251
+ });
252
+ }
253
+ }
254
+
255
+ // Detect code blocks
256
+ const codeRegex = /\`\`\`[\s\S]*?\`\`\`/g;
257
+ const codes = content.match(codeRegex) || [];
258
+ for (const code of codes) {
259
+ policies.push({
260
+ type: 'code_signature',
261
+ content: summarizeCode(code),
262
+ sourceContent: code,
263
+ });
264
+ }
265
+
266
+ return policies;
267
+ }
268
+ \`\`\`
269
+ `,
270
+ },
271
+
272
+ // ──────────────────────────────────────────────────────────────
273
+ // Category: text_only
274
+ // ──────────────────────────────────────────────────────────────
275
+ {
276
+ id: "architecture_overview",
277
+ title: "System Architecture Overview",
278
+ category: "text_only",
279
+ content: `# System Architecture Overview
280
+
281
+ The memory plugin uses a hybrid retrieval architecture combining lexical and semantic search to provide accurate document retrieval across multiple languages.
282
+
283
+ ## Design Principles
284
+
285
+ The system is built on three core principles. First, all search modes operate on the same underlying chunk store, ensuring consistency. Second, policy chunks provide structured summaries of tables and code blocks for better search targeting. Third, the fusion layer combines multiple retrieval signals to improve recall.
286
+
287
+ ## Retrieval Flow
288
+
289
+ When a user submits a query, the system first tokenizes and sanitizes the input. For lexical search, it queries the SQLite FTS5 index using BM25 ranking. For semantic search, it computes a dense vector embedding using the ONNX model and performs a brute-force cosine similarity scan across all stored vectors.
290
+
291
+ The hybrid modes combine these two signals. RRF uses reciprocal rank fusion to merge the ranked lists, while RSF uses relative score fusion with a configurable alpha weight. The alpha parameter controls the balance between semantic and lexical signals.
292
+
293
+ ## Storage Layer
294
+
295
+ Documents are stored in a SQLite database with three hierarchical levels. The document level stores metadata and raw content. The section level represents logical divisions based on headings. The chunk level contains the actual searchable units, with micro chunks being the smallest granularity.
296
+
297
+ The blob store uses content-addressable storage with SHA-256 hashing and zstd compression. This ensures deduplication and efficient storage of repeated content across documents.
298
+
299
+ ## Performance Characteristics
300
+
301
+ The system is designed for single-machine operation with modest resource requirements. The ONNX model loads once and stays in memory. Vector search is brute-force with no index approximation, which is acceptable for corpora up to 100K chunks. For larger corpora, an HNSW index would be needed.
302
+ `,
303
+ },
304
+
305
+ {
306
+ id: "multilingual_design",
307
+ title: "Multilingual Search Design",
308
+ category: "text_only",
309
+ content: `# Multilingual Search Design
310
+
311
+ The memory plugin supports search across 100+ languages using multilingual embedding models.
312
+
313
+ ## Cross-Lingual Challenge
314
+
315
+ Traditional lexical search fails when the query language differs from the document language. A Russian query for "библиотека HTTP" will not match an English document containing "HTTP library" because there is zero lexical overlap.
316
+
317
+ ## Embedding Solution
318
+
319
+ Multilingual models like multilingual-e5-small map text from different languages into a shared vector space. Semantically similar phrases in different languages end up close together in the embedding space, enabling cross-lingual retrieval.
320
+
321
+ ## Query Processing
322
+
323
+ When a non-English query is detected, the system still generates an embedding using the multilingual model. The embedding captures the semantic meaning regardless of language. This embedding is then compared against all document chunk embeddings using cosine similarity.
324
+
325
+ ## BM25 Limitations
326
+
327
+ BM25 relies on exact term matching. It cannot bridge the language gap between Russian queries and English documents. However, BM25 excels at keyword searches where exact terms are known, such as function names, error codes, or API endpoints.
328
+
329
+ ## Hybrid Approach
330
+
331
+ The hybrid modes combine BM25's strength in keyword matching with vector search's strength in semantic understanding. For cross-lingual queries, the vector signal dominates. For code and keyword queries, BM25 provides precise matches that complement the semantic signal.
332
+ `,
333
+ },
334
+
335
+ // ──────────────────────────────────────────────────────────────
336
+ // Category: mixed
337
+ // ──────────────────────────────────────────────────────────────
338
+ {
339
+ id: "full_system_spec",
340
+ title: "Memory Plugin Complete Specification",
341
+ category: "mixed",
342
+ content: `# Memory Plugin Complete Specification
343
+
344
+ This document provides the complete technical specification for the memory plugin's retrieval system.
345
+
346
+ ## System Components
347
+
348
+ The plugin consists of several interconnected components that work together to provide hybrid search capabilities.
349
+
350
+ ### Ingestion Pipeline
351
+
352
+ The ingestion pipeline processes raw markdown documents into searchable chunks. It handles tables, code blocks, and prose differently to optimize search quality.
353
+
354
+ \`\`\`javascript
355
+ async function processDocument(content, metadata) {
356
+ const doc = await createDocument(metadata);
357
+ const sections = splitIntoSections(content);
358
+
359
+ for (const section of sections) {
360
+ const chunks = await chunkSection(section);
361
+ await storeChunks(doc.id, chunks);
362
+ }
363
+
364
+ return doc.id;
365
+ }
366
+ \`\`\`
367
+
368
+ ### Search Modes
369
+
370
+ The system supports four distinct search modes, each with different characteristics.
371
+
372
+ | Mode | Type | Strengths | Weaknesses |
373
+ |--------|-------------|----------------------------------------|-------------------------------|
374
+ | BM25 | Lexical | Fast, exact keywords, code symbols | No semantic understanding |
375
+ | Vector | Semantic | Cross-lingual, paraphrase, conceptual | Slower, misses exact keywords |
376
+ | RRF | Hybrid | Combines both signals, robust | Fixed fusion formula |
377
+ | RSF | Hybrid | Configurable balance, best MRR | Requires tuning alpha |
378
+
379
+ ### Configuration Parameters
380
+
381
+ The following parameters control search behavior.
382
+
383
+ | Parameter | Default | Range | Description |
384
+ |--------------|---------|---------|--------------------------------------|
385
+ | alpha | 0.5 | 0-1 | Semantic weight in RSF fusion |
386
+ | k | 60 | 1-200 | RRF smoothing parameter |
387
+ | vectorScanLimit | 0 | 0-100000| Max chunks to scan (0=unlimited) |
388
+ | minSim | 0.25 | 0-1 | Minimum cosine similarity threshold |
389
+
390
+ ### Policy Chunk Expansion
391
+
392
+ When a policy chunk (table_summary or code_signature) is retrieved, the system expands it to full content. This ensures users receive complete tables or code blocks rather than just summaries.
393
+
394
+ \`\`\`javascript
395
+ function expandPolicyChunk(hit) {
396
+ if (hit.retrieval_policy === 'table_summary') {
397
+ return getFullTable(hit.policy_source_id);
398
+ }
399
+ if (hit.retrieval_policy === 'code_signature') {
400
+ return getFullCode(hit.policy_source_id);
401
+ }
402
+ return hit.content;
403
+ }
404
+ \`\`\`
405
+
406
+ ## Performance Metrics
407
+
408
+ The system was evaluated on 21 challenging queries across three categories. RSF achieved the best MRR@5 of 0.9286, followed by RRF at 0.8810, Vector at 0.8135, and BM25 at 0.6706.
409
+
410
+ ## Storage Architecture
411
+
412
+ Documents are stored in SQLite with FTS5 for full-text search and BLOB columns for dense vectors. The blob store uses SHA-256 content addressing with zstd compression for deduplication.
413
+ `,
414
+ },
415
+
416
+ {
417
+ id: "api_reference_doc",
418
+ title: "Memory Plugin API Reference",
419
+ category: "mixed",
420
+ content: `# Memory Plugin API Reference
421
+
422
+ Complete API reference for the memory plugin's public interface.
423
+
424
+ ## Core Functions
425
+
426
+ The plugin exposes several core functions for document management and search.
427
+
428
+ ### ingestDocument
429
+
430
+ Ingests a document into the knowledge base with optional embedding generation.
431
+
432
+ \`\`\`javascript
433
+ async function ingestDocument({
434
+ content, // Raw markdown content
435
+ type, // 'file' | 'text' | 'url'
436
+ title, // Document title
437
+ path, // Source path or identifier
438
+ generateEmbeddings, // boolean, default true
439
+ customDb, // Optional database instance
440
+ customBlobDir, // Optional blob directory
441
+ })
442
+ // Returns: { sectionsCount, microChunksCount, deduplicated }
443
+ \`\`\`
444
+
445
+ ### hybridQuery
446
+
447
+ Performs hybrid search with configurable fusion algorithm.
448
+
449
+ \`\`\`javascript
450
+ async function hybridQuery({
451
+ query, // Search query string
452
+ limit, // Max results (default 5)
453
+ scoreThreshold, // Minimum score (default 0.01)
454
+ fusionAlgorithm, // 'rsf' | 'rrf' | 'bm25_only' | 'vector_only'
455
+ alpha, // RSF alpha weight (default 0.5)
456
+ embeddingModel, // Model identifier
457
+ instruction, // Optional instruction for embedding
458
+ })
459
+ // Returns: Array of result objects with snippet, score, retrieval_policy
460
+ \`\`\`
461
+
462
+ ### queryKnowledgeBase
463
+
464
+ High-level query function that returns formatted results.
465
+
466
+ \`\`\`javascript
467
+ async function queryKnowledgeBase(query, options = {})
468
+ // Returns: { results, mode, timing }
469
+ \`\`\`
470
+
471
+ ## Configuration
472
+
473
+ The following configuration options control system behavior.
474
+
475
+ | Option | Type | Default | Description |
476
+ |---------------------|--------|---------|------------------------------------|
477
+ | fusionAlgorithm | string | 'rsf' | Fusion mode for hybrid search |
478
+ | alpha | number | 0.5 | Semantic weight (0=lexical, 1=semantic) |
479
+ | vectorScanLimit | number | 0 | Max vectors to scan (0=all) |
480
+ | rerankerEnabled | bool | false | Enable cross-encoder reranking |
481
+ | embeddingModel | string | 'Xenova/multilingual-e5-small' | Model for embeddings |
482
+
483
+ ## Result Format
484
+
485
+ Search results include the following fields.
486
+
487
+ | Field | Type | Description |
488
+ |--------------------|--------|--------------------------------------|
489
+ | chunk_id | string | Unique chunk identifier |
490
+ | snippet | string | Result content (expanded if policy) |
491
+ | score | number | Final fusion score |
492
+ | retrieval_policy | string | 'micro_chunk' | 'table_summary' | 'code_signature' |
493
+ | doc_title | string | Source document title |
494
+ | breadcrumbs | string | Section path |
495
+ | defined_symbols | array | GraphRAG symbols from section |
496
+
497
+ ## Error Handling
498
+
499
+ All functions return empty arrays on error rather than throwing. Warnings are logged to console for diagnostic purposes.
500
+ `,
501
+ },
502
+ ];
503
+
504
+ // Queries designed to test policy vs micro_chunk competition.
505
+ // Each query targets a specific document and has an expected chunk type
506
+ // that SHOULD win (depending on the query formulation).
507
+ //
508
+ // query_types:
509
+ // 'summary' — descriptive query → policy chunk should win
510
+ // 'exact_value' — specific value lookup → micro_chunk should win
511
+ // 'code_symbol' — function/class name → code_signature should win
512
+ // 'keyword' — keyword match → depends on mode
513
+
514
+ export const POLICY_DOMINANCE_QUERIES = [
515
+ // ── table_only queries ──
516
+ {
517
+ query: "Table with columns Algorithm MRR Recall Latency containing benchmark results",
518
+ expectedDocIds: ["benchmark_results_table"],
519
+ query_type: "summary",
520
+ expectedWinner: "table_summary",
521
+ description: "Descriptive table query — policy chunk should win",
522
+ },
523
+ {
524
+ query: "What is the MRR@5 score for RRF algorithm",
525
+ expectedDocIds: ["benchmark_results_table"],
526
+ query_type: "exact_value",
527
+ expectedWinner: "micro_chunk",
528
+ description: "Exact value lookup — micro_chunk (raw row) should win",
529
+ },
530
+ {
531
+ query: "Table with columns Model Dimensions Size Accuracy for embedding models",
532
+ expectedDocIds: ["model_comparison_table"],
533
+ query_type: "summary",
534
+ expectedWinner: "table_summary",
535
+ description: "Model comparison table — policy chunk should win",
536
+ },
537
+ {
538
+ query: "What is the accuracy of bge-small-en-v1.5 model",
539
+ expectedDocIds: ["model_comparison_table"],
540
+ query_type: "exact_value",
541
+ expectedWinner: "micro_chunk",
542
+ description: "Specific model accuracy — micro_chunk should win",
543
+ },
544
+
545
+ // ── code_only queries ──
546
+ {
547
+ query: "Function bm25Search with FTS5 MATCH query and rank ordering",
548
+ expectedDocIds: ["retrieval_pipeline_code"],
549
+ query_type: "code_symbol",
550
+ expectedWinner: "code_signature",
551
+ description: "Function description — code_signature should win",
552
+ },
553
+ {
554
+ query: "rrfFusion scoreMap rrf_score 1.0 divided by k plus rank",
555
+ expectedDocIds: ["retrieval_pipeline_code"],
556
+ query_type: "code_symbol",
557
+ expectedWinner: "code_signature",
558
+ description: "RRF formula — code_signature should win",
559
+ },
560
+ {
561
+ query: "ingestDocument parseSections createMediumChunks createMicroChunks",
562
+ expectedDocIds: ["ingestion_pipeline_code"],
563
+ query_type: "code_symbol",
564
+ expectedWinner: "code_signature",
565
+ description: "Pipeline function names — code_signature should win",
566
+ },
567
+
568
+ // ── text_only queries (control) ──
569
+ {
570
+ query: "System architecture combining lexical and semantic search principles",
571
+ expectedDocIds: ["architecture_overview"],
572
+ query_type: "summary",
573
+ expectedWinner: "micro_chunk",
574
+ description: "Architecture description — only micro_chunks available (control)",
575
+ },
576
+ {
577
+ query: "Cross-lingual retrieval using multilingual embedding models",
578
+ expectedDocIds: ["multilingual_design"],
579
+ query_type: "summary",
580
+ expectedWinner: "micro_chunk",
581
+ description: "Multilingual design — only micro_chunks available (control)",
582
+ },
583
+
584
+ // ── mixed queries ──
585
+ {
586
+ query: "Table with columns Mode Type Strengths Weaknesses for search modes",
587
+ expectedDocIds: ["full_system_spec"],
588
+ query_type: "summary",
589
+ expectedWinner: "table_summary",
590
+ description: "Search modes table — policy chunk should win",
591
+ },
592
+ {
593
+ query: "alpha parameter default value range description configuration",
594
+ expectedDocIds: ["full_system_spec"],
595
+ query_type: "exact_value",
596
+ expectedWinner: "micro_chunk",
597
+ description: "Config parameter lookup — micro_chunk should win",
598
+ },
599
+ {
600
+ query: "hybridQuery function signature fusionAlgorithm alpha embeddingModel",
601
+ expectedDocIds: ["api_reference_doc"],
602
+ query_type: "code_symbol",
603
+ expectedWinner: "code_signature",
604
+ description: "API function signature — code_signature should win",
605
+ },
606
+ {
607
+ query: "result format fields chunk_id snippet score retrieval_policy",
608
+ expectedDocIds: ["api_reference_doc"],
609
+ query_type: "exact_value",
610
+ expectedWinner: "micro_chunk",
611
+ description: "Result field lookup — micro_chunk should win",
612
+ },
613
+ ];