Part 6 · Inside a Production Coding Agent

From File Changes to Hybrid Ranking

Tracing the memory recall pipeline: FTS, vector retrieval, time decay, and MMR re-ranking

THE QUESTION THIS PAGE ANSWERS

ANSWER FIRST

What is the key idea behind “From File Changes to Hybrid Ranking”?

Tracing the memory recall pipeline: FTS, vector retrieval, time decay, and MMR re-ranking

DECISION RULE

Make the claim earn its place. Use this page as a decision aid, not a definition to memorize. Connect the idea to one real task, one observable result, and one failure that would change your mind.

TRY NEXT

Write one question you could answer with evidence after trying this idea.

WATCH FOR

A conclusion that sounds complete but leaves the key assumption untested.

Learning Objective Describe in correct order: sync-on-search, FTS, embedding, KNN, weighted merge, and MMR. Be able to explain what happens when embedding fails and when MMR is disabled.
Core Diagram · Complete Retrieval Path
Watcher Dirty Pathscreate · modify · remove sync-on-searchreindex_file / delete_path User Queryquery FTS5 BM25Always available · keyword candidates Embedding + KNNUses sqlite-vec when available embedding failureFTS-only Merge & Rankdecay × source weight × access boostMMR optional, then truncate SearchResultmax_results
Pedagogical diagram: failure branch falls back to FTS-only; MMR is opt-in and does not re-rank by default.
Real Mechanisms in the Pipeline
01 · SYNC

Sync Before Query

MemoryFileWatcher accumulates changed Markdown paths. The backend re-indexes new or modified files at the start of each search, and deletes stale chunks for removed files.

02 · FTS

BM25 Candidates

First run standard FTS, then supplement with global and workspace source queries to reduce crowding-out caused by too many sessions.

03 · VECTOR

Optional KNN

Embeds the query only when sqlite-vec and the provider are available. Embedding errors are logged as warnings; None is passed to continue FTS-only.

04 · SCORE

Normalize & Merge

BM25 scores and vector L2 distances are normalized separately. Dual-path hits are merged by weight, while ensuring results are not below the chunk's FTS score.

05 · WEIGHT

Time & Source

Sessions decay exponentially with a half-life; global and workspace sources are treated as evergreen. Then multiply by source weight and a moderate access boost.

06 · DIVERSITY

Optional MMR

When enabled, performs greedy re-ranking by relevance and Jaccard diversity of snippets. Finally truncates to max_results.

Two Commonly Misread Switches

Embedding Failure

The vector path stops, but FTS results still enter hybrid_search_merge. The page or caller does not need to treat an embedding failure as a total search failure.

fallback = FTS-only

MMR Default State

MmrConfig::default() sets enabled: false and lambda: 0.7. The 0.7 value only takes effect when MMR is explicitly enabled.

enabled = false
Real Source Code Evidence
crates/codegen/xai-grok-memory/src/search.rs · Lines 146–190 (excerpt)
pub async fn hybrid_search(
    index: &MemoryIndex,
    embedding_provider: Option<&dyn EmbeddingProvider>,
    query: &str,
    config: &MemorySearchConfig,
) -> Result<Vec<SearchResult>, Box<dyn std::error::Error>> {
    let candidate_limit = config.max_results * 3;
    let mut fts_results =
        index.search_fts(query, candidate_limit).unwrap_or_default();
    /* source for supplementing evergreen FTS candidates is here */

    let vec_available = index.vec_available();
    let query_embedding = if vec_available {
        if let Some(provider) = embedding_provider {
            match provider.embed_batch(&[query]).await {
                Ok(embeddings) if !embeddings.is_empty() =>
                    Some(embeddings.into_iter().next().unwrap()),
                Ok(_) => None,
                Err(e) => {
                    tracing::warn!(error = %e,
                        "embedding query failed, falling back to FTS-only");
                    None
                }
            }
        } else { None }
    } else { None };

    hybrid_search_merge(index, fts_results, query_embedding.as_deref(), config)
}
crates/codegen/xai-grok-memory/src/backend.rs: search() — executes watcher sync and query crates/codegen/xai-grok-memory/src/watcher.rs: MemoryFileWatcher crates/codegen/xai-grok-memory/src/mmr.rs: mmr_rerank crates/codegen/xai-grok-config-types/src/memory.rs: MmrConfig defaults
Source Snapshot Note: Based on the local repository grok-build-main, verified on 2026-07-17. Code blocks retain real functions and branches; the only omitted section is explained by a comment; the flow diagram is explicitly labeled as a pedagogical diagram.
Classroom Exercise
06

Trace a Degraded Query

Assume the watcher detects a modified file, query embedding then fails, and MMR stays at its default configuration. Write out — in order — index update, candidate generation, weighted ranking, and final truncation, and mark the two steps that did not occur.

Takeaway: Memory retrieval has two key guarantees: graceful degradation and sync-on-search. FTS always provides baseline candidates while vector search enhances based on availability; time decay and source weight adjust ranking; MMR requires explicit activation; the watcher ensures external Markdown changes are indexed before the next query.

Why “Core Diagram · Complete Retrieval Path” can find relevant content

“MemoryFileWatcher accumulates changed Markdown paths.” moves retrieval beyond storing material: the real question is how to find what is relevant. That decision shapes the input quality of RAG, recommendation, and image-search systems.

Similarity is not the answer

In the flow described by “First run standard FTS, then supplement with global and workspace source queries to reduce crowding-out caused by too many sessions”, embeddings place items in a comparable semantic space and a neighbor index narrows the search. The final answer still depends on whether the retrieved chunks cover the question, whether the distance metric fits, and whether the evidence is current.

Separate findable from relevant

Turn “Assume the watcher detects a modified file, query embedding then fails, and MMR stays at its default configuration.” into a small test: prepare queries with known answers, record relevance, misses, and distractors, then decide whether chunking, the index, or reranking needs to change.

From “Core Diagram · Complete Retrieval Path” to “Sync Before Query”

“Core Diagram · Complete Retrieval Path” grounds the problem in “Watcher Dirty Paths create · modify · remove sync-on-search reindex_file / delete_path User Query query FTS5 BM25 Always available · keyword candidates Embedding + KNN Uses sqlite-vec when available embedding f…”. “Sync Before Query” then moves it toward “MemoryFileWatcher accumulates changed Markdown paths. The backend re-indexes new or modified files at the start of each search, and deletes stale chunks for removed files”. Together, they show that the lesson is not just a conclusion to remember, but a claim with conditions.

Carry the judgment into the next situation

The same logic applies to retrieval: define what counts as relevant, check whether recall covers the question, and then inspect whether ranking, chunking, or freshness pushed useful evidence out.

  • “Core Diagram · Complete Retrieval Path”: Watcher Dirty Paths create · modify · remove sync-on-search reindex_file / delete_path User Query query FTS5 BM25 Always available · keyword candidates Embedding + KNN Uses sqlite-vec when available embedding f…
  • “Sync Before Query”: MemoryFileWatcher accumulates changed Markdown paths. The backend re-indexes new or modified files at the start of each search, and deletes stale chunks for removed files
  • “The closing point”: MmrConfig::default() sets enabled: false and lambda: 0.7 . The 0.7 value only takes effect when MMR is explicitly enabled

The final “The closing point” brings the discussion to “MmrConfig::default() sets enabled: false and lambda: 0.7 . The 0.7 value only takes effect when MMR is explicitly enabled”. The useful thing to carry forward is knowing which judgments must be revisited when input, scale, or risk changes.

Mark as learned Your reading progress updates automatically
← PreviousNext →

Keep reading

The next useful article in the thread.

ARTICLE DISCUSSION

Leave one useful thought here.

Keep the idea that clicked, the question that stayed open, or a small note for the next learner.

Discussing From File Changes to Hybrid Ranking Inside a Production Coding Agent
3discussionsArticle discussion · synced with the Circle
View in the learning circle
AM
Asha MorganContent editor
INSIGHTField note

I turned one judgment from this article into a small experiment I could run today. Knowing what to observe next is more useful than simply remembering the conclusion.

ARTICLE DISCUSSION7 helpful
LH
Lin HarperIndie developer
INSIGHTInsight

After reading this, I first looked for the conditions behind the idea instead of copying the method into a project. That order made the later trade-offs much clearer.

ARTICLE DISCUSSION5 helpful
KM
Kiki MooreProduct operations
QUESTIONQuestion

When this judgment reaches real work, which constraint should be added first? I am curious which step matters most between reading and the first practical attempt.

ARTICLE DISCUSSION4 helpful