# m12p1 — Read-recall harness: measurement truth (✅ COMPLETE 2026-06-14) Landed in `bb21e69`. Changelog: [CHANGELOG.md](../../../CHANGELOG.md). Milestone index: [README.md](README.md). Backfilled record. ## Why this came first G1 and G2 are numeric gates. Before m12p1 the project had no way to measure either: no pure ANN probe (every read path mixed profile scoring, fusion, and diversity into the result), and no ground truth to compare against. A gate you cannot measure is a gate you cannot pass — so the harness shipped before the tuning it exists to judge. ## What shipped 1. **A pure k-NN probe.** `TidalDb::vector_search_items(query, k, ef_search)` returns raw HNSW nearest neighbours over the item content embedding slot with **no** profile scoring, fusion, or diversity, so the result measures index quality in isolation — the G2 metric. Exposed as `POST /vector_search` on the standalone router and on the multi-process region node, which merges by distance across hosted shard groups. A dimension-mismatched query is a **400, not a 500**: caller error, not server fault. 2. **The oracle.** `tidal-stress --verify-recall` (`tidal-stress/src/recall.rs`) seeds the corpus with deterministic, id-keyed embeddings (reproducible with `--skip-seed`), holds a brute-force cosine ground truth in RAM, and ramps `/vector_search` probes **open-loop** with coordinated-omission correction. 3. **A verdict, not a number dump.** It reports per-stage **true p99** and mean recall@k, plus the **read-knee** — the highest sustained QPS at which `p99 ≤ target AND recall@k ≥ target` both hold — with a machine-readable JSON summary (`tidal-stress/src/summary.rs`) and a `--fail-on-knee` PASS/FAIL exit code. Knobs: `--recall-k`, `--recall-queries`, `--read-p99-target-ms`, `--recall-target`, `--recall-ef-search`. 4. **Repaired fabricated numbers.** The p99 column in `docs/profiling/social-scale.md` was mean-as-p99 (the `social` bench is Criterion, which reports mean only). That column and the `scale.rs` / scale-baselines framing were corrected: every closed-loop number is now labelled an *isolated per-op mean (regression tripwire)*, and only the open-loop harness signs off p99/recall SLOs. ## Evidence - **recall@10 = 0.9997** at 20k items / 1536-D against a real standalone server (HNSW M=16 / ef=400 / F16 vs brute-force cosine) — far above the 0.95 G2 target. - `tidal/tests/m12p1_vector_recall.rs` (3), `tidal-server/tests/vector_search.rs` (8). - Harness section in [docs/profiling/scale-baselines.md](../../profiling/scale-baselines.md). - A 1536-D HNSW-vs-brute recall@10 bench added to `tidal/benches/vector.rs`. ## Carried constraint The brute-force oracle needs roughly 6 GB RAM at 1M vectors, which is why the 100k/1M exit-gate runs execute the same harness on the k3s cluster rather than a laptop.