code

fill kosha from a repo, grep the working tree, and federate all of it with the prose

kosha is the code half of the vault: AST chunks, symbol names, and a call graph with PageRank over your repo and your installed packages. It embeds code with a code-trained model, deliberately — identifiers are not sentences — so the two stores share no vector space, and federate fuses their rankings rather than their distances. rgapi adds a third kind of evidence for free: ripgrep over the files as they are on disk right now, which is the only leg that sees what nothing has indexed.


source

Vault.index_code

def index_code(
    dir:str=None, # repo to index
    graph:bool=True, # also build the AST call graph (callers, callees, PageRank)
    env:bool=False, # also index installed packages (slow the first time)
    force:bool=False, verbose:bool=False, **kw
)->dict: # forwarded to kosha update_repo/sync

Point the vault at a repo and fill kosha’s stores from it.

This is the code path proper — symbol search and call-graph navigation — as opposed to Vault.code(), which files source files into the vault as ordinary documents. Both can coexist, and federate() searches whichever exist.


source

Vault.kosha

def kosha(
    dir:str=None, # repo root; defaults to the cwd repo
    share_encoder:bool=False, # embed code with the vault's encoder instead of kosha's
    **kw
):

The Kosha for dir, cached on the vault so index_code and code_search hit one store.

share_encoder=True makes the two stores directly comparable at the cost of worse code ranking; it needs a real encoder, so it is a no-op on the hashing fallback.


source

Vault.grep

def grep(
    pattern:str, # a ripgrep regex
    dir:str='.', # tree to search
    limit:int=20, # matching lines returned
    **kw
)->L: # forwarded to rgapi.rg (glob=, ext=, context=, hidden=, ...)

Exact matches in the files on disk, through ripgrep.

The leg neither of the others can serve: embeddings generalise and FTS5 stems, so an identifier that appears verbatim in a file the vault never ingested — or ingested an older copy of — is invisible to both. .gitignore applies, so build output stays out of the results.


source

Vault.where_to_add

def where_to_add(
    description:str, limit:int=5, dir:str=None
)->L:

Where in the indexed repo a described change belongs — kosha ranking over the call graph.


source

Vault.symbol

def symbol(
    name:str, depth:int=1, dir:str=None
)->AttrDict:

A symbol in the call graph: its file, PageRank and degree, plus its callers and callees.


source

Vault.federate

def federate(
    q:str, # the query
    limit:int=12, # fused hits returned
    prose:bool=True, # the vault's own documents, papers, notes
    repo:bool=True, # kosha's repo index
    env:bool=False, # kosha's installed-package index
    grep:bool=True, # ripgrep over the working tree
    kind:str=None, # restrict the prose leg to some KINDS
    weights:dict=None, # per-leg RRF weights, e.g. {'prose':1.0,'repo':1.5}
    dir:str=None, # repo for the code and grep legs
    per_leg:int=None, # hits pulled from each leg before fusion
)->AttrDict:

One ranked answer across prose, indexed code and the files on disk, fused by RRF.

The legs share no vector space — the vault embeds prose, kosha embeds identifiers, ripgrep embeds nothing — so they cannot be merged by distance. Reciprocal Rank Fusion needs only each leg’s ordering, which is exactly what survives a change of encoder, and it is the same mechanism litesearch already uses to combine FTS with vectors. Each leg is tried independently: legs reports what each contributed, or why it did not.

Try it

Each leg is optional and each fails on its own: with no repo indexed, legs says so and the others still answer.

v = Vault(':memory:')
v.note('litesearch fuses the FTS and vector legs with reciprocal rank fusion.')
f = v.federate('rank fusion', repo=False, grep=False)
f.hits[0].where, f.legs, f.note
/Users/71293/code/personal/orgs/vishalakshi/.venv/lib/python3.13/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm
('litesearch fuses the FTS and vector legs with reciprocal rank fusion.',
 {'prose': 1},
 'RRF over prose; the legs use different encoders, so ranks are fused, not distances')
test_eq(f.legs['prose'], 1)
test_eq(f.hits[0].source, 'prose')
test_eq(v.federate('rank fusion', prose=False, repo=False, grep=False).hits, [])  # every leg off: empty, not an error
assert v.grep('reciprocal rank fusion', '.')                                     # ripgrep reads the disk, not the vault