Code Is Not Documentation
Document knowledge base retrieval: chunk documents, vectorize, find similar chunks when a question arrives, generate an answer.
The same approach works on a codebase, but loses most of what matters. "Find all callers of parseInput()" isn't answerable by similarity search — semantic similarity finds code that looks related, not code that calls a specific function. "What tests would break if I change parseInput()" requires a complete call graph; vector search can't answer it at all.
Three fundamental differences between codebases and document stores:
1. Structure is richer
Documents: paragraphs relate through sequence and reference
Code: functions call functions, classes inherit classes,
modules import modules — these relationships live
in runtime semantics, not in the text
2. Semantics are multi-layered
One business concept scatters across:
- Interface definitions (abstract class / interface)
- Concrete implementations
- Unit tests (test_xxx.py)
- Inline comments (# explains why)
- Function signatures (parameter names convey intent)
Vector retrieval mixes these five layers into one result set
3. High update velocity
Documentation update frequency: monthly / quarterly
Code update frequency: multiple times daily
The index must support incremental updates —
full rebuild is too expensive
Four Understanding Layers
Code knowledge has four layers. Each layer corresponds to different query requirements:
Layer 1: Syntactic
The surface structure of code as text — variable names, function signatures, class definitions, import statements.
# Questions the syntactic layer can answer:
"Find all classes with 'Parser' in the name"
"What functions does this file define?"
"Which files import the utils module?"
Tools: Regex, symbol indexes (LSP/ctags), AST parsing.
Layer 2: Semantic
The intent of functions — what they do, why they exist, how they relate to other functions.
# Questions the semantic layer can answer:
"Find code that handles user authentication"
"Which function is responsible for parsing JSON config?"
"All classes related to database connection management"
Tools: Code vectorization (CodeBERT/semantic embedding) + comment joint indexing. The semantic layer is the natural home of vector search.
Layer 3: Architectural
The dependency structure between modules, call chains, system boundaries.
# Questions the architectural layer can answer:
"What downstream callers would be affected if I modify parseInput()?"
"What's the complete call chain for this feature?"
"What dependencies exist between module A and module B?"
Tools: Call graphs, dependency graphs, code knowledge graphs.
Layer 4: Intent
Why the code is designed this way — historical decisions, trade-offs, business context.
# Questions the intent layer can answer:
"Why is there that strange null check boundary handling?"
"Why was this algorithm chosen over the simpler approach?"
"What bug prompted this code to be added?"
Tools: Git history (commit messages + diffs) + linked Jira/GitHub Issues.
Capability Matrix for Current Approaches
Approach Layer 1 Layer 2 Layer 3 Layer 4
────────────────────────────────────────────────────────────────
grep / ripgrep ✓ ✗ ✗ ✗
Vector search (generic) △ ✓ ✗ △
Vector search (code-tuned) △ ✓✓ ✗ △
AST symbol indexing ✓✓ △ △ ✗
Call graph / dep graph △ △ ✓✓ ✗
Code knowledge graph ✓✓ ✓ ✓✓ △
Git history indexing ✗ △ ✗ ✓✓
Hybrid approach ✓✓ ✓✓ ✓✓ ✓
✓✓ strong ✓ capable △ limited ✗ not supported
No single approach covers all four layers. A production-ready codebase knowledge base requires a hybrid: vector search for Layer 2, graph structures for Layer 3, Git history for Layer 4.
Four Canonical Scenarios
Scenario 1: Bug Localization
User question: "I'm seeing a NullPointerException in config.parse(), where's the relevant code?"
Requires: Layer 2 (find the config.parse implementation) + Layer 3 (trace the call chain to find where the null originates)
Vector-only limitation: Finds the implementation, but can't automatically trace the null value's upstream origin.
Scenario 2: Impact Analysis
User question: "I need to change the return type of UserService.getById(). What else needs updating?"
Requires: Layer 3 (complete call graph)
Tool requirement: Must have a call graph. Vector search cannot answer this question at all.
Scenario 3: Onboarding a New Module
User question: "What's the overall design of the authentication module? What are the main classes and their responsibilities?"
Requires: Layer 2 (class intent) + Layer 3 (class relationships) + Layer 4 (design rationale)
Ideal answer includes: Class list + each class's responsibility + key design decisions (ideally referencing commit records)
Scenario 4: Code Review Assistance
User question: "This PR modifies parseInput(). Is its test coverage complete?"
Requires: Layer 3 (TESTS edges: which tests cover this function) + Layer 1 (find all test functions)
Technology Landscape
Codebase Knowledge Systems
│
├── Traditional Code Search
│ ├── grep / ripgrep Exact string, fastest
│ ├── sourcegraph / zoekt Regex + symbol index, enterprise
│ └── LSP (Language Server) Symbol navigation, definition jump
│
├── Semantic Vector Retrieval
│ ├── Generic embeddings Treats code as text (lossy)
│ ├── CodeBERT / UniXcoder Code-specific pre-trained models
│ └── Code + comment joint Mixed semantic indexing
│
├── Structured Code Understanding
│ ├── AST parsing (Tree-sitter) Syntax structure extraction
│ ├── Call graph Function call relationships
│ ├── Dependency graph Module import relationships
│ └── Code knowledge graph Unified graph representation
│
├── Historical Knowledge
│ ├── Git Blame Per-line modification history
│ ├── Git Commit index Change intent and rationale
│ └── Issue linkage Bug/feature to code mapping
│
└── Agent Interface Layer
├── MCP Server Standard protocol, any Host
├── LSP client IDE integration
└── Custom API Business system integration
Why codebase-memory-mcp Is the Core Reference
codebase-memory-mcp is a MCP Server designed specifically for codebase knowledge, combining:
- Symbol retrieval: AST-based precise symbol location
- Semantic retrieval: vector semantic search
- Graph queries: call and dependency relationship queries
- MCP protocol: standardized exposure, directly usable by Claude Code
It's one complete implementation of the "hybrid approach." Subsequent articles in this series (tool evaluation in Article 02, enterprise deployment in Article 09) build on it directly.
Summary
- Four knowledge layers: syntactic (AST) → semantic (vectors) → architectural (graphs) → intent (Git history); each layer requires different tooling
- No single best approach: vectors handle Layer 2, call graphs handle Layer 3, Git history handles Layer 4 — a production codebase knowledge base is always a hybrid
- The key challenge is velocity: code changes daily; the indexing strategy must support incremental updates, not full rebuilds
Check out PrimeSkills — a curated marketplace of AI agents and skills that have been validated in real-world, enterprise-grade workflows. No fluff, just what actually works.
Find more useful knowledge and interesting products on my Homepage
Top comments (0)