1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
//! 0.8.2 Slice E1 — the CE reranker actually reranks.
//!
//! Runs ONLY under `--features default-reranker` (the whole target is
//! feature-gated in `Cargo.toml`). It exercises the real TinyBERT-L-2
//! cross-encoder: a `rerank_depth > 0` call over a fused pool where the CE
//! disagrees with the RRF order must REORDER the pool so the
//! genuinely-relevant passage rises above the spuriously top-RRF one.
//!
//! Against the pre-E1 stub (`try_get_loaded() → None`, `score() → 0.0`) the CE
//! path returns `None` → soft-fallback → no reorder → this test FAILS (RED).
//! With the real model loaded it reorders → PASS (GREEN).
//!
//! Loading the model on a cold cache performs ONE gated network fetch of the
//! pinned ~17 MB weights (sha256-verified), then caches under
//! `~/.cache/fathomdb/reranker/`. This is the sanctioned gated download
//! (not a FathomDB-default network call): the default build and the
//! `rerank_depth == 0` path never touch it.
use fathomdb_engine::{rerank_fused, IdSpace, SearchHit, SoftFallbackBranch};
fn hit(id: u64, body: &str, score: f64) -> SearchHit {
SearchHit {
// C-2 (0.8.19): typed id-space carrier; positional cursor in `write_cursor`.
id: IdSpace::content(id.to_string()),
write_cursor: id,
kind: "doc".to_string(),
body: body.to_string(),
score,
branch: SoftFallbackBranch::Vector,
source_id: fathomdb_engine::SourceId::new("test:fixture").expect("test source id"),
// 0.8.5 — additive CE score; None until set inside `ce_rerank` for in-pool hits.
ce_score: None,
}
}
/// 0.8.5 — the canonical Berlin reorder fixture shared by the α/pool_n tests.
/// A (id=1) is spuriously top of RRF but off-topic; B (id=2) is the relevant
/// population fact just below A; C (id=3) is a far-down span-widening filler.
fn berlin_fixture() -> (&'static str, Vec<SearchHit>) {
let query = "How many people live in Berlin?";
let a = hit(
1,
"Berlin is famous for its vibrant art scene, nightlife, and historic architecture.",
0.500,
);
let b = hit(2, "Berlin has a population of about 3.7 million inhabitants, making it the most populous city in Germany.", 0.499);
let c = hit(3, "The quick brown fox jumps over the lazy dog near the river.", 0.001);
(query, vec![a, b, c])
}
/// min-max RRF normalization over a pool's raw scores (mirrors `ce_rerank`).
fn rrf_norm(scores: &[f64], s: f64) -> f64 {
let lo = scores.iter().copied().fold(f64::INFINITY, f64::min);
let hi = scores.iter().copied().fold(f64::NEG_INFINITY, f64::max);
let span = hi - lo;
if span > 0.0 {
(s - lo) / span
} else {
1.0
}
}
/// Skip-guard: returns true when the CE model produced real scores (some in-pool
/// `ce_score` is `Some`). When the model is absent (cold cache + no network) the
/// soft-fallback path leaves every `ce_score == None` — a model-dependent test
/// must then bail rather than assert a reorder it cannot get.
fn model_scored(out: &[SearchHit]) -> bool {
out.iter().any(|h| h.ce_score.is_some())
}
// =================== 0.8.5 — α / pool_n / ce_score exposure ===================
/// REGRESSION PIN (C6 guard). The default config (`alpha=0.3`, `pool_n=rerank_depth`)
/// must reproduce the pre-slice blend EXACTLY: order `[B, A, C]` and each in-pool
/// `score == 0.3*ce_norm + 0.7*rrf_norm`. `ce_score` is the now-exposed `ce_norm`,
/// so the blend formula is checked against it directly — this locks the default α to
/// 0.3 (a drift to any other default flips this assertion).
#[test]
fn default_alpha_0_3_preserves_blend_and_order() {
let (query, input) = berlin_fixture();
let raw: Vec<f64> = input.iter().map(|h| h.score).collect();
let out = rerank_fused(query, input.clone(), 3, 0.3, 3);
if !model_scored(&out) {
eprintln!("[SKIP] CE model unavailable — default-blend pin needs the cached reranker");
return;
}
assert_eq!(
out.iter().map(|h| h.id).collect::<Vec<_>>(),
vec![2, 1, 3],
"α=0.3 default order must stay [B, A, C] (C6 guard)"
);
for h in &out {
let ce = h.ce_score.expect("in-pool hit must carry ce_score at depth==pool==len");
// recover the raw score for this id from the input to compute rrf_norm.
let original = raw[(h.id - 1) as usize];
let expected = 0.3 * ce + 0.7 * rrf_norm(&raw, original);
assert!(
(h.score - expected).abs() < 1e-9,
"id={} blended score {} != 0.3*ce({}) + 0.7*rrf; expected {}",
h.id,
h.score,
ce,
expected
);
}
}
/// α=1.0 → pure CE: in-pool order == sort-by-`ce_norm` desc, and each in-pool
/// `score == ce_score` exactly (the RRF term drops out at α=1.0).
#[test]
fn alpha_1_0_is_pure_ce_order() {
let (query, input) = berlin_fixture();
let out = rerank_fused(query, input.clone(), 3, 1.0, 3);
if !model_scored(&out) {
eprintln!("[SKIP] CE model unavailable — α=1.0 ordering needs the cached reranker");
return;
}
// score == ce_norm exactly at α=1.0.
for h in &out {
let ce = h.ce_score.expect("in-pool ce_score");
assert!((h.score - ce).abs() < 1e-12, "α=1.0: score must equal ce_norm");
}
// monotonically non-increasing by score (== ce_norm desc).
for w in out.windows(2) {
assert!(w[0].score >= w[1].score, "α=1.0 pool must be sorted by ce_norm desc");
}
assert_eq!(out[0].id, 2, "the population fact (B) must top a pure-CE ranking");
}
/// α=0.0 → pure RRF: the CE weight vanishes so the order is the input RRF order
/// (input is already score-descending → unchanged ids [1,2,3]). ce_score is still
/// computed (`Some`) for in-pool hits.
#[test]
fn alpha_0_0_is_pure_rrf_order() {
let (query, input) = berlin_fixture();
let out = rerank_fused(query, input.clone(), 3, 0.0, 3);
if !model_scored(&out) {
eprintln!("[SKIP] CE model unavailable — α=0.0 ordering needs the cached reranker");
return;
}
assert_eq!(
out.iter().map(|h| h.id).collect::<Vec<_>>(),
vec![1, 2, 3],
"α=0.0 must reproduce the input RRF order"
);
}
/// α out of `[0,1]` is clamped silently: α=-0.5 behaves as α=0.0, α=2.0 as α=1.0.
#[test]
fn alpha_is_clamped_to_unit_interval() {
let (query, input) = berlin_fixture();
let lo = rerank_fused(query, input.clone(), 3, -0.5, 3);
let lo0 = rerank_fused(query, input.clone(), 3, 0.0, 3);
let hi = rerank_fused(query, input.clone(), 3, 2.0, 3);
let hi1 = rerank_fused(query, input.clone(), 3, 1.0, 3);
assert_eq!(lo, lo0, "α=-0.5 must behave exactly as α=0.0 (clamp)");
assert_eq!(hi, hi1, "α=2.0 must behave exactly as α=1.0 (clamp)");
}
/// pool_n clamps to `hits.len()`; pool_n < rerank_depth reranks only the top
/// `pool_n` and leaves the remainder untouched with `ce_score == None`.
#[test]
fn pool_n_clamps_and_bounds_the_reranked_pool() {
let (query, input) = berlin_fixture();
let raw_c = input[2].score;
// pool_n=2 < depth=3 → only A,B reranked; C is the untouched remainder.
let out = rerank_fused(query, input.clone(), 3, 1.0, 2);
if !model_scored(&out) {
eprintln!("[SKIP] CE model unavailable — pool_n bound needs the cached reranker");
return;
}
assert_eq!(out.len(), 3);
let last = out.last().unwrap();
assert_eq!(last.id, 3, "the out-of-pool filler stays last");
assert_eq!(last.ce_score, None, "remainder hit must keep ce_score == None");
assert!((last.score - raw_c).abs() < 1e-12, "remainder keeps its original RRF score");
assert!(out[0].ce_score.is_some() && out[1].ce_score.is_some(), "in-pool hits carry ce_score");
// pool_n > len clamps to len → identical to pool_n == len.
let wide = rerank_fused(query, input.clone(), 3, 1.0, 10);
let exact = rerank_fused(query, input.clone(), 3, 1.0, 3);
assert_eq!(wide, exact, "pool_n > len must clamp to len");
}
/// ce_score is `Some(ce_norm) ∈ [0,1]` for in-pool hits and `None` for the
/// remainder (D1). depth=0 is the identity gate → `ce_score == None` everywhere.
#[test]
fn ce_score_population_scope() {
let (query, input) = berlin_fixture();
// depth=0 → identity, no model load, ce_score None on every hit.
let identity = rerank_fused(query, input.clone(), 0, 1.0, 3);
assert_eq!(identity, input, "depth=0 stays byte-identical incl. ce_score == None");
assert!(identity.iter().all(|h| h.ce_score.is_none()));
let out = rerank_fused(query, input.clone(), 3, 1.0, 3);
if !model_scored(&out) {
eprintln!("[SKIP] CE model unavailable — ce_score values need the cached reranker");
return;
}
for h in &out {
let ce = h.ce_score.expect("all three hits are in-pool at depth==pool==len");
assert!((0.0..=1.0).contains(&ce), "ce_norm must be in [0,1], got {ce}");
}
}
/// CE disagrees with RRF → reorder. The pool is constructed so that:
/// - `A` (id=1) is spuriously top of the RRF order but irrelevant to the query;
/// - `B` (id=2) is just barely below `A` in RRF but is the relevant passage;
/// - `C` (id=3) is a far-down filler that WIDENS the min-max RRF span so the
/// normalized A↔B gap is tiny (≈0.002) — small enough for the α=0.3 CE weight
/// to flip it when the CE strongly prefers `B`.
///
/// Asserts `B` is ranked first after rerank (it was second before).
#[test]
fn ce_rerank_reorders_when_ce_disagrees_with_rrf() {
let query = "How many people live in Berlin?";
// A: top RRF but off-topic. B: relevant population fact. C: filler (span widener).
let a = hit(
1,
"Berlin is famous for its vibrant art scene, nightlife, and historic architecture.",
0.500,
);
let b = hit(2, "Berlin has a population of about 3.7 million inhabitants, making it the most populous city in Germany.", 0.499);
let c = hit(3, "The quick brown fox jumps over the lazy dog near the river.", 0.001);
let input = vec![a.clone(), b.clone(), c.clone()];
// Sanity: A is first, B second in the RRF order we feed in.
assert_eq!(input[0].id, 1);
assert_eq!(input[1].id, 2);
let out = rerank_fused(query, input.clone(), 3, 0.3, 3);
assert_ne!(
out, input,
"CE rerank must change the order (RED against the 0.0-logit stub, which is identity). \
If this is the first run on a cold cache and the network is unavailable, the model \
could not load — re-run with network access to fetch the pinned reranker weights."
);
assert_eq!(
out[0].id, 2,
"the relevant passage (B, id=2) must rank first after CE rerank; got id={}",
out[0].id
);
}
/// The soft-fallback identity contract still holds WITH the feature compiled in:
/// `rerank_depth == 0` returns the pool byte-identical (no model load, no
/// network), even though the CE path is now real.
#[test]
fn ce_feature_on_depth_0_is_identity() {
let hits = vec![hit(10, "alpha", 0.05), hit(20, "beta", 0.04), hit(30, "gamma", 0.03)];
let out = rerank_fused("anything", hits.clone(), 0, 0.3, 0);
assert_eq!(out, hits, "depth=0 must stay byte-identical even under default-reranker");
}
/// Empty-hits short-circuit: `rerank_fused` with `rerank_depth > 0` but an
/// empty hit set must return an empty vec immediately — without driving the
/// singleton `try_get_loaded()` for nothing.
///
/// This pins the `hits.is_empty()` guard added in fix-1 (codex §9 [P2]).
/// Without the guard, the implementation would call `try_get_loaded()` on every
/// empty search at `rerank_depth > 0`, potentially loading/downloading the ~17 MB
/// model for no benefit, and memoizing a transient load failure process-wide.
///
/// The correctness contract (empty-in → empty-out) is equivalent with or without
/// the guard; the assertion below is the regression anchor.
#[test]
fn ce_rerank_empty_hits_returns_empty_immediately() {
let hits: Vec<SearchHit> = vec![];
let out = rerank_fused("any query", hits.clone(), 10, 0.3, 10);
assert!(
out.is_empty(),
"rerank_fused with rerank_depth>0 and empty input must return empty immediately"
);
}
/// 0.8.5 (codex §9 P2-1) — a non-finite α (NaN / ±inf) must NOT poison the blend.
/// `f64::clamp(NaN)` returns NaN, which would make every blended score NaN and
/// destroy the ranking. The engine falls back to the documented default α=0.3,
/// so the result is byte-identical to the α=0.3 order with all-finite scores.
#[test]
fn nonfinite_alpha_falls_back_to_default() {
let (query, input) = berlin_fixture();
let out_default = rerank_fused(query, input.clone(), 3, 0.3, 3);
if !model_scored(&out_default) {
eprintln!("[SKIP] CE model unavailable — NaN-α fallback pin needs the cached reranker");
return;
}
for bad in [f64::NAN, f64::INFINITY, f64::NEG_INFINITY] {
let out = rerank_fused(query, input.clone(), 3, bad, 3);
assert!(
out.iter().all(|h| h.score.is_finite()),
"α={bad} produced a non-finite blended score"
);
assert_eq!(
out.iter().map(|h| h.id).collect::<Vec<_>>(),
out_default.iter().map(|h| h.id).collect::<Vec<_>>(),
"α={bad} must fall back to the α=0.3 default order"
);
}
}