Bernardo Castro MEGABRAIN LIVE DEMO ▸

ENGINEERING CASE · JULY 2026

Ask a codebase a question.
Get the exact code back.

megabrain is a code-retrieval engine built on one bet: the LLM is the least reliable part of the system, so it is not allowed in the loop. Retrieval is pure math on embeddings — no model call, ~10ms warm. When a model does narrate, it can only point at code; the engine splices every cited span verbatim from disk. A hallucinated line is not unlikely — it's unrepresentable.

an engineering case by Bernardo Castro — how it's built, with the real numbers · and yes, it was researched by pointing megabrain at its own repo

0

LLM calls in the retrieval path

100%

golden bundle recall — every verified file present

86%

golden R@1 · top file is a gold file

10ms

p50 retrieval, warm

83%

SWE-bench Lite recall@5 · zero training

7

content types · py ts/js rb go rs php md

345×

repeat-question speedup, flow cache

215

tests · offline, no key, 3 OS × 4 Pythons

01 · THE THESIS

Five hard rules, each locked by an experiment.

Every load-bearing choice in the engine was tested against alternatives, and the losers are on the record. These aren't design preferences — they're rules a change is not allowed to violate, because violating them measurably made retrieval worse.

THE RULE → THE EXPERIMENT THAT LOCKED IT

1 · No LLM in the retrieval path

LLM pruning was tested four ways — every variant cost completeness or added 1–2s for no recall gain. The only model calls are the narrator and an optional reorder, and both fail open to plain retrieval.

2 · Completeness beats ordering

The bundle is tuned so golden recall is 1.00 — a change that lowers it is not merged. Noise is handled by render structure, never by dropping files.

3 · The graph never ranks

Import/call edges supply candidates and annotations only. PageRank-as-ranking was tried and rejected: Acc@1 fell 0.91 → 0.73.

4 · Chunks are a line partition

Every file's chunks cover every line exactly once — no gaps, no overlaps. It's a machine-checkable invariant (validate_partition), and it's what makes an LLM-written chunker safe to accept.

5 · ask shows real code only

The model cites spans; the engine splices verbatim code from disk. The model can never emit code — so it can never hallucinate any.

The system in one sentence: point it at a repo, ask "how does auth work" in plain English, and get every related file — ranked, complete, in ~10–200ms with no model call — then, optionally, a senior-engineer walkthrough where every code block is provably copied from disk. Everything below explains each algorithm that makes that claim hold.

02 · HOW IT WORKS

Index once. Answer forever.

Two phases. Index time runs once per repo and is incremental by content hash afterwards; query time is pure vector math. A 60-second auto-refresh keeps answers matching disk — and fails open, because a slightly stale answer beats a crash.

01 · INDEX

DISCOVER

Walk the repo, skip vendored/build dirs and anything in .megabrainignore. Only files whose SHA-256 changed get re-processed — a warm re-index takes seconds.

02 · INDEX

CHUNK · cAST

Split-then-merge over the syntax tree, into chunks that are a strict line partition of the file. Every chunk carries a breadcrumb of where it lives.

03 · INDEX

EMBED · ×2 granularities

Each chunk (breadcrumb + code) AND each file's skeleton (signatures + docstrings) get their own vector — the two signals the fusion needs. Content-addressed disk cache makes near-identical checkouts almost free.

04 · INDEX

STORE · SQLite

One file per repo: chunks, vectors, symbols, skeletons, import/call edges. Vectors load into one NumPy matrix — brute-force cosine is <2ms up to ~50K chunks, so ANN indexing is deliberately deferred.

05 · QUERY

SCORE · fused

Dense chunk similarity + half the file-skeleton similarity, a soft test-file penalty, and lexical boosts for short developer queries. No LLM anywhere in this box.

06 · QUERY

BUNDLE · CORE + RELATED

Top files within 3% of the leader show full code; every other candidate — plus graph neighbors — maps as file · best-span pointer · symbols. Complete by construction.

07 · ASK

NARRATE · 1 call

One streamed chat call, forbidden from quoting code — it may only cite [[k]] spans. Broad questions fan out into parallel sub-agents first.

08 · ASK

SPLICE · verbatim

Every citation is replaced by the real block from disk — true file, true line numbers, sub-ranges snapped to symbol edges, repeats deduped to back-references.

one retrieval core, four shells — CLI · MCP server inside Claude Code · HTTP API + studio web UI · typed Python API

03 · THE CHUNKERS — cAST WITH A PARTITION INVARIANT

Split then merge, and never lose a line.

Naive RAG splits code every N characters and slices functions in half. megabrain walks the syntax tree instead (the cAST recipe): segment the file into top-level units — comment and blank gaps attach to the unit that follows them — then merge small units greedily up to a budget of 4000 non-whitespace characters, and split oversized ones structurally: a big class becomes a class-header chunk plus one chunk per method; a big function becomes sequential part k/n blocks; an unsplittable giant (a huge dict literal) falls back to line windows. Whitespace doesn't count against the budget, so indentation style can't change what lands together.

A FILE BECOMING CHUNKS · watch the partition

module
1 """Store: SQLite schema + matrix loads."""
2 import numpy as np
3 DEFAULT_BUDGET = 4000
class_header · Store
4 class Store:
5 """One SQLite file per repo."""
method · Store.load_matrix
6 def load_matrix(self):
7 rows = self.db.execute(SEL).fetchall()
8 return metas, np.vstack(vecs)
block · part 1/2
9 _LANG_TABLE = {
10 "py": "python", "ts": "typescript",
block · part 2/2
11 "rb": "ruby", "go": "go", "php": "php",
12 }

validate_partition ✓ — lines 1–12 covered exactly once · no gaps · no overlaps

WHY THE PARTITION IS THE ONE HARD INVARIANT

A gap is a span of code that can never be retrieved — invisible forever, silently. An overlap double-counts evidence and corrupts scores. So validate_partition checks every file: first chunk starts at line 1, each chunk starts exactly where the previous ended, the last one ends at the file's last line.

The payoff is bigger than hygiene: because legality is machine-checkable, the engine can accept chunkers it didn't write — a custom strategy, or one an LLM generated — by testing them against the oracle instead of trusting them. That's the keystone forge builds on (§07).

And every chunk embeds with a breadcrumb headerrepo > path > class Sig > def method(sig) — so the vector carries where the code lives, not just what it says (contextual retrieval).

ONE ALGORITHM, N LANGUAGES

The split-then-merge logic is language-agnostic; only node recognition changes. A LangSpec declares each grammar's def types, name fields and export unwrapping — so TS/TSX/JS/JSX, Ruby, Go, Rust and PHP share one chunker, and adding a language is a config entry plus a pip install, not a new class. The specs encode real grammar quirks: Rust's impl Foo has no name field (it falls back to the type), Ruby's class << self would otherwise become anonymous blocks, and CommonJS proto.use = function() assignments are captured as methods — express's entire router API is invisible without that.

LEGACY PHP — SHAPE-ROUTED

Early-2000s PHP — 2000-line files mixing HTML, SQL and top-level statements — defeats any def-based chunker. A heuristic on the parse tree routes by shape: a namespace means modern (untouched, byte-identical); top-level soup or HTML islands mean legacy. Legacy files get a section chunker where //-------- banner comments act like markdown headings — they name sections, become outline symbols, and are preferred cut points. Functions stand alone with their doc-banner attached; HTML islands get their own kind.

MARKDOWN — SCORED CUTS, NOT RIGID SPLITS

Docs use QMD-style break selection: every line gets a cut score — H1=100 down to H6=50, a code-fence boundary 80, a paragraph start 20 — and cutting inside a fence is forbidden outright. A greedy pass picks the best-scoring legal cut near the size target, so chunks are heading-aligned and never split mid-section. The same scored-cut function is shared with the PHP section chunker — one algorithm, two content types.

04 · RETRIEVAL — DUAL-GRANULARITY FUSION

A strong chunk in a weak file shouldn't win.

THE FUSION FORMULA

dense = cosine(query, chunk)

file = cosine(query, skeleton(chunk's file))

fused = dense + 0.5 · file

fused *= 0.85 if the chunk lives in a test file

dense — chunk relevance 0.72

file — skeleton relevance 0.61

fused = 0.72 + 0.5 × 0.61 1.03

The file signal comes from embedding each file's skeleton — signatures, docstrings, module constants — as one vector. The 0.5 weight is the validated core hypothesis: a decent chunk in the clearly-relevant file should outrank a strong chunk in an irrelevant one. Short developer queries (≤25 identifier tokens) also get small grid-tuned boosts for exact filename and symbol token matches — capped at two tokens each, so they nudge without dominating.

TIERING — AND WHY RELATED CAN NEVER BE DROPPED

Files rank by their best chunk; the top 12 are candidates. CORE = files within 3% of the leader → their matching chunks in full (each file keeps chunks scoring ≥80% of its best). RELATED = everything else, plus graph neighbors of the top files, rendered as a map: file · best-span pointer · symbols.

Measured on the golden set, CORE alone finds every gold file for only 36% of queries; CORE + RELATED reaches 100%45% of gold files live in RELATED. But RELATED was also ~16K of a ~22K-token render at ~5% gold density. The fix is structural, not destructive: RELATED keeps its membership and loses its inline code bodies (−65% tokens). Completeness by data, economy by render.

CORE only · bundle recall 0.36

CORE + RELATED 1.00

THE GRAPH — CANDIDATES, NEVER RANK

At index time the engine extracts import/call edges: Python via a package index that resolves from pkg import X and call sites to unique defs; TS/JS by resolving relative imports (including export * from, dynamic and side-effect imports) against the real file set; PHP by building an FQCN→file map from actual namespace + declarations — PSR-4-agnostic, so it works whatever the folder layout — then resolving use statements, group-use and trait-use against it.

At query time, neighbors of the top files join the bundle as extras in RELATED only. They can add recall; they can never touch the ranking — because when the graph was allowed to rank, accuracy collapsed (rule 3).

ISSUE MODE — LONG QUERIES GET THREE EXTRA LANES

A pasted bug report (>25 identifier tokens) is not a developer query — so three deterministic signals switch on, still with no LLM:

Variant ensemble — title, traceback, fenced code and an identifier bag are embedded in one batch call and merged by reciprocal-rank fusion, the full-issue ranking double-weighted

Traceback grounding — Python File "x.py", line N and JS/TS at fn (src/x.ts:12:5) frames pin files with tiered bonuses (frame > explicit path > backticked identifier), and the enclosing function's span gets its own bonus

Entity-ID BM25 — a sparse lexical lane over each file's path + symbol names + signatures, RRF-merged. Issue-mode only: it raised SWE-bench recall but cost golden completeness on short queries, so it stays out of them

THE OPTIONAL RERANK — AND ITS ASYMMETRIC SAFETY VALVE

--best runs a listwise LLM reorder: each candidate presented with its actual best chunk, three votes in parallel, merged by mean rank. It is permute-only — never adds or removes candidates, so recall is untouched by construction — and it fails open to retriever order. The subtle part is bounded demotion: a file may rise freely on the votes, but may fall at most one place below its retriever rank. The LLM is trusted to promote what the code evidence supports, and distrusted to demote what the math already ranked high — an asymmetry that encodes exactly how much the model has earned.

05 · ASK — THE VERBATIM SPLICE

The model can point. It cannot paste.

The narrator's prompt forbids quoting code and requires double-bracket citations — [[3]] for a whole chunk, [[3:705-731]] for a line range. As the answer streams, the engine replaces each citation with the verbatim block read from disk: real file, real line numbers, sub-ranges snapped outward to enclosing symbol edges so a citation never opens mid-function, repeated spans deduped into back-references. If the model cites nothing, or errors, or there's no key — fail open to the full retrieval bundle. Non-cited candidates always list in a footer, so the model's selection is never a silent filter.

WHY THIS IS A GUARANTEE, NOT A PROMPT

Prompting a model "don't hallucinate" is a request. This is an information-flow property: code in the final answer has exactly one producer, and it's a file read. The model's tokens are prose and citation indices — there is no channel through which an invented line of code can reach the output.

The narrator itself is provider-routed: a logged-in Claude Code subscription (via the Agent SDK, pinned to pure narration — no tools) or any OpenAI-compatible endpoint. A bakeoff found qwen3-coder on par with Claude Haiku at citation selection at ~5× lower cost — because retrieval already guarantees completeness, the narrator only has to choose, not to find.

DOCS ARE A FIRST-CLASS MODE

Markdown indexes alongside code with the same partition guarantee, so --docs walks documentation only and --with-docs explains code and docs together. The heading-aligned chunks mean a docs answer returns whole sections in reading order, not fragments — which is also what powers the /docsearch endpoint: a documentation site's search box served by the same index, section-level hits deduped to the best per page.

05.1 · ASK V2 — ADAPTIVE MULTI-AGENT SYNTHESIS

A broad question dilutes a single narrator — it must cover several subsystems in one pass. So ask branches on the shape of the retrieval itself, classified in ~0ms with no LLM: several CORE files inside the tier-1 gap, candidates spread across ≥3 top-level directories, ≥4 RELATED files near score parity, or an issue-length query — any signal means broad. Scoped questions never pay the fan-out.

a broad question fanning out — the real event stream

~ $

retrieval 189ms · 21 files → BROAD (3 CORE within the gap · spans 4 dirs)

plan → 3 agents: chunking · retrieval-scoring · ask-splice

agents run in parallel · each may call search_more / get_file / get_symbol (tools are still no-LLM)

synthesis → one walkthrough · 9 spans spliced verbatim from disk

global citations

Every sub-agent cites [[k]] into one shared candidate index. The synthesizer merges partials preserving the numbers — so the unchanged splice pipeline grounds the merged answer, and repeated spans dedupe across agents.

a planner that can be wrong

One cheap LLM call splits the question and assigns each agent a disjoint slice of chunks. If it emits garbage: deterministic clustering by top-level directory. If that yields one group: single-agent ask. Fail-open at every link.

bounded everything

≤4 agents, ≤3 tool rounds each, capped tool output, per-agent timeout — one hung agent dies alone and the rest proceed. The whole run emits JSON events, so the CLI, the SSE endpoint and the studio UI all watch the same stream.

06 · GRAPH — THE REPO AS A NAVIGABLE MAP

Two lanes of evidence. One map. No model in the structure.

Graph-RAG tools spend LLM sub-agents extracting relationships from source. megabrain already owns them: the AST import/call edges written at index time are the structural lane, and the per-file skeleton embeddings add a semantic lane — files that talk about the same thing without ever importing each other, carrying an honest cosine instead of a model's "inferred" tag. Communities, god nodes, surprises and paths are all numpy on top of that. The only LLM in the module is naming the communities: one buffered call, cached under a graph fingerprint, fail-open to Community N.

STRUCTURAL LANE · index time

Each language strategy resolves imports and call sites to real files in this repo — never to a package name. Go gets two lanes, because a Go package's files call each other with no import at all: resolved-import edges plus same-package sibling calls, with a lookbehind guard so other.Name can't leak in as a bare use. PHP walks use, group-use and trait-use through the FQCN map, falling back to the file's own namespace so a bare trait name resolves to the sibling that defines it.

Edges are replaced per file on every reindex, and an extractor upgrade re-extracts files whose bytes never changed — edges are derived data, so backfilling them costs zero embeddings.

SEMANTIC LANE · graph-build time

The file skeletons — signatures and docstrings, already embedded at index time — are L2-normalized, and one matrix product yields every pairwise cosine. Each node keeps its top 3 neighbours above 0.80, stored bidirectionally with the score as the edge weight. Capped on purpose: the graph stays sparse enough to be read, and a similarity edge never outnumbers the real ones.

This is the lane that finds the two email handlers with identical vocabulary and no shared import — the relationship a pure import graph structurally cannot represent.

communities · label propagation

Every file starts as its own community, then votes: a structural neighbour weighs 1.0 × its edge kinds, a semantic one 0.5 × its cosine. Fixed visit order and a smallest-label tie-break make it byte-stable across runs; communities renumber by size. No networkx, and no resolution knob to tune — label prop is parameter-free. PageRank was tried and lost, but for ranking; this is structure, a different job.

god nodes · the core abstractions

Ranked by undirected structural degree, reported with the in/out split and their community. These are the routers, the config loaders, the package __init__ — the files that everything touches, and the honest first answer to "where do I start reading". The same degree signal is what later makes them expensive to walk through.

surprises · what imports can't show

Pairs scoring ≥ 0.85 — stricter than the edge floor — with no structural edge and in different communities. Duplicated logic, parallel implementations, the copy-paste that drifted. Scored, not asserted: every surprise ships with the cosine that produced it.

06.1 · THREE MODES, INCREASING DEPTH

map

Labeled communities, god nodes, surprises, and every node and edge. The studio renders it as one bubble per multi-file community, sized by membership and linked by inter-community edge counts — deliberately never the whole-repo hairball. Where you start an unfamiliar codebase.

node

One file — resolved from a path or a concept. Exact path wins, then filename, then embedding: "the scoring pipeline" lands on scoring.py. Test files carry retrieval's same soft penalty here, because a test's skeleton is full of the vocabulary of the thing it tests. Returns its community, in/out edges, semantic neighbours, symbols — and its real chunks, spliced verbatim.

path

A route between two concepts, both endpoints resolved by embedding. Each hop names the carrier symbols — defined in one file and actually used in the other, AST call sites before inferred matches — and splices both the use site and the definition. It also separates a true call chain from a meeting point, where the two endpoints never call each other but both reach into the same middle.

06.2 · THE HUB TOLL — WHY BFS GIVES YOU A USELESS PATH

A SHORTEST PATH THROUGH THE LOGGER EXPLAINS NOTHING

Any two files in a repo are two hops apart through the config module. Unweighted BFS finds that route and calls it the answer — verified live against the obvious baseline (nx.shortest_path): it routes through the single highest-degree node in its own graph, every time, because plain BFS has no concept of a boring hub.

So transit is costed, not just ordered — Dijkstra over the combined graph. The degree distribution sets the price: anything above the repo's own p90 pays to be a stop, scaled by how hubby it is. The result is a route through real relationships instead of infrastructure.

THE PRICE LIST

structural hopan import or a call2
semantic hopsimilarity, not a real link — costs more3
__init__.pypackage plumbing, at any graph size+4
test filebridges without explaining+4
hub, degree > p903 + every edge past the floorscaled
the endpointsyou asked for them — exempt0

The toll generalized an earlier rule that penalized __init__ by name — which missed the real offender: a production logger module with an in-degree of 94.

07 · FLOWS — RETRIEVAL THAT LEARNS ITS OWN ANSWERS

An answer worth seven seconds shouldn't be computed twice.

A successful ask synthesizes a cross-file workflow — the most expensive artifact the engine produces, and until 0.11 it was thrown away the moment it was printed. The flow cache (on by default, per-repo opt-out, env kill-switch) stores the rendered walkthrough — prose and the code already spliced from disk — so a repeat question can be served without a model ever running.

THE WRITE PATH · two vectors, one batch call

Every cited answer is embedded twice in a single request: question + prose (the semantic-recall lane) and question only (the near-exact lane, so a long walkthrough's prose can never dilute an identical question down to a miss). Code is stripped before embedding; the stored text keeps it for serving. The flow also records the SHA-256 of every file it cites.

The dedup key is the question, not the answer: anything above 0.92 on the question-only vector replaces the old row, so two narrations of one question can never accumulate. The write lives in the single ask pipeline, which is why the CLI, the SSE stream and the studio all feed the same cache.

THE READ PATH · three tiers of pure cosine

≥ 0.88 → SERVE — near-exact question, still-current files: the cached walkthrough is returned verbatim, no LLM at all. Measured 6.9s → 0.02s, a 345× repeat-question speedup — and on the hosted demo a cache hit refunds the rate-limit slot, because it spent nothing.

0.62 – 0.88 → ATTACH — a paraphrase of the same workflow rides along as explicitly non-citable context, and the narrator answers fresh against the real chunks.

below 0.62 → nothing — the lane is a no-op, at zero cost.

All of it runs against the query vector retrieval already computed. Never a second embed, never a model call.

the coverage guard

A high score is not enough to serve. The cached question must also contain ≥80% of the query's content words — with question scaffolding ("how does… work", "where is… handled") stripped first, since it carries no topic. Without it, a compound question is silently half-answered by a cached flow that only covered its first clause.

flows attach, they never rank

A matched flow cannot reorder or displace a single file. Its source files append to the RELATED tail only when missing entirely, at most 3 — pure additions, so the bundle's recall can only rise. The §04 rule holds: nothing that isn't measured evidence gets to move a ranking.

it cannot outlive its code

Every reindex prunes any flow whose cited files changed SHA or vanished. Serving re-checks the hashes against disk, not the index — which can lag it by the 60s refresh — so a walkthrough is never served for code that has already moved on.

EXPIRE, OR UPDATE

Pruning is the free default. flows --refresh is the opt-in alternative: reindex keeping the stale rows, then re-ask each flow's original question against the current code so the walkthrough is regenerated rather than lost. Flows whose sources all vanished are dropped — there's nothing left to re-ask.

And flows --warm starts the cache full instead of lazily: a deterministic planner derives the repo's main workflows from its central files and pre-asks them, once, on request.

THE BUG THAT SHAPED THE CONTEXT FORMAT

An attached flow is stored rendered — including the citation chrome the splicer emits, headers like **`src/x/y.py` L58-83**. Fed back to a narrator as context, the model imitated the format: it emitted those headers instead of [[k]] citations, so the splicer matched nothing and the answer confidently named files, lines and symbols while displaying not one line of code.

So the attach lane strips code, citations, headers and back-references before the flow ever reaches the prompt, and labels what remains do NOT cite this. A stale flow can now mis-prioritize — it can never fabricate, because the splice still only copies from disk.

the cache is also the UI's memory: with no .megabrainqueries committed, the studio's starter chips are the questions already in the flow cache — clicking one answers instantly, and the row says so honestly

08 · FORGE — THE ENGINE WRITES ITS OWN CHUNKERS

An LLM writes code once — behind an oracle.

A repo full of .toml or .proto files the registry can't index is invisible to retrieval. megabrain forge closes that hole: a deterministic census finds uncovered extensions, an LLM writes a ChunkStrategy from the real contract source plus sample files from this repo — and the candidate is accepted only if it chunks every matching file with a clean partition. Failures feed a repair loop, three attempts max. The LLM writes code exactly once, at forge time, gated by the machine-checkable oracle from §03 — retrieval stays LLM-free.

THE VETTING PIPELINE · live

Real run on pallets/click: .toml (11 files) and .yaml (8 CI workflows) both forged first-attempt in ~28s — and "which workflow runs the test suite" went from a total miss to the right file at #1.

VERDICT: INSTALLED — trust-gated, loads on every reindex

censusuncovered extensions, deterministic — no LLMFOUND .toml
generateone chat call: contract source + real samplesCANDIDATE
compilemodule execs, ChunkStrategy instantiatesPASS
partitionattempt 1: gap at L41 on file 7 of 11REPAIR
partitionattempt 2: every matching file, cleanPASS
trustsha256 recorded in the user-level storePASS

THE TRUST MODEL — A CLONED REPO CANNOT SELF-APPROVE

Vetted strategies live in the repo (.megabrain/strategies/*.py) and load on every reindex — which means the loader executes repo-provided code. So it's trust-gated: a module loads only when its SHA-256 matches the entry in the user-level store (~/.megabrain/trust.json) — a location the repo itself cannot write. forge records the hash on install; megabrain trust approves hand-written modules; any edit un-trusts the file — skipped with a loud warning, never silently — until re-approved. Cloning a malicious repo gets you exactly nothing executed.

SPECIALIZATION — WHERE THE LLM LOST ON PURPOSE

Rewriting how an already-covered file is chunked needs a second, empirical gate: neutral probe spans derived from the file's own structure score both chunkers on identical targets, using rank-aware span-IoU — the file's top-retrieved chunk versus the true span, not best-over-all-chunks, because an early version of that metric let a median-one-line micro-chunker fake a winning score. A candidate installs only on a measured win with no per-file regression.

And the honest finding: LLM-generated specializations lost to the deterministic recipe everywhere they were tried, so that path was removed. Deeper still — on the only human-verified query set, no chunk budget beats 4000. Tighter chunks read nicer and rank worse, because the merge concentrates a file's evidence, and that's what wins retrieval.

09 · EVIDENCE — THE BAKEOFFS

Every default earned its place in a measured fight.

EMBEDDING BAKEOFF · golden R@1, same harness, same corpus

The smallest, cheapest model won on both axes — and it's 30–60× faster per query than the 3072-dim giants. Bigger was not better: the code-specialized and the largest general models all scored lower. The winning R@1 came with 95.5% bundle recall; a one-notch bump to the graph-extras cap took it back to 1.00.

CHUNK-BUDGET SWEEP · golden R@1 by recipe

The literature-tuned 2000-char recipe and a surgical blob-splitter both lose to the plain 4000 merge. Span precision and retrieval ranking are different objectives — optimizing the first quietly damages the second. This is the experiment that killed LLM-generated chunker "improvements".

SWE-BENCH LITE · file localization, Acc@1 / Acc@5

megabrain is retrieval-only and has never seen SWE-bench in training; both baselines are retrievers trained for this task. Parity with CodeRankEmbed, untrained — and when ask narrates and its cited files are scored instead, Acc@1 rises to 0.69–0.71, into trained-SweRank territory.

WHAT THE GOLDEN GATE ACTUALLY IS

Human-verified queries over a real production codebase, each with its verified gold files. Every engine change runs the gate: R@1 0.86 · bundle recall 1.00 · p50 ~10ms warm — plus a multi-repo gate and a 134K-line scale gate. A change that drops bundle recall doesn't merge, whatever else it improves.

The offline suite — 215 tests, no network, no key — runs in CI on Linux, macOS and Windows across four Python versions. Windows is in the matrix for a reason: platform-default text decoding once silently indexed mojibake, and backslash path keys once corrupted an index. Both are regression-guarded now — the second reason every relpath in the store is POSIX on every platform.

10 · SURFACES — ONE CORE, FOUR SHELLS

The same retrieval, wherever the caller lives.

MCP · inside Claude Code

A stdio server with a deliberately lean surface — six tools, because every tool costs the calling agent context and a routing decision. Auto-refreshes a stale index (60s TTL, fail-open) before answering, so results always match disk.

megabrain_ask · _search · _graph · _index · _forge · _flows

CLI

index · ask · query (with --prune for flat signal-only chunks) · graph · get · chunks · forge · trust · flows · scan. Path-scope everywhere: pass a sub-path and retrieval confines itself to it; the repo root auto-detects up the tree.

megabrain ask ~/repo/src/auth "how does login work"

HTTP + studio

A stdlib server with warm state that reloads on db-mtime change; SSE streams the multi-agent ask live. Bearer auth on everything but /health; file reads are containment-checked so ../../etc/passwd can't escape the repo. studio serves a local web UI over it — search heatmap, signal/noise view, the agents live.

megabrain serve-api ~/repo · /ask/stream · /docsearch

Python API

Typed, lazily imported: index_repo · search · load_state · prune_search · ChunkStrategy. Custom strategies inject ahead of the built-ins — claim a new content type or override one, no fork. Multi-repo search merges by score across concurrently-queried roots.

import megabrain · py.typed

and the dogfood loop is real: pinecall's knowledge-base RAG is a megabrain index, the docs search on a production docs site is /docsearch, and this page was researched with 20 megabrain_ask calls against the engine's own repo

11 · WHAT'S SHIPPED

Published, gated, and running.

On PyPI as megabrain (0.9.1), MIT-licensed, releasing through CI with Trusted Publishing — and drivable by anyone in the live demo on this site.

THE ENGINE

Syntax-tree chunking with a machine-checkable partition invariant, across 7 content types via one LangSpec-parameterized algorithm

Dual-granularity fusion — chunk + file skeleton — with a soft test-file penalty and capped lexical boosts

Deterministic issue mode: variant-ensemble RRF, traceback grounding for Python and JS/TS, an entity BM25 lane

Verbatim splice — the LLM cites, the engine copies from disk; hallucinated code is unrepresentable

Adaptive multi-agent ask with shape-based classification, global citations and a fail-open chain at every link

A knowledge graph over AST edges plus skeleton-cosine edges — deterministic communities, god nodes, surprises, and hub-tolled paths that carry the symbols and code of every hop

A flow cache that serves a repeat question 345× faster with no model call, and dies with the SHA of the code it describes

forge: LLM-written chunkers accepted only through the partition oracle, installed behind a user-level trust store

THE PROOF

Golden gate on every change: R@1 0.86 · bundle recall 1.00 · p50 ~10ms

SWE-bench Lite localization without training: Acc@5 0.83, on par with a trained retriever; ask-cited Acc@1 0.69–0.71

Embedding, ask-model, budget and graph-extras bakeoffs all on the record — including the ones the defaults lost

215 offline tests in CI across 3 OSes × 4 Pythons — Windows in the matrix because it caught real corruption twice

Runs fully local if you want it to: Ollama embeddings + a Claude Code subscription narrator, zero cloud keys

In production underneath other systems on this site — the voice platform's RAG and a docs site's search are both this index