Add corrective-retrieval signal to search responses#36
Conversation
Add a sys.path bootstrap to the repo root before importing main.utils.frontmatter, mirroring the pattern already used in cross_collection_gap_analysis.py. Commit a90d124 switched this script to import from the main package, but the daily Jira update runs it as `uv run scripts/knowledge_graph/extract_jira_graph.py`, which puts the script's directory on sys.path rather than the repo root. That made `import main` fail with ModuleNotFoundError and silently skipped the Jira graph re-extraction step in the daily job.
Search responses (HTTP /api/search, the MCP search tools, and the HTTP MCP adapter) now carry the signal a client needs to decide whether to re-query: a response-level bestScore, a per-result confidenceBand (high/medium/low; rank-based brief-mode results are capped at medium), a retryHints object (detectedEntities, graph-neighbour relatedTerms, narrowerQuery, a heuristic broaderQuery), and noConfidentResults. A new min_relevance param drops weak results and, when it empties the set, returns retryHints + noConfidentResults instead of low-quality filler. The search trace gains an additive "response" block recording the same decisions. Defaults are unchanged, so existing callers are unaffected. This is Phase 0 of the corrective-retrieval / query-decomposition work (see mimir/plans/huginn-muninn-corrective-rag.md). Huginn stays a pure retriever; the agentic corrective loop lives in Muninn, which will consume this contract — but it needs Huginn to expose a cheap, no-LLM quality signal first. confidenceBand thresholds are tied to the searcher's existing LOW_CONFIDENCE_THRESHOLD so "low" means the reranker's own noise zone. - confidence_band() in search_response_formatter; shape_search_results tags every result - GraphSearchAugmenter.get_retry_hints() + _broaden_query() (works with no graph) - SearchTrace.set_response_meta(); optional "response" key, no schema bump - min_relevance threaded through build_search_tool_fn and the HTTP adapter's 4 signature variants - 22 new tests; full suite (636) green; live-checked against a wiki-collection server
Smoke test — green ✅Server PID 1862 started 20:16, after commit Direct
HTTP MCP adapter ( Caveat (known, documented in plan): brief mode skips the reranker, so Bot leg skipped: hivemind isn't active in this session, so no muninn peer to drive a bot search + read the muninn-db trace. Change is purely additive (new response keys, default-off param) and the two layers below the bot are verified above; the 22 new unit tests + full suite (636) are green. |
Search responses now carry the signal a client needs to decide whether to re-query: a response-level
bestScore, a per-resultconfidenceBand, aretryHintsobject,noConfidentResults, and a newmin_relevancefilter param. Defaults are unchanged — existing callers are unaffected.This is Phase 0 of the corrective-retrieval / query-decomposition work tracked in
mimir/plans/huginn-muninn-corrective-rag.md. Huginn stays a pure retriever; the agentic corrective loop (CRAG-style grade-and-requery) and query decomposition live in Muninn — but Muninn needs Huginn to expose a cheap, no-LLM quality signal first.confidenceBandthresholds are tied to the searcher's existingLOW_CONFIDENCE_THRESHOLD, so alowband is the reranker's own noise zone; rank-based brief-mode results are capped atmedium(never claimhigh).confidence_band()+confidenceBandon every shaped result;bestScoreon the response (taken before any filter, so callers can tell "found something below your bar" from "found nothing")GraphSearchAugmenter.get_retry_hints()→detectedEntities/ graph-neighbourrelatedTerms/narrowerQuery/ heuristicbroaderQuery(the broadening works with no graph); emitted when results are empty orbestScoreis weakmin_relevanceparam on/api/search,build_search_tool_fn, and the HTTP MCP adapter (all signature variants) — drops weak results; when it empties the set, returnsretryHints+noConfidentResultsinstead of low-quality fillerSearchTrace.set_response_meta()— additive optionalresponseblock (no schema bump); HTTP MCP adapter renders(NN% relevant · band)+ a compact retry-hint footerTesting
confidence_bandboundaries,shape_search_resultsband tagging,_broaden_queryheuristics,get_retry_hintswith/without graph,mcp_search_toolcorrective signal incl. trace block); full suite 636 passing/api/searchagainst awiki-collection server:min_relevance=0.99→{"results":[],"bestScore":0.75,"noConfidentResults":true,"retryHints":{...}}; normal queries unchanged (confidenceBand+graph_contextpresent)huginn-pr-smoke-testafter restarting it on this code)Notes
main, which was one commit ahead oforigin/main— so this PR also carries the pre-existing7f71a22 Fix extract_jira_graph import when run as a script.retryHints.suggestedCollections(needs entity→collection attribution at graph-load), areranked: falseresponse flag (so callers knowbestScoreis rank-based in brief mode), and wiringmin_relevanceinto the stdio MCP tool args.