Most retrieval evals are rerun because a query set changed, a ranker changed, or someone argues about a regression. In all three cases the corpus is the same as it was, yet the naive pipeline rebuilds it anyway: it re-crawls the source, re-splits documents into chunks, and re-embeds every chunk. That last step is the expensive one, and it is also the one that changes results without anyone intending it. Embedding models place the same text in a coordinate system fixed by the model, and vectors from two different models are incompatible, so a silent model swap does not just cost money, it invalidates every stored vector you already have the embedding model selection guide. If your eval pipeline re-embeds on every run, an accidental model change is invisible until scores move.
The design principle is borrowed from a different corner of engineering. Contract testing works because the interface is a machine-readable artifact that every commit must prove still holds, so a provider cannot silently rename a field and break a consumer the API contract testing guide. Your retrieval eval has the same shape: the golden query is the consumer, the chunk store is the provider, and the manifest is the contract between them. Freeze it, version it, and the rerun becomes a lookup.
There is a second reason to separate storage from computation. Retrieval metrics only mean something if the corpus behind the labeled passages is fixed. If the passage a judge labeled as required evidence has drifted, the metric measures your pipeline against a moving target the golden dataset guide. Storing the exact chunk text, not a pointer to it, is what makes a rerun reproducible months later.



