Architecture¶
The application keeps generation, conversation persistence, retrieval, grounding, and evaluation in separate modules. Local retrieval is opt-in; disabling it leaves the streaming chat path unchanged.
flowchart TB
USER[CLI user] --> MAIN[main.py]
MAIN <--> HISTORY[(Conversation JSON)]
MAIN --> RETRIEVER
subgraph RAG[Optional hybrid retrieval]
FILES[Python and Markdown] --> INGEST[AST and heading chunking]
INGEST --> BM25[BM25 index]
INGEST --> VECTOR[Vector indexes]
VOYAGE[Voyage embeddings] --> VECTOR
BM25 --> RRF[Reciprocal Rank Fusion]
VECTOR --> RRF
RRF --> CONTEXT[Grounding context]
end
RETRIEVER[HybridRetriever] --> BM25
RETRIEVER --> VECTOR
CONTEXT -. current turn only .-> CLIENT[ClaudeChatClient]
MAIN --> CLIENT
CLIENT --> API[Anthropic Messages API]
Request lifecycle¶
main.pyloads settings and prior conversation history.- When RAG is enabled,
HybridRetrieverfinds relevant local chunks. context.pyformats those chunks as untrusted grounding material with citation and abstention instructions.ClaudeChatClientstreams the response from the Anthropic Messages API.- Only the user's plain question and Claude's answer are persisted. Injected retrieval context is discarded after the request.
Retrieval pipeline¶
| Stage | Module | Responsibility |
|---|---|---|
| Ingestion | app/rag/ingest.py |
Split Python by top-level symbols and Markdown by headings |
| Lexical retrieval | app/rag/index_bm25.py |
Rank exact vocabulary and code identifier matches |
| Embeddings | app/rag/embed_voyage.py |
Embed code and prose with model-specific spaces |
| Vector retrieval | app/rag/index_vector.py |
Perform exact cosine-similarity search locally |
| Fusion | app/rag/rrf.py |
Merge rankings without comparing incompatible scores |
| Grounding | app/rag/context.py |
Bound context size and frame retrieved text as untrusted data |
Trust boundaries¶
Retrieved repository text is data, not instruction. The grounding layer tells Claude to ignore instructions found inside source chunks and to abstain when those chunks do not support an answer.
The vector cache and indexes contain embeddings and source metadata, but never API keys. Secrets are loaded from .env, which is excluded from version control.