Changelog¶
Entries are tagged by component: [engine] for the Python package under
engine/, [plugin] for Claude Code plugin primitives (skills, agents,
commands, manifests), [docs] for documentation-only changes. The plugin
and the engine are versioned in lockstep — a single version number covers
both.
0.7.0 — 2026-07-27¶
- [engine]
vendor/added toDEFAULT_EXCLUDE_DIRSinproject_loader, so vendored third-party code is skipped during file discovery likenode_modulesandvenvalready are. - [engine] Pluggable tokenizer modes (
plain/code) onTfidfIndexandBM25Index."code"mode emits each whole token's lowercased subtokens (split on_/-/.and camelCase/PascalCase boundaries) after the whole token, so identifier-heavy corpora can match on subtoken vocabulary (e.g.getUserById→user/by/id) without losing exact-identifier matches."plain"stays byte-identical to the prior tokenizer. The mode is persisted into_dict/from_dictand never re-derived at query time. - [engine] Breaking: cache schema bump (v2 -> v3) for
LexicalRetrieverandHybridRetriever. Tier-A hyperparameters (bm25_k1/bm25_b/tokenizer/model_name/bit_width/lucene_k1/lucene_band a chunk-size policy) are now threaded from CLI flags (or auto-derived corpus signals) through to their consumers and recorded in each cache'smeta, so query time never re-derives them; a v2 on-disk cache for either retriever is treated as unrecognized and auto-rebuilt on the nextindex/query— no manual cache-clearing needed. Newbuild_retriever/resolve_ctor_kwargsmap a filteredparamsdict onto each retriever's declaredACCEPTSset. Newretrieval.autotunemodule (stdlib-only) collects corpus signals and resolves the full hyperparameter dict viaresolve_params(), with a static-default fallback on an empty corpus. Newretrieval tunesubcommand reports auto-derived params without writing anything;index/querygain--autoplus per-hyperparameter flags (--bm25-k1,--tokenizer,--bit-width, etc.),query's--top-kdefault becomesNone(explicit > auto-resolved >5),evalgains--autoand recordsauto_params, andstatsechoeshyperparams/corpus_statswhen present. Hyperparameters recorded this way are now preserved across both query-triggered and index-triggered cache rebuilds (a barequeryor bareindex/index --forcewith no explicit flags no longer silently reverts a cache's recordedbm25_k1,tokenizer, etc. to static defaults) — an explicit flag value still takes precedence and overwrites the recovered value, and a from-scratch index with no priormetais unaffected. - [engine] [docs] Hyperparameter decisions delegated to the invoking
agent.
resolve_paramsnow also decides the turbovec/hybrid embedding model from corpus content and size (_decide_embed_model): code-dominated corpora (>0.6 code bytes) get a code-search-trained embedder, small corpora (≤2000 chunks) get the higher-qualitympnet, large corpora get the fastMiniLM, and an empty corpus degrades to theMiniLMstatic default;bit_widthis now sized from the chosen (or overridden) model's embedding dimensionality instead of a hardcoded 384.skills/retrieval/SKILL.mdStep 2 and the command dispatcher (commands/retrieval.md) now instruct the agent to decide hyperparameters inline at index/query time —indexwith--autoas the corpus- calibrated baseline plus per-flag explicit overrides,querywith--auto,top-k,--weights, and--pool— including a decision table mapping corpus/query observations to concrete flags and the persistence semantics (decide once, survives rebuilds, changed values trigger a selective rebuild). - [engine]
retrieval.__version__realigned withpyproject.toml(both0.6.0); a new regression test parsespyproject.toml's version field by regex and asserts it matchesretrieval.__version__so this can't silently drift again. This explains why on-disk caches built during the 0.6.0 development window may show differingengine_versionvalues in theirmeta.jsondepending on exactly which commit produced them. - [docs] Docs-only disambiguation. The README, docs home, per-retriever
how-to, troubleshooting table, the
lucene-retrieval-usageskill, and thePiSeriniRetrieverdocstring now state explicitly thatpi-serini(the strategy/registry key from the Pi-Serini paper) andpyserini(the Castorini library and install extra) are distinct names, not a typo for each other. No identifier, CLI flag, registry key, cache filename, class name, or extra name changed. - [docs] Pi-Serini method explainer.
docs/concepts/retrieval-strategies.mdgains a "The pi-serini method" section with the full paper citation (Hsu, Yang, Lin — Rethinking Agentic Search with Pi-Serini: Is Lexical Retrieval Sufficient?, arXiv:2605.10848): the retrieve-deeper thesis, BrowseComp-Plus results, and thek1=25, b=1tuning rationale.
0.6.0 — 2026-07-25¶
- [plugin] New default deep-answer workflow (Q/R/T/C/S). The
retrievalskill's Step 3 now runs a phased Decompose → Retrieve-per-sub-question → Trace → Coverage-gate → Synthesize loop by default for explanatory/ comprehensiveness questions (with a shallow triage fast-path for bare locate-a-symbol asks), replacing the previous four-step loop with an explicit coverage checklist that must be satisfied before answering. New optionalretrieval-traceragent (agents/retrieval-tracer.md) for fanning out Phase T across sub-aspects on broad questions (≥4 independent sub-aspects), returning detailedfile:linetraces to be stitched together by the caller.docs/how-to/consolidated-query.mdanddocs/how-to/integrate-coding-agents.mddocument the workflow's use of the--outputJSON envelope as the per-sub-question seed carrier, including a non-Claude-agent variant using only the CLI. No CLI output, JSON envelope, or engine logic changed — this is entirely plugin-primitive (skill/agent/doc) guidance.--queries-file/--path-prefixengine flags were considered to support this workflow natively but deferred; the workflow is achievable today with per-sub-questionquery --outputcalls. - [docs] Docs/guidance-only clarification. The
retrievalskill, the five per-method usage skills, and theretrieval.consolidationdocstrings/docs now spell out that the consolidated list is scaffolding for exploration (not a finished answer to hand the user directly), and thatscore/agreement/confidencemeasure cross-retriever agreement on query-text match — not that a span is current, canonical, or non-deprecated. No CLI output, JSON envelope, or engine logic changed.
0.5.0 — 2026-07-24¶
- [engine] Breaking: the default persisted index cache moved from
~/.cache/agentic-retrieval/indexes/<project-key>to<project-root>/.agentic-retrieval, resolved from the indexed root's absolute path so it follows the project regardless of where it's checked out. Existing caches under the old home-directory location are abandoned (not migrated) and lazily rebuilt at the new location on the nextindex/query. TheRETRIEVAL_INDEX_DIRenvironment variable now instead selects a shared base directory (keyed byproject_key(root)) rather than being the default location itself; its shared-base + project-key layout is otherwise unchanged. The new.agentic-retrievalcache dirname is excluded from file discovery by default (preventing a self-indexing feedback loop) and added to.gitignoreso index blobs are never committed.
0.4.0 — 2026-07-24¶
- [engine] Breaking: the distribution package was renamed from
rag-retrievaltoagentic-retrieval(therag-retrievalname was already taken on PyPI). The importable module (retrieval) and theretrievalconsole script are unchanged; only the distribution name, its self-referencingallextra, the release workflow's PyPI URL, and install instructions moved toagentic-retrieval. Any install command referencing the oldrag-retrievaldistribution name (e.g.uv pip install rag-retrieval,uvx --from rag-retrieval, or arag-retrieval[all] @ git+...requirement) must be updated toagentic-retrieval. - [engine] [docs] New
retrieval evalsubcommand runs a labeled query set against every retriever plus consolidated fusion, reporting recall@k, nDCG@k, confidence-bucket precision (agreement-signal validity), and cold/warm search latency; entirely in-memory (no on-disk cache writes). Missing extras are skipped gracefully, mirroring the consolidated query path. Ships an in-repo fixture corpus with 10 hand-labeled queries and extras-free tests, plus a new how-to guide (docs/how-to/evaluate-retrievers.md).skills/retrieval/SKILL.mdnow states what single-retriever mode trades away (the cross-retriever agreement/confidence signal) so agents can choose the opt-out deliberately; the consolidated default is unchanged.
0.3.0¶
- [engine] Breaking:
retrieval querydefault is now consolidated (all-retriever) mode. With no--retrieverflag (or the new explicit--retriever allalias),queryloads every available strategy in_DEFAULT_INDEX_SET, searches each, and merges/fuses them into a single deduplicated, ranked, explainable list via the newretrieval.consolidation.consolidate— same-file overlapping/adjacent spans across retrievers merge into one candidate, and each result carriesscore/provenance/agreement/confidence/contributors. A missing backend is skipped (never a hard failure) as long aslexicalconsolidates successfully. New consolidated- mode-only flags:--weights "name:w,..."(per-retriever RRF weight override) and--output PATH(also persist the JSON envelope to disk).--retriever <name>(single strategy) is unaffected — its plain-text and--jsonoutput stay byte-identical to before this change. See Consolidated query. - [engine] Weighted Reciprocal Rank Fusion.
retrieval.fusion.reciprocal_rank_fusiongained a trailingweights: Optional[List[float]] = Noneparameter;None(the default) weights every ranking1.0, numerically identical to the previous unweighted behavior, so every existing caller is unaffected. - [engine] New
retrieval.consolidationmodule.ConsolidatedHitdataclass +consolidate(per_retriever_hits, *, k=60, weights=None, merge_adjacent=True) -> List[ConsolidatedHit]: groups same-file overlapping/adjacentSearchHitspans across retrievers into one candidate, fuses each group's per-retriever ranks with weighted RRF, and returns a list sorted best-first, each hit carryingprovenance(which retrievers found it),agreement(how many), and aconfidencelabel (highifagreement >= 2; elsemediumif the sole contributing arm is a dense/Lucene arm —turbovec/pi-serini; elselow). - [engine] Tree-sitter (AST-boundary chunking) retrieval strategy. New
retrieval.ast_chunkermodule implements cAST-style (arXiv 2506.15655) split-then-merge chunking at AST node boundaries, viatree-sitter-language-pack(newtreesitterextra). Every chunk carries a dottedcontextbreadcrumb (enclosing function/class path, e.g."Bar.baz").retrieval.project_loader.load_ast_chunk_documentsis the AST-boundary analog ofload_chunk_documents, falling back to the line-based chunker per file when a suffix's language is unmapped or a file's AST chunking comes back empty. NewTreeSitterRetriever(REGISTRY keytreesitter) subclassesLexicalRetriever, ranking with the same TF-IDF + BM25 + RRF over AST chunks with the breadcrumb prefixed into the ranked text — the retriever class itself needs no optional dependency, only the loader does.DocumentandSearchHitgained an optional, trailing-defaultcontext: str = ""field. - [engine]
site/excluded from indexing by default.site(MkDocs/static-site build output) joinedDEFAULT_EXCLUDE_DIRSinretrieval.project_loader, so generated site assets no longer pollute the index. On-disk caches built before this change will read as stale on the nextquery(the content fingerprint now differs) and auto-rebuild — no manual cache-clearing. Override with theexclude_dirs=keyword if your project keeps real source undersite/. - [plugin] Skill guidance: post-retrieval enrichment loop. The
retrievalskill gained a Step 3 framing retrieved spans as exploration seeds (read the span, follow references outward, re-query with the vocabulary a hit reveals, stop when the question is answered) plus a noisy/low-relevance recovery subsection. The four*-retrieval-usageskills and the integrate-coding- agents how-to mirror the same "seed, not final answer" framing; the earlier "no manual grepping needed" / "no re-grepping" stop-signal phrasing was removed. - [engine] Chunk-level indexing with file:line spans. All five production
retrievers now index chunk-granularity
Documents (retrieval.project_loader.load_chunk_documents) instead of whole files:docidis"{path}:{start}-{end}", and eachDocumentcarriessource_path/start_line/end_linespan metadata. Every retriever gainedsearch_detailed(query, top_k) -> List[SearchHit], resolving each result's span from that metadata (never by parsing the docid string).search()is now a thin[h.docid for h in search_detailed(...)]projection, kept for backward compatibility. - [engine] Chunker line-span tracking.
retrieval.chunker.Chunkgainedstart_line/end_line(1-based, inclusive);chunk_documenttracks source line numbers for every paragraph and extends a chunk's span to include the heading line that introduced it. - [engine] Breaking:
retrieval query --jsonoutput shape.resultswas a flat list of docid strings; it is now a list of objects ({"docid", "path", "start_line", "end_line", "rank"}). Plain-textqueryoutput changed from one docid per line to onepath:start_line-end_linespan per line. - [engine] Cache schema bump (v1 -> v2). Every retriever's
SCHEMA_VERSIONbumped to persist the new chunk-spanunits; a v1 on-disk cache is treated as unrecognized and auto-rebuilt on the nextindex/query— no manual cache-clearing needed. - [engine]
retrieval indexprints<name>: indexed <N> chunks(was... docs);retrieval statsprints bothchunks:(chunk count) andfiles:(distinct source-file count) instead of a singledocs:line. The cache'smeta.jsongained afile_countfield alongside the existing (now chunk-counting)doc_count.
0.2.0¶
- [engine] Persistent, on-disk index cache (
retrieval.persistence) keyed by project path, with fingerprint-based staleness detection. - [engine] New
retrievalconsole-script CLI (index/query/stats), including--force,--stale-ok, and--json. - [engine]
uv-native setup — the engine's environment is managed entirely byuv sync/uv run; the deprecated no-uvfallback (scripts/setup_venv.py) has been removed. - [engine]
allextra — one-shot install of every optional retrieval extra (local,remote,turbovec,pyserini).
0.1.0¶
[engine] Initial vendored engine: LexicalRetriever (TF-IDF + BM25 + RRF),
TurbovecRetriever (dense ANN), PiSeriniRetriever (Lucene BM25), and the
heuristic/LLM contextualizers, with an in-memory-only engine API.
See GitHub Releases for the full release history and downloadable build artifacts.