ralph-hero-knowledge-index 0.1.30 → 0.1.32

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ralph-knowledge",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "description": "Knowledge graph for ralph-hero: semantic search, relationship traversal, and document indexing across thoughts/ documents. Optional companion to ralph-hero.",
5
5
  "author": {
6
6
  "name": "Chad Dubiel",
package/.mcp.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "ralph-knowledge": {
4
4
  "command": "npx",
5
- "args": ["-y", "ralph-hero-knowledge-index@0.1.30"]
5
+ "args": ["-y", "ralph-hero-knowledge-index@0.1.32"]
6
6
  }
7
7
  }
8
8
  }
@@ -0,0 +1,241 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * GH-927 — Re-run the 8-query golden eval with `rerank: true` against the live
4
+ * `~/.ralph-hero/knowledge.db`. Captures per-query rank-of-expected, cold/warm
5
+ * latency, and rerank logits. Output is JSON on stdout for downstream
6
+ * markdown formatting.
7
+ *
8
+ * Usage:
9
+ * node benchmark/eval-rerank.mjs > /tmp/eval-rerank-results.json
10
+ *
11
+ * The script imports the compiled `dist/` modules so it exercises the exact
12
+ * code path `knowledge_search` runs in production.
13
+ */
14
+ import { homedir } from "node:os";
15
+ import { join } from "node:path";
16
+ import { performance } from "node:perf_hooks";
17
+ import { KnowledgeDB } from "../dist/db.js";
18
+ import { FtsSearch } from "../dist/search.js";
19
+ import { VectorSearch } from "../dist/vector-search.js";
20
+ import { HybridSearch } from "../dist/hybrid-search.js";
21
+ import { embed } from "../dist/embedder.js";
22
+ import { Reranker } from "../dist/reranker.js";
23
+
24
+ const DB_PATH = process.env.RALPH_KNOWLEDGE_DB
25
+ ?? join(homedir(), ".ralph-hero", "knowledge.db");
26
+
27
+ /**
28
+ * The 8 golden queries from the 2026-04-29 baseline eval. `expectedSubstrings`
29
+ * lists path-segment substrings any of which counts as a hit (some queries
30
+ * have multiple legitimate primary docs per the baseline).
31
+ */
32
+ const QUERIES = [
33
+ {
34
+ n: 1,
35
+ query: "what causes the reindex to OOM in ralph-knowledge",
36
+ expectedSubstrings: ["2026-04-29-reindex-memory-profile"],
37
+ type: "specific-keyword",
38
+ },
39
+ {
40
+ n: 2,
41
+ query: "release transformer tensors after embedding to free memory",
42
+ expectedSubstrings: ["2026-04-29-GH-911-release-embedder-tensors"],
43
+ type: "specific-keyword",
44
+ },
45
+ {
46
+ n: 3,
47
+ query: "chunker forward progress infinite loop fix",
48
+ expectedSubstrings: ["2026-04-29-GH-916-chunker-no-progress-fix"],
49
+ type: "specific-keyword",
50
+ },
51
+ {
52
+ n: 4,
53
+ query: "dream-loop memory consolidation pipeline architecture",
54
+ expectedSubstrings: [
55
+ "2026-04-26-dreaming-research-trail-and-self-containment",
56
+ "2026-04-16-GH-0761",
57
+ ],
58
+ type: "mixed",
59
+ },
60
+ {
61
+ n: 5,
62
+ query: "cross-encoder reranker score calibration",
63
+ expectedSubstrings: ["2026-04-26-softmax-and-rerank-calibration"],
64
+ type: "mixed",
65
+ },
66
+ {
67
+ n: 6,
68
+ query: "wikilink extractor for markdown",
69
+ expectedSubstrings: ["2026-04-26-ralph-knowledge-wikilink-extractor"],
70
+ type: "specific-keyword",
71
+ },
72
+ {
73
+ n: 7,
74
+ query: "context handoff topology between agents",
75
+ expectedSubstrings: ["2026-04-22-context-handoff-topology"],
76
+ type: "mixed",
77
+ },
78
+ {
79
+ n: 8,
80
+ query: "landcrawler permit raw data migration hardening",
81
+ expectedSubstrings: ["2026-04-24-landcrawler-backend-hardening-postmortem"],
82
+ type: "specific-keyword",
83
+ },
84
+ ];
85
+
86
+ function findRank(results, expectedSubstrings) {
87
+ for (let i = 0; i < results.length; i++) {
88
+ const r = results[i];
89
+ const path = (r.path ?? "") + (r.id ?? "");
90
+ for (const sub of expectedSubstrings) {
91
+ if (path.includes(sub)) return i + 1;
92
+ }
93
+ }
94
+ return null;
95
+ }
96
+
97
+ async function runOne(hybrid, q, withRerank) {
98
+ const t0 = performance.now();
99
+ const results = await hybrid.search(q.query, {
100
+ limit: 10,
101
+ diagnosticMode: true,
102
+ rerank: withRerank,
103
+ });
104
+ const elapsed = performance.now() - t0;
105
+ return { results, elapsedMs: elapsed };
106
+ }
107
+
108
+ async function main() {
109
+ console.error(`[eval-rerank] DB: ${DB_PATH}`);
110
+ const db = new KnowledgeDB(DB_PATH);
111
+ const fts = new FtsSearch(db);
112
+ const vec = new VectorSearch(db);
113
+ const reranker = new Reranker();
114
+ const hybrid = new HybridSearch(db, fts, vec, embed, reranker);
115
+
116
+ // Warm up the embedder once (it's a separate model from the reranker; we
117
+ // care about cold-start of the *reranker*, not the embedder, so isolate it).
118
+ console.error(`[eval-rerank] warming embedder...`);
119
+ await hybrid.search("warmup", { limit: 1 });
120
+
121
+ const out = [];
122
+ let firstRerankCall = true;
123
+
124
+ for (const q of QUERIES) {
125
+ console.error(`[eval-rerank] Q${q.n}: ${q.query}`);
126
+
127
+ // First rerank invocation is the cold-start one (model load + first batch).
128
+ // Subsequent invocations are warm.
129
+ const cold = await runOne(hybrid, q, true);
130
+ const wasFirstCall = firstRerankCall;
131
+ firstRerankCall = false;
132
+
133
+ // Warm runs: 3 repeats to compute median + p95.
134
+ const warmRuns = [];
135
+ for (let i = 0; i < 3; i++) {
136
+ warmRuns.push(await runOne(hybrid, q, true));
137
+ }
138
+
139
+ // Also capture the no-rerank baseline order from the same DB so the eval
140
+ // doc can verify the baseline column is reproducible (sanity check).
141
+ const noRerank = await runOne(hybrid, q, false);
142
+
143
+ const sortedWarm = warmRuns.map((r) => r.elapsedMs).sort((a, b) => a - b);
144
+ const median = sortedWarm[Math.floor(sortedWarm.length / 2)];
145
+ const p95Idx = Math.min(sortedWarm.length - 1, Math.floor(sortedWarm.length * 0.95));
146
+
147
+ const top10 = cold.results.slice(0, 10).map((r) => ({
148
+ id: r.id,
149
+ path: r.path,
150
+ title: r.title,
151
+ score: r.score,
152
+ rerankScore: r.rerankScore,
153
+ ftsScore: r.ftsScore,
154
+ vecDistance: r.vecDistance,
155
+ hitSources: r.hitSources,
156
+ }));
157
+ const noRerankTop10 = noRerank.results.slice(0, 10).map((r) => ({
158
+ id: r.id,
159
+ path: r.path,
160
+ title: r.title,
161
+ score: r.score,
162
+ }));
163
+
164
+ const rank = findRank(cold.results, q.expectedSubstrings);
165
+ const rankNoRerank = findRank(noRerank.results, q.expectedSubstrings);
166
+ const expectedHit = rank !== null
167
+ ? cold.results[rank - 1]
168
+ : null;
169
+
170
+ out.push({
171
+ n: q.n,
172
+ query: q.query,
173
+ type: q.type,
174
+ expectedSubstrings: q.expectedSubstrings,
175
+ rank,
176
+ rankNoRerank,
177
+ expected: expectedHit
178
+ ? {
179
+ id: expectedHit.id,
180
+ path: expectedHit.path,
181
+ rerankScore: expectedHit.rerankScore,
182
+ rrfScore: expectedHit.score,
183
+ }
184
+ : null,
185
+ latency: {
186
+ coldStartMs: wasFirstCall ? cold.elapsedMs : null,
187
+ firstCallMs: cold.elapsedMs,
188
+ warmMedianMs: median,
189
+ warmP95Ms: sortedWarm[p95Idx],
190
+ warmRunsMs: sortedWarm,
191
+ noRerankMs: noRerank.elapsedMs,
192
+ },
193
+ top10,
194
+ noRerankTop10,
195
+ });
196
+ }
197
+
198
+ const ranksWithRerank = out.map((o) => o.rank);
199
+ const ranksNoRerank = out.map((o) => o.rankNoRerank);
200
+ const hitAt = (ranks, k) => ranks.filter((r) => r !== null && r <= k).length;
201
+ const mrr = (ranks) =>
202
+ ranks.reduce((a, r) => a + (r === null ? 0 : 1 / r), 0) / ranks.length;
203
+
204
+ const aggregate = {
205
+ rerank: {
206
+ hitAt1: `${hitAt(ranksWithRerank, 1)}/${ranksWithRerank.length}`,
207
+ hitAt5: `${hitAt(ranksWithRerank, 5)}/${ranksWithRerank.length}`,
208
+ hitAt10: `${hitAt(ranksWithRerank, 10)}/${ranksWithRerank.length}`,
209
+ mrr: mrr(ranksWithRerank),
210
+ },
211
+ noRerank: {
212
+ hitAt1: `${hitAt(ranksNoRerank, 1)}/${ranksNoRerank.length}`,
213
+ hitAt5: `${hitAt(ranksNoRerank, 5)}/${ranksNoRerank.length}`,
214
+ hitAt10: `${hitAt(ranksNoRerank, 10)}/${ranksNoRerank.length}`,
215
+ mrr: mrr(ranksNoRerank),
216
+ },
217
+ };
218
+
219
+ // Latency aggregate
220
+ const allCold = out.map((o) => o.latency.coldStartMs).filter((x) => x != null);
221
+ const allWarmMedian = out.map((o) => o.latency.warmMedianMs);
222
+ const allFirst = out.map((o) => o.latency.firstCallMs);
223
+ aggregate.latency = {
224
+ coldStartMs: allCold[0] ?? null,
225
+ avgWarmMedianMs:
226
+ allWarmMedian.reduce((a, x) => a + x, 0) / allWarmMedian.length,
227
+ avgFirstCallMs:
228
+ allFirst.reduce((a, x) => a + x, 0) / allFirst.length,
229
+ avgNoRerankMs:
230
+ out.reduce((a, o) => a + o.latency.noRerankMs, 0) / out.length,
231
+ };
232
+
233
+ console.log(JSON.stringify({ queries: out, aggregate, dbPath: DB_PATH }, null, 2));
234
+ console.error(`[eval-rerank] done; aggregate:`, aggregate);
235
+ db.close();
236
+ }
237
+
238
+ main().catch((e) => {
239
+ console.error(e);
240
+ process.exit(1);
241
+ });
package/dist/chunker.js CHANGED
@@ -127,6 +127,10 @@ function buildChunk(originalText, atoms, index) {
127
127
  * chunk ended at `prevEnd`. We walk backward through the atom list to find
128
128
  * the atom whose start >= prevEnd - chunkOverlap; that atom begins the
129
129
  * overlap region.
130
+ *
131
+ * NOTE: this function may return an index <= the previous chunk's first atom
132
+ * when the previous chunk consisted of a single atom shorter than chunkOverlap.
133
+ * The caller in chunkText clamps the result to ensure forward progress.
130
134
  */
131
135
  function findOverlapStartIndex(atoms, lastEndAtomIndex, prevEnd, chunkOverlap) {
132
136
  if (chunkOverlap <= 0) {
@@ -212,7 +216,14 @@ export function chunkText(text, opts = {}) {
212
216
  // Compute overlap start for the next chunk.
213
217
  const lastEndAtomIdx = j - 1;
214
218
  const nextStart = findOverlapStartIndex(atoms, lastEndAtomIdx, chunk.charEnd, chunkOverlap);
215
- i = nextStart;
219
+ // Ensure forward progress: when a chunk consists of a single atom shorter
220
+ // than chunkOverlap, the overlap walk would land back on the same atom.
221
+ // Clamp to i + 1 in that case so we always advance, accepting that the
222
+ // resulting chunks will not overlap (this is the only correct option:
223
+ // overlap requires that the next chunk start within the previous chunk's
224
+ // span, but if the previous chunk has only one atom, there is no earlier
225
+ // position within its span to start from).
226
+ i = nextStart > i ? nextStart : i + 1;
216
227
  }
217
228
  return chunks;
218
229
  }
@@ -1 +1 @@
1
- {"version":3,"file":"chunker.js","sourceRoot":"","sources":["../src/chunker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chunker.js","sourceRoot":"","sources":["../src/chunker.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,35 @@
1
1
  import type { KnowledgeDB } from "./db.js";
2
2
  import type { FtsSearch, SearchOptions, SearchResult } from "./search.js";
3
3
  import type { VectorSearch } from "./vector-search.js";
4
+ import { type Reranker } from "./reranker.js";
4
5
  export type EmbedFn = (text: string) => Promise<Float32Array>;
5
6
  export declare class HybridSearch {
6
7
  private readonly db;
7
8
  private readonly fts;
8
9
  private readonly vec;
9
10
  private readonly embedFn;
11
+ /**
12
+ * Optional cross-encoder reranker (Phase 2, GH-925). When provided AND
13
+ * `options.rerank === true`, the post-RRF top-N candidate set is rescored
14
+ * by the cross-encoder before MMR / `slice(limit)`. When omitted, the
15
+ * `rerank` option is silently ignored — defensive fallback for incremental
16
+ * rollouts where `index.ts` may register `HybridSearch` before the
17
+ * reranker is wired up. Tests inject a deterministic stub to avoid the
18
+ * ~580 MB ONNX model download.
19
+ */
20
+ private readonly reranker?;
10
21
  private static readonly RRF_K;
11
- constructor(db: KnowledgeDB, fts: FtsSearch, vec: VectorSearch, embedFn: EmbedFn);
22
+ constructor(db: KnowledgeDB, fts: FtsSearch, vec: VectorSearch, embedFn: EmbedFn,
23
+ /**
24
+ * Optional cross-encoder reranker (Phase 2, GH-925). When provided AND
25
+ * `options.rerank === true`, the post-RRF top-N candidate set is rescored
26
+ * by the cross-encoder before MMR / `slice(limit)`. When omitted, the
27
+ * `rerank` option is silently ignored — defensive fallback for incremental
28
+ * rollouts where `index.ts` may register `HybridSearch` before the
29
+ * reranker is wired up. Tests inject a deterministic stub to avoid the
30
+ * ~580 MB ONNX model download.
31
+ */
32
+ reranker?: Reranker | undefined);
12
33
  /**
13
34
  * Returns true when the `chunks` table exists (schema v3+). When absent we
14
35
  * behave as if all vector ids are doc ids (pre-chunking behavior).
@@ -1,3 +1,4 @@
1
+ import { truncateForRerank } from "./reranker.js";
1
2
  /**
2
3
  * Maximum snippet length (in characters) when the snippet is sourced from a
3
4
  * chunk's content. Keeps the MCP payload compact while still representative.
@@ -8,12 +9,24 @@ export class HybridSearch {
8
9
  fts;
9
10
  vec;
10
11
  embedFn;
12
+ reranker;
11
13
  static RRF_K = 60;
12
- constructor(db, fts, vec, embedFn) {
14
+ constructor(db, fts, vec, embedFn,
15
+ /**
16
+ * Optional cross-encoder reranker (Phase 2, GH-925). When provided AND
17
+ * `options.rerank === true`, the post-RRF top-N candidate set is rescored
18
+ * by the cross-encoder before MMR / `slice(limit)`. When omitted, the
19
+ * `rerank` option is silently ignored — defensive fallback for incremental
20
+ * rollouts where `index.ts` may register `HybridSearch` before the
21
+ * reranker is wired up. Tests inject a deterministic stub to avoid the
22
+ * ~580 MB ONNX model download.
23
+ */
24
+ reranker) {
13
25
  this.db = db;
14
26
  this.fts = fts;
15
27
  this.vec = vec;
16
28
  this.embedFn = embedFn;
29
+ this.reranker = reranker;
17
30
  }
18
31
  /**
19
32
  * Returns true when the `chunks` table exists (schema v3+). When absent we
@@ -48,7 +61,7 @@ export class HybridSearch {
48
61
  .get(chunkId);
49
62
  }
50
63
  async search(query, options = {}) {
51
- const { type, tags, includeSuperseded = false, limit = 20, memoryTier, lambda, diagnosticMode = false, } = options;
64
+ const { type, tags, includeSuperseded = false, limit = 20, memoryTier, lambda, diagnosticMode = false, rerank = false, } = options;
52
65
  // Run FTS and vector search (FTS already applies memoryTier filter in SQL
53
66
  // when the schema supports it).
54
67
  const ftsResults = this.fts.search(query, {
@@ -218,6 +231,91 @@ export class HybridSearch {
218
231
  r.hitSources = sources;
219
232
  }
220
233
  }
234
+ // Cross-encoder rerank splice (Phase 2, GH-925; tuned post-#927 eval).
235
+ // Runs AFTER post-filters, chunk-meta enrichment, and diagnostic-mode
236
+ // population, but BEFORE the optional MMR pass. Decisions captured here:
237
+ //
238
+ // (a) **Score semantics** — `score` continues to mean "RRF score" so
239
+ // callers that sort/filter on it stay stable across `rerank` on/off.
240
+ // The cross-encoder logit is stamped onto the new `rerankScore` field
241
+ // (mirrors the `ftsScore` / `vecDistance` diagnostic-field pattern).
242
+ // This is Constraint 7 from the GH-0923 group plan.
243
+ //
244
+ // (b) **Score fusion (post-#927 tuning)** — the rerank-sorted order is a
245
+ // WEIGHTED BLEND of normalized RRF score and sigmoid(logit), NOT a
246
+ // pure replace. The 8-query golden eval (GH-927) showed pure-replace
247
+ // dropped Hit@1 from 62.5% to 25% on this corpus because off-the-shelf
248
+ // BGE-Reranker-v2-m3 systematically over-weights critique/review docs
249
+ // vs the underlying plans/research they critique, and demotes correct
250
+ // docs whose chunks lack the literal query terms. Blending preserves
251
+ // the retriever's high ceiling while letting the reranker break ties
252
+ // and refine close calls. RERANK_FUSION_ALPHA is the RRF weight; the
253
+ // remainder is the sigmoid-of-logit weight. 0.5 = equal weight.
254
+ //
255
+ // (c) **Snippet-only input** — the reranker scores `snippet` alone, NOT
256
+ // `${title}\n${snippet}`. Per #927, the title prefix amplifies the
257
+ // critique-bias failure mode because critique titles (e.g.,
258
+ // "GH-911-critique") engage the question vocabulary as densely as
259
+ // the body. Dropping the title prefix lets the model judge on the
260
+ // chunk content the retriever actually selected.
261
+ //
262
+ // (d) **Ordering rule** — when both `rerank: true` AND `lambda < 1.0` are
263
+ // set, rerank applies BEFORE MMR. MMR receives the blend-sorted
264
+ // `filtered` array. Rationale: rerank has already determined "most
265
+ // relevant"; MMR adds diversity over that relevance order. MMR's
266
+ // relevance term still uses the RRF `score` field (NOT `rerankScore`)
267
+ // so the diversity / relevance trade-off math stays unchanged from
268
+ // the pure-RRF path — Phase 1 (GH-902) calibration carried over.
269
+ //
270
+ // (e) **Fallback for missing ids** — if the reranker's score map omits a
271
+ // doc id, that doc keeps `rerankScore = undefined` and falls back to
272
+ // pure RRF placement via `sigmoid(0) = 0.5` neutral in the blend.
273
+ // Docs beyond the rerank window (top-N) keep their RRF position.
274
+ //
275
+ // (f) **Defensive guard** — if `rerank: true` but no `Reranker` was
276
+ // injected at construction time, the splice is a no-op and the RRF
277
+ // order is returned. Lets `index.ts` adopt the option incrementally.
278
+ if (rerank && this.reranker && filtered.length > 0) {
279
+ // Rerank window: at least 50, scale to 5x the requested limit, cap at
280
+ // the candidate set size. Larger windows trade latency for recall.
281
+ const topN = Math.min(filtered.length, Math.max(50, limit * 5));
282
+ const rerankSet = filtered.slice(0, topN);
283
+ const tail = filtered.slice(topN);
284
+ // Snippet-only input — see decision (c) above. Title prefix dropped
285
+ // because it pumps critique-doc scores per the #927 eval analysis.
286
+ const inputs = rerankSet.map((r) => ({
287
+ id: r.id,
288
+ text: truncateForRerank(r.snippet),
289
+ }));
290
+ const scoreMap = await this.reranker.score(query, inputs);
291
+ // Stamp the logit onto each candidate. Missing ids leave rerankScore
292
+ // undefined (see fallback note (e) above).
293
+ for (const r of rerankSet) {
294
+ const logit = scoreMap.get(r.id);
295
+ if (logit !== undefined) {
296
+ r.rerankScore = logit;
297
+ }
298
+ }
299
+ // Score fusion: blend max-normalized RRF score with sigmoid(logit).
300
+ // Both terms live in [0, 1], so a 0.5/0.5 weight gives equal voice.
301
+ // See decision (b) above for the eval-driven rationale.
302
+ const RERANK_FUSION_ALPHA = 0.5;
303
+ let maxRrf = 0;
304
+ for (const r of rerankSet) {
305
+ if (r.score > maxRrf)
306
+ maxRrf = r.score;
307
+ }
308
+ const sigmoid = (x) => 1 / (1 + Math.exp(-x));
309
+ const blendedScore = (r) => {
310
+ const normRrf = maxRrf > 0 ? r.score / maxRrf : 0;
311
+ const normRerank = r.rerankScore !== undefined ? sigmoid(r.rerankScore) : 0.5;
312
+ return RERANK_FUSION_ALPHA * normRrf + (1 - RERANK_FUSION_ALPHA) * normRerank;
313
+ };
314
+ // Re-sort the rerank window by blended score descending.
315
+ rerankSet.sort((a, b) => blendedScore(b) - blendedScore(a));
316
+ // Reassemble: blend-sorted top-N followed by the un-reranked tail.
317
+ filtered = [...rerankSet, ...tail];
318
+ }
221
319
  // MMR diversity rerank (Phase 1, GH-902). Opt-in via `lambda` < 1.0.
222
320
  // When omitted or `lambda === 1.0`, the pure-RRF order is preserved
223
321
  // byte-identically. Values outside [0, 1] are silently clamped.
@@ -1 +1 @@
1
- {"version":3,"file":"hybrid-search.js","sourceRoot":"","sources":["../src/hybrid-search.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAa9B,MAAM,OAAO,YAAY;IAIJ;IACA;IACA;IACA;IANX,MAAM,CAAU,KAAK,GAAG,EAAE,CAAC;IAEnC,YACmB,EAAe,EACf,GAAc,EACd,GAAiB,EACjB,OAAgB;QAHhB,OAAE,GAAF,EAAE,CAAa;QACf,QAAG,GAAH,GAAG,CAAW;QACd,QAAG,GAAH,GAAG,CAAc;QACjB,YAAO,GAAP,OAAO,CAAS;IAChC,CAAC;IAEJ;;;OAGG;IACK,iBAAiB;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE;aACnB,OAAO,CACN,qEAAqE,CACtE;aACA,GAAG,EAAE,CAAC;QACT,OAAO,GAAG,KAAK,SAAS,CAAC;IAC3B,CAAC;IAED;;;;OAIG;IACK,cAAc,CAAC,KAAa;QAClC,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,MAAM,KAAK,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QAChC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACvC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,KAAK,CAAC;QAC/D,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAChC,CAAC;IAEO,UAAU,CAAC,OAAe;QAChC,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;YAAE,OAAO,SAAS,CAAC;QAChD,OAAO,IAAI,CAAC,EAAE,CAAC,EAAE;aACd,OAAO,CACN;kCAC0B,CAC3B;aACA,GAAG,CAAC,OAAO,CAAyB,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,MAAM,CACV,KAAa,EACb,UAAyB,EAAE;QAE3B,MAAM,EACJ,IAAI,EACJ,IAAI,EACJ,iBAAiB,GAAG,KAAK,EACzB,KAAK,GAAG,EAAE,EACV,UAAU,EACV,MAAM,EACN,cAAc,GAAG,KAAK,GACvB,GAAG,OAAO,CAAC;QAEZ,0EAA0E;QAC1E,gCAAgC;QAChC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE;YACxC,iBAAiB,EAAE,IAAI;YACvB,KAAK,EAAE,KAAK,GAAG,CAAC;YAChB,UAAU;SACX,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,UAAU,GAAmB,IAAI,CAAC,GAAG,CAAC,MAAM,CAChD,cAAc,EACd,KAAK,GAAG,CAAC,CACV,CAAC;QAEF,0EAA0E;QAC1E,0EAA0E;QAC1E,wEAAwE;QACxE,MAAM,eAAe,GAAG,cAAc;YACpC,CAAC,CAAC,IAAI,GAAG,EAAkB;YAC3B,CAAC,CAAC,IAAI,CAAC;QACT,MAAM,kBAAkB,GAAG,cAAc;YACvC,CAAC,CAAC,IAAI,GAAG,EAAkB;YAC3B,CAAC,CAAC,IAAI,CAAC;QACT,IAAI,cAAc,IAAI,eAAe,EAAE,CAAC;YACtC,KAAK,MAAM,MAAM,IAAI,UAAU,EAAE,CAAC;gBAChC,qEAAqE;gBACrE,oCAAoC;gBACpC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;oBACpC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC/C,CAAC;YACH,CAAC;QACH,CAAC;QAED,0EAA0E;QAC1E,mEAAmE;QACnE,mEAAmE;QACnE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAqB,CAAC;QAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC1C,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,SAAS,CAAC,sCAAsC;YACxE,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE;gBACjB,QAAQ,EAAE,CAAC;gBACX,WAAW,EAAE,GAAG,CAAC,EAAE;gBACnB,WAAW,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE;aAC/B,CAAC,CAAC;YACH,uEAAuE;YACvE,qEAAqE;YACrE,0CAA0C;YAC1C,IAAI,cAAc,IAAI,kBAAkB,EAAE,CAAC;gBACzC,kBAAkB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;QAED,wEAAwE;QACxE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,MAAM,cAAc,GAAG,IAAI,GAAG,EAA6C,CAAC;QAE5E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YAClD,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;QACnD,CAAC;QAED,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACtC,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,GAAG,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;YAChE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;YACvD,wCAAwC;YACxC,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACjD,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;YACpF,CAAC;QACH,CAAC;QAED,uDAAuD;QACvD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;QAChD,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QACvB,CAAC;QAED,sEAAsE;QACtE,uEAAuE;QACvE,eAAe;QACf,MAAM,QAAQ,GAAmB,EAAE,CAAC;QAEpC,KAAK,MAAM,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,MAAM,EAAE,CAAC;YACpC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC/B,IAAI,MAAM,EAAE,CAAC;gBACX,sEAAsE;gBACtE,kDAAkD;gBAClD,MAAM,OAAO,GACX,MAAM,IAAI,MAAM,CAAC,WAAW;oBAC1B,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC;oBAChD,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;gBACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;YACzD,CAAC;iBAAM,CAAC;gBACN,sDAAsD;gBACtD,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;gBACpC,0DAA0D;gBAC1D,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM;oBAAE,SAAS;gBACjC,MAAM,OAAO,GAAG,MAAM;oBACpB,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,iBAAiB,CAAC;oBAChD,CAAC,CAAC,EAAE,CAAC;gBACP,QAAQ,CAAC,IAAI,CAAC;oBACZ,EAAE,EAAE,GAAG,CAAC,EAAE;oBACV,IAAI,EAAE,GAAG,CAAC,IAAc;oBACxB,KAAK,EAAE,GAAG,CAAC,KAAK;oBAChB,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,KAAK,EAAE,QAAQ;oBACf,OAAO;iBACR,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,+BAA+B;QAC/B,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QAE3C,0BAA0B;QAC1B,IAAI,QAAQ,GAAG,QAAQ,CAAC;QACxB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC;QAC/D,CAAC;QAED,oBAAoB;QACpB,IAAI,IAAI,EAAE,CAAC;YACT,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACrD,CAAC;QAED,oBAAoB;QACpB,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;YAC7B,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACtC,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5C,CAAC,CAAC,CAAC;QACL,CAAC;QAED,sEAAsE;QACtE,uEAAuE;QACvE,sDAAsD;QACtD,IAAI,UAAU,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;YACvC,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACzC,gDAAgD;gBAChD,OAAO,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,UAAU,CAAC;YACxC,CAAC,CAAC,CAAC;QACL,CAAC;QAED,oEAAoE;QACpE,kBAAkB;QAClB,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACtC,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5C,IAAI,CAAC,KAAK;gBAAE,SAAS;YACrB,CAAC,CAAC,WAAW,GAAG,KAAK,CAAC,EAAE,CAAC;YACzB,CAAC,CAAC,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC;YACjC,CAAC,CAAC,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC;YAC/B,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC;YAC3B,CAAC,CAAC,aAAa,GAAG,KAAK,CAAC,cAAc,CAAC;QACzC,CAAC;QAED,0EAA0E;QAC1E,yEAAyE;QACzE,oEAAoE;QACpE,IAAI,cAAc,IAAI,eAAe,IAAI,kBAAkB,EAAE,CAAC;YAC5D,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,MAAM,GAAG,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACtC,MAAM,GAAG,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACzC,MAAM,OAAO,GAAyB,EAAE,CAAC;gBACzC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;oBACtB,CAAC,CAAC,QAAQ,GAAG,GAAG,CAAC;oBACjB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACtB,CAAC;gBACD,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;oBACtB,CAAC,CAAC,WAAW,GAAG,GAAG,CAAC;oBACpB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBACtB,CAAC;gBACD,CAAC,CAAC,UAAU,GAAG,OAAO,CAAC;YACzB,CAAC;QACH,CAAC;QAED,qEAAqE;QACrE,oEAAoE;QACpE,gEAAgE;QAChE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YACjD,IAAI,OAAO,GAAG,GAAG,EAAE,CAAC;gBAClB,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACK,QAAQ,CACd,UAA0B,EAC1B,MAAc,EACd,KAAa,EACb,cAA8D;QAE9D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,UAAU,CAAC;QAE/C,uEAAuE;QACvE,uDAAuD;QACvD,IAAI,QAAQ,GAAG,QAAQ,CAAC;QACxB,IAAI,QAAQ,GAAG,CAAC,QAAQ,CAAC;QACzB,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,IAAI,CAAC,CAAC,KAAK,GAAG,QAAQ;gBAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC;YAC3C,IAAI,CAAC,CAAC,KAAK,GAAG,QAAQ;gBAAE,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC;QAC7C,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;QAClC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC5C,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,wEAAwE;YACxE,qDAAqD;YACrD,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACtE,CAAC;QAED,yEAAyE;QACzE,oEAAoE;QACpE,0DAA0D;QAC1D,MAAM,UAAU,GAAG,IAAI,GAAG,EAA+B,CAAC;QAC1D,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACtC,uEAAuE;YACvE,+DAA+D;YAC/D,MAAM,KAAK,GAAG,IAAI,EAAE,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC;YACpC,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;gBACnC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpC,CAAC;YACD,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC5B,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAmB,EAAE,CAAC;QACpC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACvD,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAU,CAAC,CAAC,CAAC;QAEzE,wEAAwE;QACxE,qEAAqE;QACrE,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;QACnD,KAAK,MAAM,CAAC,IAAI,UAAU;YAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAE1D,OAAO,QAAQ,CAAC,MAAM,GAAG,WAAW,IAAI,SAAS,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAC3D,IAAI,MAAM,GAAkB,IAAI,CAAC;YACjC,IAAI,YAAY,GAAG,CAAC,QAAQ,CAAC;YAE7B,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;gBAC3B,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;gBACnC,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;gBAC1C,MAAM,QAAQ,GAAG,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC;gBACnD,IAAI,QAAQ,GAAG,YAAY,EAAE,CAAC;oBAC5B,YAAY,GAAG,QAAQ,CAAC;oBACxB,MAAM,GAAG,EAAE,CAAC;gBACd,CAAC;YACH,CAAC;YAED,IAAI,MAAM,KAAK,IAAI;gBAAE,MAAM,CAAC,yDAAyD;YAErF,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAE,CAAC;YACxC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAEzB,uEAAuE;YACvE,kEAAkE;YAClE,+DAA+D;YAC/D,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACvC,IAAI,OAAO,EAAE,CAAC;gBACZ,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;oBAC3B,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBACpC,IAAI,CAAC,QAAQ;wBAAE,SAAS,CAAC,2CAA2C;oBACpE,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;oBACtD,MAAM,IAAI,GAAG,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;oBAC3C,IAAI,GAAG,GAAG,IAAI;wBAAE,gBAAgB,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;;;;OAKG;IACK,MAAM,CAAC,SAAS,CAAC,CAAe,EAAE,CAAe;QACvD,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;YAAE,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;YAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACpD,OAAO,CAAC,CAAC;IACX,CAAC"}
1
+ {"version":3,"file":"hybrid-search.js","sourceRoot":"","sources":["../src/hybrid-search.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -5,13 +5,22 @@ import { FtsSearch } from "./search.js";
5
5
  import { VectorSearch } from "./vector-search.js";
6
6
  import { HybridSearch } from "./hybrid-search.js";
7
7
  import { Traverser } from "./traverse.js";
8
+ import { Reranker } from "./reranker.js";
8
9
  /**
9
10
  * Options for `createServer`. When `embedFn` is provided it replaces the
10
11
  * production `embed` import, allowing tests to bypass the HuggingFace model
11
12
  * download.
13
+ *
14
+ * `rerankerFactory` mirrors the `embedFn` injection pattern: when provided,
15
+ * it produces the `Reranker` passed into `HybridSearch` so unit tests can
16
+ * supply a deterministic stub reranker without paying the ~580 MB ONNX
17
+ * model download. Production callers omit this field; the default `Reranker`
18
+ * is lazy-loaded and pays no cold-start cost until `rerank: true` is set on
19
+ * a `knowledge_search` call.
12
20
  */
13
21
  export interface CreateServerOptions {
14
22
  embedFn?: (text: string) => Promise<Float32Array>;
23
+ rerankerFactory?: () => Reranker;
15
24
  }
16
25
  export declare function createServer(dbPath: string, opts?: CreateServerOptions): {
17
26
  server: McpServer;
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ import { VectorSearch } from "./vector-search.js";
10
10
  import { HybridSearch } from "./hybrid-search.js";
11
11
  import { Traverser } from "./traverse.js";
12
12
  import { embed } from "./embedder.js";
13
+ import { Reranker } from "./reranker.js";
13
14
  import { formatSearchResults, formatTraverseResults } from "./format.js";
14
15
  import { registerGraphTools } from "./graph-tools.js";
15
16
  const DEFAULT_DB_PATH = join(homedir(), ".ralph-hero", "knowledge.db");
@@ -57,7 +58,12 @@ export function createServer(dbPath, opts = {}) {
57
58
  const fts = new FtsSearch(db);
58
59
  const vec = new VectorSearch(db);
59
60
  const embedImpl = opts.embedFn ?? embed;
60
- const hybrid = new HybridSearch(db, fts, vec, embedImpl);
61
+ // GH-926: production constructs a default `Reranker` (lazy no model load
62
+ // until first `rerank: true` call). Tests inject a stub via
63
+ // `rerankerFactory` to bypass the ONNX model download. Mirrors the
64
+ // `embedFn` injection above.
65
+ const reranker = opts.rerankerFactory ? opts.rerankerFactory() : new Reranker();
66
+ const hybrid = new HybridSearch(db, fts, vec, embedImpl, reranker);
61
67
  const traverser = new Traverser(db);
62
68
  server.tool("knowledge_search", "Search the knowledge base by keyword, semantic similarity, and tags. Returns ranked documents.", {
63
69
  query: z.string().describe("Search query (keywords or natural language)"),
@@ -87,6 +93,11 @@ export function createServer(dbPath, opts = {}) {
87
93
  .optional()
88
94
  .default(false)
89
95
  .describe("Include per-retriever diagnostic fields (fts_score, vec_distance, hit_sources) on each result. Default off — keeps payload byte-identical to today's response shape (Phase 2, GH-899 Track-B observability hook)."),
96
+ rerank: z
97
+ .boolean()
98
+ .optional()
99
+ .default(false)
100
+ .describe("Apply cross-encoder reranking to the post-RRF top-N candidates (BGE-Reranker-v2-m3-int8). Adds ~0.5-1s of latency on first call (cold-start model load) and ~25-45ms per pair on warm calls. Improves Hit@1 on specific-keyword queries; default off until the eval re-run confirms no regression on paraphrase queries."),
90
101
  }, async (args) => {
91
102
  try {
92
103
  const results = await hybrid.search(args.query, {
@@ -97,12 +108,13 @@ export function createServer(dbPath, opts = {}) {
97
108
  memoryTier: args.memory_tier,
98
109
  lambda: args.lambda,
99
110
  diagnosticMode: args.return_diagnostics,
111
+ rerank: args.rerank,
100
112
  });
101
113
  const enriched = results.map((r) => {
102
114
  // Start with the camelCase SearchResult shape so existing callers
103
115
  // keep working, then optionally add snake_case aliases for new
104
116
  // chunk + diagnostic fields and strip them when callers didn't opt in.
105
- const { chunkIndex, charStart, charEnd, contextPrefix, bestChunkId, ftsScore, vecDistance, hitSources, ...rest } = r;
117
+ const { chunkIndex, charStart, charEnd, contextPrefix, bestChunkId, ftsScore, vecDistance, hitSources, rerankScore, ...rest } = r;
106
118
  const base = { ...rest, tags: db.getTags(r.id) };
107
119
  if (args.return_chunk_meta) {
108
120
  if (chunkIndex !== undefined)
@@ -124,6 +136,14 @@ export function createServer(dbPath, opts = {}) {
124
136
  if (hitSources !== undefined)
125
137
  base.hit_sources = hitSources;
126
138
  }
139
+ // GH-926: rerank_score is a diagnostic field — surface it only when
140
+ // BOTH `rerank` and `return_diagnostics` are true. This matches the
141
+ // diagnostic-field discipline that hides fts_score/vec_distance
142
+ // unless diagnostics are explicitly requested.
143
+ if (args.rerank && args.return_diagnostics) {
144
+ if (rerankScore !== undefined)
145
+ base.rerank_score = rerankScore;
146
+ }
127
147
  // SearchResult does not carry githubIssue — fetch from documents table
128
148
  const doc = db.getDocument(r.id);
129
149
  if (doc?.githubIssue) {