Skip to main content

hitgate

eval-gate (advisory) Python 3.10+ License: MIT

Evaluate your RAG retrieval without labeled datasets — a regression-gated quality harness for retrieval ranking, built around a small hybrid retriever. Measure whether a change helps or hurts when you have no labels, no users to A/B against, and no budget for manual annotation.

The Problem

Building RAG systems is straightforward. Knowing whether a change made retrieval better or worse is hard — especially with a small corpus and no production telemetry. You can't A/B test with one user. You can't afford hand-labeled golden sets. LLM judges are expensive and opaque.

hitgate solves one specific problem: detect retrieval regressions label-free. Like a test suite for ranking quality.

What hitgate Does (and Doesn't)

✓ Proves whether retrieval improved or regressed between two runs (regression detection)
✓ Works with zero labeled data — no golden sets required to start
✓ Gates on measurable deltas — reports Hit@K, MRR, per-intent breakdown
✓ Plugs into your retriever — point --retriever at any callable (query, top, scope) → [results]

✗ Does not measure absolute quality — Hit@5=1.0 on a self-indexed corpus is optimistic by design
✗ Not a framework or hosted service — a harness you fork and customize
✗ Not a maintained product — personal tooling shared for the methodology

Comparison to RAGAS / DeepEval / Braintrust: Those tools gate answer quality (faithfulness, relevancy) via labeled golden sets or LLM judges. hitgate gates retrieval ranking label-free. Different layer, complementary — and the only one that requires zero labels to start. Full comparison: docs/COMPARISONS.md.


Quick Start (10 seconds)

pip install -e ".[hybrid]"   # harness + bundled hybrid retriever

# Index a repo and run the eval gate
RAG_SOURCE_ROOTS="$PWD" python -m ragcore.build
RAG_RERANK_AUTO=off python -m hitgate.run --label demo

# ...or point the gate at YOUR retriever
python -m hitgate.run --retriever myretriever:retrieve --label mine

What you get: Hit@5, Hit@1, MRR + per-case breakdown showing which queries failed and why.


CLI Commands

After pip install hitgate, the following commands are available on $PATH. Each also works as python -m <module> (e.g. python -m hitgate.run --label demo).

Indexing

rag-build — Build a searchable index from source code and docs.

RAG_SOURCE_ROOTS="/path/to/corpus" rag-build
  • --incremental FILES — Reindex only specific files (e.g. --incremental src/core.py docs/api.md)
  • --no-code — Skip source code; index docs only

rag-query QUERY — Search the indexed corpus.

rag-query "how does pagination work" --top 5 --format json
  • --top K (default 5) — Return top K results
  • --scope TYPE — Filter by source type (e.g. --scope code or --scope docs)
  • --rerank {on|off|auto} (default auto) — Cross-encoder reranking
  • --format {text|json} — Output format

Eval Gate

hitgate-run — Run the gate on a golden set and measure Hit@K, MRR.

hitgate-run --dataset eval/golden.jsonl --label baseline
  • --top K (default 5) — Measure up to top K
  • --label NAME (default baseline) — Label for output file
  • --dataset PATH — Golden set (JSONL)
  • --retriever MODULE:FUNC — Custom retriever (omit to use bundled hybrid)
  • --rerank — Force cross-encoder reranking (bundled retriever only)
  • --auto-rerank — Auto-trigger reranking on weak/ambiguous queries
  • --verbose — Show per-case details

hitgate-init [ROOT] — Scaffold a label-free golden set from a corpus.

hitgate-init /path/to/corpus --output eval/golden.jsonl
  • --output PATH (default eval/golden.jsonl) — Where to write the golden set
  • --min-confidence {high|medium|low} (default medium) — Heuristic confidence threshold
  • --limit N (default 0, unlimited) — Cap number of candidate cases

hitgate-demo [ROOT] — One-shot demo: build index, mine cases, run gate, print verdict.

hitgate-demo /path/to/corpus --limit 12
  • --limit N (default 12) — Number of golden cases to mine

Analysis

hitgate-generate — Mine candidate golden cases from a corpus (auto-generated, needs curation).

hitgate-generate --output candidates.jsonl --min-confidence medium
  • --output PATH (default hitgate/candidates.jsonl) — Where to write candidates
  • --existing JSONL — Skip files already in an existing golden set
  • --min-confidence {high|medium|low} (default medium) — Confidence threshold
  • --llm — Use an LLM to paraphrase queries (requires OPENAI_API_KEY)
  • --limit N — Cap total output cases

hitgate-diff BASELINE.json HEAD.json — Diff two eval result JSON files case-by-case.

hitgate-diff eval/baseline.json eval/ci.json
  • --quiet — Summary line only, no per-case detail

hitgate-audit-contamination — Check golden set for data leakage (eval queries appear in corpus).

hitgate-audit-contamination --dataset eval/golden.jsonl
  • --dataset PATH (default eval/golden.jsonl) — Golden set to audit

How It Works

Hybrid Retrieval

  • Dense embeddings (intfloat/multilingual-e5-small) + BM25 lexical search
  • Reciprocal Rank Fusion to combine both signals
  • Code-aware tokenizer — splits camelCase/snake_case so "get user profile" matches getUserProfile
  • Language-aware chunking — Python via AST, TS/JS/Shell via regex, fallback to word count
  • Optional reranking — cross-encoder scoped to code queries only, graceful fallback if unavailable

The Eval Gate

  1. Run your retriever against a golden set of queries (you write 20–99 JSON cases; this demo scores 99)
  2. Measure Hit@1/3/5, MRR — does the expected file rank in top K?
  3. Freeze a baseline when you like the results
  4. Gate future changes — CI exits 1 if any metric regresses by >5pp

Config via env var (RAG_*); see ragcore/config.py.


Metrics Explained

Metric Meaning
Hit@K % of queries where the expected file appears in top K results
Hit@5 Regression-gated headline metric (allows room for ranking imprecision)
Hit@1 Perfect-ranking metric (strict but useful for identifying misses)
MRR Mean Reciprocal Rank — average of 1/rank across queries

Self-indexed results are optimistic by construction — point the gate at your own retriever for numbers that mean something.


Bring Your Own Retriever — 4-Step Quickstart

A retriever is any callable:

retrieve(query: str, top: int, scope: str | None) -> Sequence[Mapping]
# Results ranked best-first; each a Mapping with at least "path" (optionally "start_line")

0. Bootstrap candidate golden cases (optional)

RAG_SOURCE_ROOTS="/path/to/corpus" python -m hitgate.generate \
    --output hitgate/candidates.jsonl \
    --min-confidence medium

Review and curate to remove vague queries or wrong expected paths.

1. Write golden cases

{"query": "how does pagination work", "expect_path_contains": "api/pagination.py", "expect_scope": "code"}
{"query": "rate limit config", "expect_path_contains": "config/limits.yaml", "expect_scope": "code"}

Aim for 20–50 cases mixing identifier lookups and paraphrased queries. Save as any .jsonl.

2. Run your retriever

python -m hitgate.run \
    --retriever mypkg.myretriever:retrieve \
    --dataset   my_golden.jsonl \
    --label     baseline-v1

Outputs hitgate/baseline-v1.json with Hit@1/3/5/MRR + per-case breakdown.

3. Freeze the baseline

cp hitgate/baseline-v1.json hitgate/baseline.myproject.json

Edit _note to record conditions: corpus, model, date.

4. Gate future runs

BASELINE_FILE=hitgate/baseline.myproject.json \
python -m hitgate.run --retriever mypkg.myretriever:retrieve --dataset my_golden.jsonl --label ci

bash hitgate/check.sh hitgate/ci.json hitgate/baseline.myproject.json
# Exits 1 if any metric regresses >5pp

Drop-in CI: examples/retrieval-gate.yml

Diff two runs case-by-case

python -m hitgate.diff hitgate/baseline-v1.json hitgate/ci.json

Architecture & Performance

Self-Indexed Demo (Reproducible)

Metric Value
Hit@5 (code scope, pure hybrid) 0.99
Hit@1 0.636
MRR 0.784
Corpus this repo, self-indexed · 99 cases

63 of 99 hit at rank 1; misses kept on purpose (no quiet dropping). Why Hit@5 is the gate: as the corpus grows, borderline cases drift rank. Hit@5 tolerates that noise; Hit@1 is for strict ranking. See CONTEXT.md (search "Drift over self-indexed corpus") for the fuller drift/self-indexed discussion.

External Corpus Benchmarks (Zero Tuning)

Corpus Language n Hit@5 Hit@1 MRR
FastAPI v0.115 Python 25 1.0 0.64 0.79
forge-space / mcp-gateway TypeScript 20 1.0 0.70 0.821
portfolio / src React/TS 15 1.0 0.60 0.778
ai-dev-toolkit / packages/core Python + TS 20 1.0 0.85 0.925
homelab / homelab_manager Python 20 0.950 0.85 0.900
Lucky / packages/backend TypeScript 21 0.905 0.71 0.810
Criativaria / web-app Next.js/TS 27 0.741 0.59 0.660

Finding: corpus module clarity predicts Hit@1 better than language or size. Clean functional boundaries → 0.85. Same-layer UI components → 0.59. Same tokenizer, zero corpus-specific tuning.

Selection bias: FastAPI is third-party; six of seven are the author's own repos. See docs/SWEEP.md for a broader 63-repo sample.

Full methodology and miss taxonomy: docs/METHODOLOGY.md


Use Cases

AI Assistant Memory

Gate retrieval quality in RAG-backed chatbots or assistants. Detect when corpus updates or embedding model swaps regress search. Deployed version of this exact use case: docs/two-channel-fastapi.md (auto-mined Hit@5=1.0 vs hand-labeled=0.92).

Want the retrieval engine + MCP server + agent-recall hooks, not just the eval gate? See shelfmark — same hybrid-retrieval lineage, packaged for agent memory instead of regression testing.

Keep search quality stable as your docs grow. No user click data? Gate on retrievability. Ecosystem wrappers for LangChain / LlamaIndex: hitgate/adapters/README.md.

Find code references and definitions. The hybrid retriever knows camelCase — useful for codebases with identifier-heavy queries. Same gate works for private codebases.


Extending

Core indexes code + docs + commits, nothing else. Tool-specific sources (assistant transcripts, code-graphs, other memory stores) plug in as optional adapters — hitgate/adapters/README.md.


What to Adopt (and What to Skip)

Adopt: The harness (hitgate/) — label-free regression gating and the --retriever interface. Plug in your own retriever.

Skip:

  • Not a framework or hosted service (no plugin marketplace, no SaaS)
  • Not state-of-the-art retrieval research (pragmatic, single-user, knows its ceiling)
  • Not a maintained product (solo operator's personal tool; best-effort, no SLA)

Deliberately omitted: CONTRIBUTING, issue templates, badge walls. DECISIONS.md records what's left out on purpose and when it might reopen.


Next Steps


License

MIT — see LICENSE.

Metadata

Release files for hitgate 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for hitgate 0.1.1
File Size Uploaded
hitgate-0.1.1.tar.gz 104.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for hitgate 0.1.1
File Interpreter ABI Platform
hitgate-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 180.6 kB

Release files / hitgate-0.1.1.tar.gz

Download URL hitgate-0.1.1.tar.gz
Size 104.7 kB
Tags Source
SHA-256 checksum
How to use checksums
bcee60f81a008d34d1d3c0f80f421d827f798248f678e0fae1db7ab0b81790a1
BLAKE2b-256 checksum
How to use checksums
185d3424fffb4854d6cb9f9e0e36947677f23abcfdd143d4fc187a0ccdb21678
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release files / hitgate-0.1.1-py3-none-any.whl

Download URL hitgate-0.1.1-py3-none-any.whl
Size 75.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5d9b763a128204e0857b41fb19824982d55fde3e76261ba070cb14835f163979
BLAKE2b-256 checksum
How to use checksums
08cd812d78f7521aaf881010333537970c72c150d5de9f954749fc0659b7afe3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page