How search works

BM25, vector, default bounded graph expansion, fusion, and reranking, end to end.

GNO hybrid search runs BM25 and vector retrieval, fuses by rank, optionally expands one hop of wiki/markdown links, then cross-encoder-reranks. Exact identifiers and quoted phrases skip HyDE; --fast (~0.7s) returns fused BM25+vector, default (~2–3s) adds bounded graph expansion and rerank.

The pipeline

  1. Query expansion — optionally expand the query with HyDE (hypothetical document embeddings) and lexical variants. GNO skips expansion when it has a strong signal.
  2. BM25 retrieval — classical full-text search over the inverted index. Fast and precise for exact terms, technical identifiers, and quoted phrases.
  3. Vector retrieval — cosine similarity over dense embeddings. Handles synonyms and conceptual matches.
  4. Reciprocal rank fusion — merges BM25 and vector results by rank position, not raw score, so the two score scales never have to be comparable.
  5. Bounded graph expansion — by default, GNO resolves only outgoing wiki/markdown links and backlinks touching the top seeds, then adds those bounded one-hop neighbors after initial fusion. Active filters still apply, existing chunk positions are preserved, and explicit links are weighted above inferred or ambiguous matches. Semantic similarity remains in the vector stage; query-time graph expansion never rebuilds the full collection graph. --no-graphand --fast skip the stage.
  6. Second fusion pass — graph candidates join the BM25/vector ranked inputs before reranking, so linked evidence can boost the right chunk instead of duplicating a document-level hit.
  7. Cross-encoder reranking — rescores the fused top-N with a cross-encoder over query+document together. Cost shows up in the Thorough (~5s+) and default (~2–3s) modes, not --fast.
  8. Return — the reranked top-K is returned with scores, snippets, and optionally the retrieval pipeline trace.

Speed modes

gno query "topic" --fast
gno query "topic" # balanced
gno query "topic" --thorough
gno query "topic" --no-graph

Benchmark fixtures

For repeatable retrieval checks, create a fixture with queries and relevant document URIs, then run gno bench <fixture>. The command evaluates BM25, vector, and hybrid modes against the same corpus and prints metrics that make model or pipeline regressions visible before you switch defaults.

gno bench docs/examples/bench-fixture.json
gno bench fixture.json --modes bm25,vector,hybrid --json

The frozen Context Capsule agent-outcome demo runs one exact-identifier task through the lexical-only baseline, current GNO query/get primitives, and the Context Capsule using the same task, agent, corpus, effective index, trial, seed, and cold lifecycle. It publishes exact evidence, stop outcome, calls, context bytes, token availability, latency, method, variance, and the complete normalized receipts. Task t0a1b2c3 is the sole cold current-GNO-failure / Capsule-success case among the authoritative 24-task cohort. It was selected to demonstrate that behavioral difference, not as a representative sample or general superiority claim. The Capsule lane is an evaluation-only lexical prototype; its latency is not the shipped Context Capsule path and is not product-equivalent.

Capsule result: INC-4827 from gno://c001/d001.md:3 in 1 agent call and 1295 model-visible UTF-8 bytes. Tokens were unavailable without one pinned comparable tokenizer. The separately labeled 22-pair Verified Ask artifact is answer-enforcement evidence; its answer metrics are not retrieval metrics.

--explain

Pass --explain to Query or Ask to see exactly what happened: expansion output, BM25 hits, vector hits, graph expansion status, fusion order, rerank scores, and stage timings including graphMs. When a non-neutral content-type rule applies, the receipt also shows the raw/base score, configured factor, bounded contribution, shared auxiliary cap, final score, rule source, and full ranking-rules fingerprint. Explain metadata stays outside canonical Context Capsule bytes.

gno query "topic" --explain
gno ask "summarize the meeting" --verify --explain

Bounded auxiliary ranking

One configured contentTypes[].searchBoost can contribute -0.05..+0.05. Trusted local CLI project affinity can contribute up to +0.03. They compose once under a shared ±0.08 cap, and the final score remains in 0..1. BM25 and vector only adjust candidates that already survived retrieval and minScore; content-type boosts alone never widen either candidate set.

Hybrid applies the composed auxiliary score to normalized fusion before rerank blending. Rerank ordering and lexical top-hit protection remain the final authority; content-type preference cannot override either safeguard.

Boost factors accept 0.5..2; omitted or 1 is neutral. A canonical configured frontmatter type wins over longest-prefix matching. Categories, unknown type text, and overlapping prefixes cannot stack or manufacture a boost. The signal never creates a candidate and never bypasses collection, tag, date, category, author, or exclude filters.

Strong signal detection

When your query contains exact identifiers or quoted phrases, the pipeline recognizes the strong signal and skips expansion — no point hallucinating a HyDE document when the user already told you exactly what they want.

Multilingual scope and evidence

Query-language classification uses an explicit 34-language allowlist to choose prompt language. Indexed-document detection is a separate seven-language path covering en, de, fr, it, zh, ja, and ko. Neither count is a retrieval-quality guarantee.

The immutable April 6, 2026 FastAPI-docs fixture used 15 documents in five corpus languages and 13 queries. It measured bge-m3 at vector nDCG@10 0.3503 and hybrid 0.642 in the bge-m3 evidence, versus Qwen3 Embedding 0.6B at vector 0.8594 and hybrid 0.947 in the Qwen evidence.

A separate July 21, 2026 screen reran the same 13-query lane after runtime/profile changes: Qwen measured 0.9891 vector / 0.9891 hybrid, and Nemotron 3 Embed 1B measured 0.9023 / 0.9461. Nemotron used a temporary PyTorch HTTP adapter while Qwen used GNO’s production GGUF path, so timings are not comparable and no official production Nemotron GGUF was validated. These small fixtures support keeping Qwen as the default; they do not prove general language superiority.

Degraded lexical behavior has separate evidence. The immutable July 22, 2026 CJK benchmark used 25 same-language queries across Chinese, Japanese, and Korean. The Chinese lane includes a genuine rank-7 retrieval fixture. Production BM25 Recall@10/nDCG@10 and zero-result results, followed by the frozen promotion floors:

The frozen promotion gates also bind MRR, non-regression, and cost requirements. This lexical baseline is not semantic evidence and does not select a future analyzer. All positive qrels use relevance 3, so nDCG measures placement but not distinctions among positive gain grades. Production tokenization remains unchanged.