Hit the recall target
# grade this stage (from your course directory)
npx theinference test --stage recall-eval --watchThe green metric line. Run knnSearch over every query at efSearch = 64, compute mean recall@10 against the brute-force ground truth, and report the mean L2 comparisons per query. Both numbers must match the frozen reference.
What to build
Print recall + comparisons
Wire the recall subcommand in src/cli.ts. For each query: compute brute-force top-10 (ground truth), reset the comparison counter, run search, accumulate the counter. Print:
{ "recall": <mean recall@10>, "meanComparisons": <mean per query> }
./your_program.sh recall <fixture>/chapters/05-knn-search/steps/03-recall-sift10k/fixtures/data.json
Process mode: stdout_json_match against the frozen reference { recall, meanComparisons }. The "recall ≥ 0.95 under a budget" framing is the idea; the actual grade is an exact match to the reference value (atol 1e-6 on recall, integer-exact on comparisons). Because your graph and search are deterministic, your recall and comparison count equal the reference's — and a brute-force solution's meanComparisons (= N) can never match the frozen budget.
If comparisons are too high, your upper-layer descent is probably using efSearch instead of ef = 1, or you are re-scanning visited nodes. If recall is off, suspect the heuristic (Chapter 3) or the build (Chapter 4) — search can only be as good as the graph it is given.