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
//! 0.8.1 Slice 10 / R1 — cross-encoder reranker unit tests.
//!
//! Tests the new `rerank_fused(query, hits, depth)` signature, its
//! soft-fallback contract (`depth=0` or model absent → byte-identical identity),
//! determinism, and the recall-gate schema pin.
//!
//! All tests in this file run in the **default build** (no `default-reranker`
//! feature). The CE inference path is feature-gated; these tests cover the
//! soft-fallback path which must work without the model.
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: None,
ce_score: None,
}
}
/// Default-build (feature-OFF) contract: `rerank_depth > 0` with model absent
/// must soft-fallback to identity. This test is gated to the **default build
/// only** — when `default-reranker` is on, the real model is loaded so the
/// output is reranked (not identity), and the feature-on contract is covered
/// by `pr_g10_reranker_ce`. Cfg-gate added in fix-1 to fix the feature-on
/// test regression (codex §9 [P2]).
#[cfg(not(feature = "default-reranker"))]
#[test]
fn rerank_fused_depth_gt0_soft_fallbacks_in_default_build() {
let hits = vec![hit(1, "a", 0.05), hit(2, "b", 0.04)];
let out = rerank_fused("query", hits.clone(), 5, 0.3, 5);
// In the default build, depth>0 but model absent → soft-fallback (identity).
assert_eq!(out, hits, "depth>0 without model must soft-fallback to identity");
}
/// Soft-fallback: `rerank_depth=0` must return hits in exactly the same order
/// with the same scores — byte-identical to the pre-Slice-10 identity stub.
#[test]
fn rerank_fused_soft_fallback_preserves_fused_order() {
let hits = vec![hit(1, "alpha", 0.05), hit(2, "beta", 0.04), hit(3, "gamma", 0.03)];
let out = rerank_fused("what is the meaning of life", hits.clone(), 0, 0.3, 0);
assert_eq!(out, hits, "rerank_depth=0 must return hits unchanged (byte-identical)");
}
/// Determinism: two consecutive `rerank_fused` calls with the same inputs must
/// produce byte-identical output. In the default build this is trivially true
/// (identity), but the invariant is pinned here so any future CE path must also
/// satisfy it.
///
/// Note: when `default-reranker` feature is enabled and the model is loaded,
/// determinism is guaranteed by fixed model weights + deterministic tokenization
/// (see design memo Decision 8). This test verifies the soft-fallback path.
#[test]
fn rerank_fused_deterministic() {
let hits = vec![
hit(10, "document one", 0.033_333),
hit(20, "document two", 0.025_000),
hit(30, "document three", 0.016_667),
];
let first = rerank_fused("document query", hits.clone(), 0, 0.3, 0);
let second = rerank_fused("document query", hits.clone(), 0, 0.3, 0);
assert_eq!(first, second, "repeated rerank_fused calls must be byte-identical");
}
/// `rerank_depth=0` under the new signature is byte-identical to the old
/// identity-stub behavior. This replaces `rerank_fused_is_identity_stub` in
/// `pr_g9_rrf_fusion.rs` as the canonical expression of the soft-fallback
/// contract under the new 3-argument signature.
///
/// The corresponding test in `pr_g9_rrf_fusion.rs` has been adapted to use
/// `depth=0` (RED-3). Both tests pin the same invariant from different test files.
#[test]
fn rerank_depth_0_is_byte_identical_to_identity_stub() {
// Mirror of the old `rerank_fused_is_identity_stub` exact input.
let hits = vec![
SearchHit {
id: IdSpace::content("1"),
write_cursor: 1,
kind: "doc".to_string(),
body: "a".to_string(),
score: 0.0,
branch: SoftFallbackBranch::Vector,
source_id: None,
ce_score: None,
},
SearchHit {
id: IdSpace::content("2"),
write_cursor: 2,
kind: "doc".to_string(),
body: "b".to_string(),
score: 0.0,
branch: SoftFallbackBranch::Text,
source_id: None,
ce_score: None,
},
];
let out = rerank_fused("", hits.clone(), 0, 0.3, 0);
assert_eq!(out, hits, "depth=0 returns input unchanged — identical to old identity stub");
}
/// Factoid no-regress gate: the CDF artifact must contain an entry for
/// `arm=rrf_fused, query_class=exact_fact, k=200` with `found_at_k >= 0.9695`.
///
/// This is a **schema/artifact-existence gate**, not a live corpus run. The live
/// factoid R@10 >= 0.90 measurement is report-only (AGENT_LONG-gated via the
/// `ir_c_cdf_run.rs` harness). This test pins the Slice 5 CDF artifact so a
/// regression is detectable at the structural level in every push.
///
/// The pin value 0.9695 is the oracle pool measured at K=200 for `rrf_fused`
/// (`IR-C-recall-cdf.json`, generated 2026-06-13).
#[test]
fn reranker_recall_gate_schema_pinned() {
// CARGO_MANIFEST_DIR = src/rust/crates/fathomdb-engine → 4 levels up = workspace root.
let artifact_path =
concat!(env!("CARGO_MANIFEST_DIR"), "/../../../../dev/plans/runs/IR-C-recall-cdf.json");
let content = std::fs::read_to_string(artifact_path)
.unwrap_or_else(|e| panic!("CDF artifact not found at {artifact_path}: {e}"));
let json: serde_json::Value =
serde_json::from_str(&content).expect("CDF artifact is not valid JSON");
let recall_cdf = json
.get("recall_cdf")
.and_then(|v| v.as_array())
.expect("CDF artifact must have a 'recall_cdf' array");
// Find the rrf_fused / exact_fact / k=200 entry.
let entry = recall_cdf.iter().find(|e| {
e.get("arm").and_then(|v| v.as_str()) == Some("rrf_fused")
&& e.get("query_class").and_then(|v| v.as_str()) == Some("exact_fact")
&& e.get("k").and_then(|v| v.as_u64()) == Some(200)
});
let entry = entry
.expect("CDF artifact must contain entry: arm=rrf_fused, query_class=exact_fact, k=200");
let found_at_k = entry
.get("found_at_k")
.and_then(|v| v.as_f64())
.expect("CDF entry must have numeric 'found_at_k'");
assert!(
found_at_k >= 0.9695,
"rrf_fused exact_fact found@200 must be >= 0.9695 (oracle pool gate); got {found_at_k}"
);
}