<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: WonderLab</title>
    <description>The latest articles on DEV Community by WonderLab (@wonderlab).</description>
    <link>https://dev.to/wonderlab</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3797373%2F25beba30-d8d4-4d2e-9ec6-170356089350.jpg</url>
      <title>DEV Community: WonderLab</title>
      <link>https://dev.to/wonderlab</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wonderlab"/>
    <language>en</language>
    <item>
      <title>Codebase Knowledge Base (13): Evaluation — How to Know Your Knowledge Base Is Good Enough</title>
      <dc:creator>WonderLab</dc:creator>
      <pubDate>Tue, 11 Aug 2026 02:31:03 +0000</pubDate>
      <link>https://dev.to/wonderlab/codebase-knowledge-base-13-evaluation-how-to-know-your-knowledge-base-is-good-enough-31o9</link>
      <guid>https://dev.to/wonderlab/codebase-knowledge-base-13-evaluation-how-to-know-your-knowledge-base-is-good-enough-31o9</guid>
      <description>&lt;h2&gt;
  
  
  Why Recall@5 Isn't Enough
&lt;/h2&gt;

&lt;p&gt;Article 03 set a precedent: test the vector path on 30 retrieval questions, Recall@5 = 0.958. Every subsequent article with retrieval experiments used similar reporting.&lt;/p&gt;

&lt;p&gt;Recall@5 is a reasonable starting metric — but it has three blind spots.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blind spot 1: Precision.&lt;/strong&gt; Recall@5 asks 'did the correct answer appear in the top 5 results?' But code retrieval often targets 'precisely locate that one function.' Appearing 5th versus 1st scores identically in Recall@5, but the practical difference is large — first place means direct hit, fifth place means manual scanning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blind spot 2: Task type.&lt;/strong&gt; Article 08 established a three-path architecture, with different paths serving different tasks: vector for semantic exploration, graph for structural traversal, symbol for exact matching. Which path does a Recall@5 dataset evaluate? Combined evaluation of all three, or separate? Combined evaluation masks each path's specific weaknesses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Blind spot 3: Impact analysis.&lt;/strong&gt; One of the core values of a codebase knowledge base is 'if I change this function, what else does it affect?' The correct answer to this question is a set (all upstream callers), and evaluation must check not just 'did it return relevant results' but 'did it miss any important callers?' That's a recall problem — but not Recall@5.&lt;/p&gt;




&lt;h2&gt;
  
  
  Four-Dimensional Evaluation Metrics
&lt;/h2&gt;

&lt;p&gt;Given codebase knowledge base characteristics, four purpose-built metrics:&lt;/p&gt;

&lt;h3&gt;
  
  
  Metric 1: Symbol Location Accuracy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; For a set of 'where is this feature implemented' queries, the percentage where the correct answer (target function) appears in first place.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Top-1 instead of Top-5:&lt;/strong&gt; Code retrieval 'success' means finding that specific function. Appearing in third place means manual filtering is still required. Top-1 accuracy measures direct-hit capability, which has the largest impact on actual engineering usability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Evaluation dataset construction:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sample queries:
Q1: "how to insert a new document into LightRAG"
A1: lightrag/lightrag.py::ainsert (function, line 1428)

Q2: "what query modes does LightRAG support"
A2: lightrag/base.py::QueryParam (class, line 83)

Q3: "where is document chunking strategy decided"
A3: lightrag/parser/routing.py::resolve_chunk_options

Q4: "what cleanup operations does deleting a document trigger"
A4: lightrag/lightrag.py::adelete_by_doc_id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Based on this series' experimental data: article 03's vector Recall@5 = 0.958, but Top-1 accuracy typically lands at 0.75-0.85 — the answer is in the top 5, but first-place rate is lower.&lt;/p&gt;

&lt;h3&gt;
  
  
  Metric 2: Semantic Search Recall
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; For a set of queries, the percentage where the correct answer appears in the top K results. K is typically 5 or 10.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Difference from Recall@5:&lt;/strong&gt; The evaluation target isn't full-set retrieval — it specifically focuses on &lt;strong&gt;vocabulary mismatch scenarios&lt;/strong&gt;: the user says 'file parsing,' the code calls it 'document ingestion pipeline'; the user says 'caching mechanism,' the code uses 'KV storage with TTL.'&lt;/p&gt;

&lt;p&gt;These queries most clearly demonstrate the value of the vector path: BM25 fails at vocabulary mismatch, while vector embeddings bridge the lexical gap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key dataset construction principle:&lt;/strong&gt; queries must deliberately use different terminology than the code. Otherwise BM25 can answer correctly, which doesn't test the vector path's contribution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Strong test cases (vocabulary mismatch):
Q: "document deduplication logic" → A: compute_mdhash_id (operate.py)
Q: "LLM request rate control" → A: priority_limit_async_func_call (utils.py)
Q: "knowledge graph node merging" → A: _merge_nodes_then_upsert (operate.py)

Weak test cases (vocabulary directly matches — BM25 can do this too):
Q: "priority limit async func" → A: priority_limit_async_func_call
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Metric 3: Impact Analysis Completeness
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; For a target function, given a query for 'all direct callers,' the intersection ratio between returned callers and actual callers.&lt;/p&gt;

&lt;p&gt;This is the metric closest to real engineering value: before modifying a function, can the knowledge base tell you every affected location?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Formula:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Completeness = |returned callers ∩ actual callers| / |actual callers|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real measurement from LightRAG (article 09): &lt;code&gt;QueryParam&lt;/code&gt; has 19 actual callers, &lt;code&gt;search_code("QueryParam")&lt;/code&gt; returned all 19. Completeness = 1.0 for this case.&lt;/p&gt;

&lt;p&gt;Not all functions are this clean. &lt;code&gt;BaseVectorStorage.upsert&lt;/code&gt; has fan_in = 268 — if the tool has a return limit (say limit=50), it would miss 218 callers and completeness would drop sharply. That's not a recall algorithm problem — it's a tool configuration problem. But evaluation surfaces that configuration gap.&lt;/p&gt;

&lt;h3&gt;
  
  
  Metric 4: History Query Hit Rate
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; For a set of 'why is this code written this way' queries, whether FILE_CHANGES_WITH edges or detect_changes historical data provide meaningful signals.&lt;/p&gt;

&lt;p&gt;This is the hardest metric to quantify, since 'meaningful signal' is inherently subjective. In practice, binary scoring works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 = query results include directly relevant historical change information
0 = query results are empty or irrelevant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For &lt;code&gt;priority_limit_async_func_call&lt;/code&gt;: query the historical change pattern of &lt;code&gt;utils.py&lt;/code&gt;, get 'high-frequency change file' — hit, score 1.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;base.py::QueryParam&lt;/code&gt;: FILE_CHANGES_WITH shows &lt;code&gt;base.py ↔ lightrag.py&lt;/code&gt; has strong coupling — hit, score 1.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three Sources for Evaluation Datasets
&lt;/h2&gt;

&lt;p&gt;When building evaluation datasets, codebase knowledge bases have a natural advantage over document RAG: &lt;strong&gt;the code itself is the annotation source&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source 1: Extracted from test files
&lt;/h3&gt;

&lt;p&gt;Test files are the best documentation of 'what this function should do.' For each test function, you can reverse-engineer the corresponding production retrieval question:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# tests/test_query.py
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_hybrid_query&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;QueryParam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hybrid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;what is LightRAG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From this test, automatically generate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query: 'LightRAG hybrid query mode'&lt;/li&gt;
&lt;li&gt;Expected answer: &lt;code&gt;lightrag/base.py::QueryParam&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;LightRAG has over 200 test files — each is a potential evaluation data source.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source 2: Extracted from git commit messages
&lt;/h3&gt;

&lt;p&gt;Git commit messages frequently contain 'which function had what problem fixed' — reversible into queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;commit: "fix: priority_limit_async_func_call deadlock when worker timeout"
→ Query: 'where is the concurrent LLM call timeout deadlock handled'
→ Expected answer: lightrag/utils.py::priority_limit_async_func_call
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The characteristic of this dataset type: it tests 'real questions real engineers would ask,' which is more representative of actual usage than manually constructed questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source 3: Manually constructed hard cases
&lt;/h3&gt;

&lt;p&gt;The first two sources tend to cover 'parts of the codebase with explicit documentation.' But the scenarios where engineers most need the knowledge base are precisely those &lt;strong&gt;without documentation, where understanding requires reading the code&lt;/strong&gt;. These need manual construction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hard case examples:
Q: "do SDK users and REST API users go through different code paths for document processing?"
A: Yes — SDK goes through ainsert (F-only), REST API goes through apipeline_enqueue_documents
   Finding the answer means locating the branch point between the two paths

Q: "changing a Kafka message format — which consumers are affected?" (cross-repo)
A: Requires cross-repo analysis, finding CROSS_ASYNC_CALLS edges
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These cases don't need to be the majority of the evaluation set (around 20% is sufficient), but they're the dividing line between 'good enough' and 'genuinely useful.'&lt;/p&gt;




&lt;h2&gt;
  
  
  Reference Baselines for Four-Dimensional Metrics
&lt;/h2&gt;

&lt;p&gt;Based on experimental data from the preceding twelve articles:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Weak baseline (vector only)&lt;/th&gt;
&lt;th&gt;Three-path baseline&lt;/th&gt;
&lt;th&gt;Four-path baseline&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Symbol Location Accuracy (Top-1)&lt;/td&gt;
&lt;td&gt;0.65-0.75&lt;/td&gt;
&lt;td&gt;0.85-0.92&lt;/td&gt;
&lt;td&gt;Similar to three-path (history path aids understanding, not location precision)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Semantic Search Recall (@5)&lt;/td&gt;
&lt;td&gt;0.90-0.96&lt;/td&gt;
&lt;td&gt;0.95-0.99&lt;/td&gt;
&lt;td&gt;0.95-0.99&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Impact Analysis Completeness&lt;/td&gt;
&lt;td&gt;N/A (single path can't do impact analysis)&lt;/td&gt;
&lt;td&gt;0.90-1.0 (depends on limit config)&lt;/td&gt;
&lt;td&gt;0.90-1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;History Query Hit Rate&lt;/td&gt;
&lt;td&gt;0 (no history path)&lt;/td&gt;
&lt;td&gt;0 (no history path)&lt;/td&gt;
&lt;td&gt;0.70-0.85&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;How to read this table:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Semantic search recall is already high at the weak baseline (0.90+), because article 03 proved that AST-chunked vector retrieval is already quite strong. The three-path improvement shows up mainly in Top-1 accuracy and impact analysis — the two scenarios where vector retrieval alone performs poorly.&lt;/p&gt;

&lt;p&gt;History Query Hit Rate is a four-path-only metric measuring whether the knowledge base can answer 'why' questions. The first three paths score 0 on it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wiring Evaluation into CI/CD
&lt;/h2&gt;

&lt;p&gt;Evaluation isn't a one-time exercise — it's continuous monitoring. Code evolves and the knowledge base updates with it. After each incremental update, running a quick evaluation confirms that the update didn't degrade retrieval quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Minimal CI integration:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Pseudocode — not runnable as-is
# Triggered in CI pipeline (after each PR merge)
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_kb_quality_check&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="c1"&gt;# Sample 50 questions from the annotation set
&lt;/span&gt;    &lt;span class="c1"&gt;# (random sample, covering all four metric types)
&lt;/span&gt;    &lt;span class="n"&gt;questions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EVAL_DATASET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;symbol_accuracy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;semantic_recall&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;impact_completeness&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;history_hit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;questions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;query_knowledge_base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metric_type&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;scores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;

    &lt;span class="c1"&gt;# Alert thresholds
&lt;/span&gt;    &lt;span class="n"&gt;THRESHOLDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;symbol_accuracy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;semantic_recall&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;impact_completeness&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;history_hit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.65&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;THRESHOLDS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Knowledge base quality degraded: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;metric&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;scores&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach only requires maintaining an annotation dataset (50-200 questions is enough). CI runtime is roughly 5-15 minutes — acceptable overhead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to rebuild the annotation dataset:&lt;/strong&gt; Large-scale refactors can invalidate old annotation sets if target functions were renamed or moved. Good practice is to record each function's git hash in the annotation set. If a target function no longer exists in the new version, automatically mark that question as 'stale' — it needs human update.&lt;/p&gt;




&lt;h2&gt;
  
  
  Series Retrospective: What Thirteen Articles Covered
&lt;/h2&gt;

&lt;p&gt;A complete review at the final article.&lt;/p&gt;

&lt;p&gt;This series began with one concrete question: &lt;strong&gt;how can engineers build a retrievable knowledge system for a large codebase?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Part 1 (Theory and Tools): Articles 01-02&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Established two foundational understandings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The core value of a codebase knowledge base isn't 'code generation' — it's 'code understanding': answering 'where is this,' 'what does it affect,' 'why is it this way'&lt;/li&gt;
&lt;li&gt;Capability boundaries of existing tools: plain-text embedding, AST analysis, and knowledge graphs each have strengths, and each alone has blind spots&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Part 2 (Core Technology): Articles 03-08&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Conclusions driven by experimental data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Article 03: AST function-level chunking Recall@5 = 0.958 — the ceiling for the vector-only path&lt;/li&gt;
&lt;li&gt;Article 04: Four chunking strategies (F/R/V/P) — chunking granularity directly determines retrieval quality&lt;/li&gt;
&lt;li&gt;Article 05: Graph and vector paths are not substitutes — Q8 (cross-file structural questions) proved the graph path is irreplaceable&lt;/li&gt;
&lt;li&gt;Articles 06-07: Structural embeddings and hybrid search are marginal improvements; the core problem is 'routing to the wrong path,' not 'the path isn't strong enough'&lt;/li&gt;
&lt;li&gt;Article 08: Three-path architecture — vector/graph/symbol as orthogonal paths, routed by query intent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Part 3 (Engineering Practice): Articles 09-13&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;From lab to production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Article 09: &lt;code&gt;codebase-memory-mcp&lt;/code&gt; three-path practice on a real project (LightRAG, 20,674 nodes)&lt;/li&gt;
&lt;li&gt;Article 10: Incremental update three-tier decision tree — 80% of commits can be skipped at tier one&lt;/li&gt;
&lt;li&gt;Article 11: Cross-repo analysis — 0 edges is a meaningful answer; LightRAG × graphrag = parallel alternatives&lt;/li&gt;
&lt;li&gt;Article 12: Git history is the fourth path — 465 FILE_CHANGES_WITH edges reveal implicit coupling&lt;/li&gt;
&lt;li&gt;Article 13: Evaluation framework — four-dimensional metrics, dataset construction, CI monitoring&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The thread that runs through all thirteen:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This series has been making the same point throughout — &lt;strong&gt;code understanding is multi-dimensional, and no single signal covers all question types.&lt;/strong&gt; The vector path is strong when vocabulary matches, the graph path is irreplaceable for structural traversal, the symbol path is unambiguous for precise location, and the history path is unique for understanding evolutionary context.&lt;/p&gt;

&lt;p&gt;A good codebase knowledge base doesn't pick the strongest single path — it maps out each path's capability boundary clearly, then routes by question type.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The Codebase Knowledge Base series ends here.&lt;/p&gt;

&lt;p&gt;Thirteen articles covered the full engineering lifecycle: from theory to tooling, from experiments to production, from single-repo to cross-repo, from building to maintaining.&lt;/p&gt;

&lt;p&gt;If there's one sentence that captures the core conclusion of the whole series:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The quality of a codebase knowledge base depends not on how powerful the embedding model or how large the graph is — it depends on whether each path's capability boundaries are clearly understood, and whether the routing logic is correct.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Four retrieval paths, a three-tier decision tree, four-dimensional evaluation — none of this is complex engineering. It's what naturally emerges when you think clearly about the structure of the 'code understanding' problem.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Check out &lt;a href="https://primeskills.store" rel="noopener noreferrer"&gt;PrimeSkills&lt;/a&gt; — a curated marketplace of AI agents and skills that have been validated in real-world, enterprise-grade workflows. No fluff, just what actually works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Find more useful knowledge and interesting products on my &lt;a href="https://home.wonlab.top/en" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>evaluation</category>
      <category>knowledgebase</category>
      <category>engineering</category>
    </item>
    <item>
      <title>Open Source Project #147: Ontology Playground — Microsoft's Zero-Backend Visual Ontology Learning Tool</title>
      <dc:creator>WonderLab</dc:creator>
      <pubDate>Tue, 11 Aug 2026 02:29:42 +0000</pubDate>
      <link>https://dev.to/wonderlab/open-source-project-147-ontology-playground-microsofts-zero-backend-visual-ontology-learning-3f47</link>
      <guid>https://dev.to/wonderlab/open-source-project-147-ontology-playground-microsofts-zero-backend-visual-ontology-learning-3f47</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"Ontology is the map that lets AI understand what your business actually means. Building that map has always required fighting with dense standards and steep tooling."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is &lt;strong&gt;article #147&lt;/strong&gt; in the "One Open Source Project a Day" series. Today's project is &lt;strong&gt;Ontology Playground&lt;/strong&gt; — Microsoft's open-source zero-backend web tool for learning and designing ontologies, with a specific focus on Microsoft Fabric IQ.&lt;/p&gt;

&lt;p&gt;Ontology appears constantly across knowledge engineering, semantic web, and enterprise AI domains, but it's notoriously hard to get started with. OWL, RDF, class hierarchies, property constraints — layers of standards and terminology that stay abstract without hands-on tooling. Ontology Playground converts those abstractions into clickable, draggable, live-preview visual graphs, paired with structured courses that go from fundamentals to working domain ontologies.&lt;/p&gt;

&lt;p&gt;Zero backend. Zero server. Opens in any browser. 2,300 Stars. MIT license.&lt;/p&gt;

&lt;h3&gt;
  
  
  What You'll Learn
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;What ontology is and how it relates to knowledge graphs&lt;/li&gt;
&lt;li&gt;What Microsoft Fabric IQ does, and the role ontology plays in it&lt;/li&gt;
&lt;li&gt;Four core features: catalogue, designer, school, embeddable widget&lt;/li&gt;
&lt;li&gt;How to export ontologies in RDF/OWL format for Fabric IQ&lt;/li&gt;
&lt;li&gt;The embeddable widget: interactive ontology diagrams on any webpage with one line of HTML&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge graph concepts (nodes, edges, relationships)&lt;/li&gt;
&lt;li&gt;Familiarity with data modeling thinking (entities, attributes, relationships)&lt;/li&gt;
&lt;li&gt;No prior RDF/OWL experience needed — that's exactly what the Playground teaches&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What Is Ontology
&lt;/h2&gt;

&lt;p&gt;In philosophy, ontology studies "what exists." In computer science, an ontology is a &lt;strong&gt;formal description of knowledge in a domain&lt;/strong&gt;: what types of entities exist, what properties they have, and what relationships connect them.&lt;/p&gt;

&lt;p&gt;A retail domain ontology might describe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Classes&lt;/strong&gt;: Product, Order, Customer, Warehouse&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Properties&lt;/strong&gt;: Product has &lt;code&gt;price&lt;/code&gt; (data property), Order &lt;code&gt;placedBy&lt;/code&gt; Customer (object property)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constraints&lt;/strong&gt;: An Order must correspond to at least one Customer
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer ──[placedBy]──→ Order ──[contains]──→ Product
   ↑                        ↑                      ↑
[Person]              [Transaction]          [StockItem]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't a database schema. It captures &lt;strong&gt;business semantics&lt;/strong&gt;: not just "these tables and columns exist," but "what these entities mean in business logic and what their relationships imply."&lt;/p&gt;

&lt;h3&gt;
  
  
  Ontology and AI
&lt;/h3&gt;

&lt;p&gt;AI systems — especially LLM-driven agents — need more than data to understand business problems. They need semantic context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Order cancellation rate dropped 5%" requires the AI to know what an "order" is, what "cancellation" means as an operation, and 5% relative to what baseline&lt;/li&gt;
&lt;li&gt;Without a semantic layer, the AI guesses or asks the user to re-explain in every conversation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the problem Microsoft Fabric IQ addresses.&lt;/p&gt;




&lt;h2&gt;
  
  
  Microsoft Fabric IQ: Semantic Foundation for Enterprise AI
&lt;/h2&gt;

&lt;p&gt;Fabric IQ is the semantic layer in the Microsoft Fabric data platform. It links raw data lake content to business ontologies so AI agents can understand business meaning when querying data — not just execute SQL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without Fabric IQ:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI Agent: "Show me high-value customer orders from the last 30 days"
→ AI needs to understand what "high-value customer" means
  (Is there a threshold? A customer tier table?)
→ Guesses or asks the user to explain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With Fabric IQ + ontology:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI Agent: "Show me high-value customer orders from the last 30 days"
→ Queries the ontology: CustomerTier.HIGH_VALUE defined as annual spend &amp;gt; $10,000
→ Generates the correct query directly, no user explanation required
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ontology Playground is the tool for learning how to design and export ontologies for Fabric IQ.&lt;/p&gt;




&lt;h2&gt;
  
  
  Core Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Ontology Catalogue
&lt;/h3&gt;

&lt;p&gt;Six industry domains, pre-built and ready to explore:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Domain&lt;/th&gt;
&lt;th&gt;Ontology&lt;/th&gt;
&lt;th&gt;Entities&lt;/th&gt;
&lt;th&gt;Relationships&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Retail&lt;/td&gt;
&lt;td&gt;Fourth Coffee&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E-Commerce&lt;/td&gt;
&lt;td&gt;Online Retail&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Healthcare&lt;/td&gt;
&lt;td&gt;Clinical System&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Finance&lt;/td&gt;
&lt;td&gt;Banking &amp;amp; Finance&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manufacturing&lt;/td&gt;
&lt;td&gt;Industry 4.0&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Education&lt;/td&gt;
&lt;td&gt;University System&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each ontology has a shareable deep-link URL. Open one and you get an interactive graph — click nodes to inspect properties, follow edges to explore relationships.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Visual Designer
&lt;/h3&gt;

&lt;p&gt;Drag-and-drop design interface:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node operations&lt;/strong&gt;: add classes, set names, add data properties (field + type)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Relationship operations&lt;/strong&gt;: drag connections to create object properties, set relationship names and cardinality constraints&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live validation&lt;/strong&gt;: structural errors shown in real time as you design&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Undo/redo&lt;/strong&gt;: 50 history levels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Five domain starter templates&lt;/strong&gt;: avoid blank-canvas paralysis — pick the closest template and modify&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Export to RDF/XML (&lt;code&gt;.rdf&lt;/code&gt; or &lt;code&gt;.owl&lt;/code&gt;) in exactly the format Microsoft Fabric IQ expects. Round-trip fidelity is verified by automated tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Ontology School: Nine Structured Courses
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Fundamentals track (6 articles):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What ontology is and why enterprises need it&lt;/li&gt;
&lt;li&gt;RDF and OWL standards introduction&lt;/li&gt;
&lt;li&gt;Microsoft Fabric IQ overview&lt;/li&gt;
&lt;li&gt;Ontology design patterns&lt;/li&gt;
&lt;li&gt;From data model to ontology&lt;/li&gt;
&lt;li&gt;Hands-on lab: 15-entity retail ontology from scratch&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Seven domain learning paths:&lt;/strong&gt; Four progressive articles each, from concepts to hands-on practice, with live embedded graphs in every article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interactive features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Presentation/slides mode for every article (classroom-ready)&lt;/li&gt;
&lt;li&gt;Multiple-choice quizzes with immediate feedback embedded throughout&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Embeddable Widget
&lt;/h3&gt;

&lt;p&gt;One line of HTML puts an interactive ontology graph on any webpage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Embed the Healthcare ontology from the catalogue --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script
  &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://microsoft.github.io/Ontology-Playground/widget.js"&lt;/span&gt;
  &lt;span class="na"&gt;data-ontology-id=&lt;/span&gt;&lt;span class="s"&gt;"healthcare-clinical"&lt;/span&gt;
  &lt;span class="na"&gt;data-theme=&lt;/span&gt;&lt;span class="s"&gt;"dark"&lt;/span&gt;
&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Widget options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;data-theme&lt;/code&gt;: &lt;code&gt;dark&lt;/code&gt; or &lt;code&gt;light&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-ontology-id&lt;/code&gt;: catalogue item ID&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-ontology-url&lt;/code&gt;: external RDF file URL&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data-ontology-b64&lt;/code&gt;: base64-encoded inline RDF&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Useful for embedding ontology diagrams into documentation, blog posts, or internal wikis.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;p&gt;The entire application is pure static — zero server, zero backend:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Framework&lt;/td&gt;
&lt;td&gt;React 19 + TypeScript 5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graph rendering&lt;/td&gt;
&lt;td&gt;Cytoscape.js (fcose layout)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;State management&lt;/td&gt;
&lt;td&gt;Zustand&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build tool&lt;/td&gt;
&lt;td&gt;Vite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Animation&lt;/td&gt;
&lt;td&gt;Framer Motion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Markdown&lt;/td&gt;
&lt;td&gt;marked (build-time)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;RDF handling&lt;/strong&gt;: a custom parser and serializer with full round-trip fidelity for OWL classes, datatype properties, object properties, and cardinality constraints.&lt;/p&gt;




&lt;h2&gt;
  
  
  Deployment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  GitHub Pages (Simplest)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Fork the repository&lt;/span&gt;
&lt;span class="c"&gt;# Go to Settings &amp;gt; Pages &amp;gt; enable GitHub Actions deployment&lt;/span&gt;
&lt;span class="c"&gt;# Every push to main deploys automatically&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Azure Static Web Apps
&lt;/h3&gt;

&lt;p&gt;A GitHub Actions workflow is already configured in the repo. Connect your Azure SWA resource to the GitHub repository and it deploys on push.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local Development
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/microsoft/Ontology-Playground
&lt;span class="nb"&gt;cd &lt;/span&gt;Ontology-Playground
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;span class="c"&gt;# Open http://localhost:5173&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Optional: AI Ontology Builder
&lt;/h2&gt;

&lt;p&gt;Enable via environment variable (requires Azure OpenAI):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VITE_ENABLE_AI_BUILDER=true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this on, describe a business domain in natural language and the AI drafts an initial ontology structure. Then refine it in the visual designer.&lt;/p&gt;




&lt;h2&gt;
  
  
  One-Click Catalogue Contributions
&lt;/h2&gt;

&lt;p&gt;GitHub device-flow sign-in unlocks a "submit to catalogue" flow: the app forks the repo, creates a branch, commits your RDF file and metadata, and opens a pull request — all automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🌟 &lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/microsoft/Ontology-Playground" rel="noopener noreferrer"&gt;microsoft/Ontology-Playground&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Live Demo&lt;/strong&gt;: &lt;a href="https://microsoft.github.io/Ontology-Playground" rel="noopener noreferrer"&gt;microsoft.github.io/Ontology-Playground&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📖 &lt;strong&gt;Microsoft Fabric IQ&lt;/strong&gt;: &lt;a href="https://learn.microsoft.com/fabric" rel="noopener noreferrer"&gt;Microsoft Fabric documentation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Ontology Playground solves a specific onboarding friction: ontology concepts aren't intrinsically hard, but the lack of immediately usable hands-on tooling has always been the real barrier. RDF/OWL specification documents are dense. Professional ontology editors like Protégé are complete but steep. Opening a browser, dragging out a retail ontology in five minutes, and exporting valid RDF — that difference matters significantly for learners.&lt;/p&gt;

&lt;p&gt;The broader context: as AI agents deploy deeper into enterprise settings, "how do we make AI correctly understand business semantics" becomes a genuine engineering problem, not a theoretical one. Fabric IQ is Microsoft's architectural answer. Ontology Playground is the learning path to getting there.&lt;/p&gt;

&lt;p&gt;If you're building on Microsoft Fabric for enterprise data, or if you're interested in semantic web and knowledge graphs but unsure where to start, this is worth an afternoon.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Explore &lt;a href="https://primeskills.store" rel="noopener noreferrer"&gt;PrimeSkills&lt;/a&gt; — A marketplace for handpicked AI Agents and skills. Each is validated in real enterprise workflows, stripping away hype and keeping only what truly works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Welcome to my &lt;a href="https://home.wonlab.top/en" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt; for more useful insights and interesting products.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ontology</category>
      <category>opensource</category>
      <category>knowledge</category>
      <category>microsoft</category>
    </item>
    <item>
      <title>Open Source Project #146: Graphify — Turn Your Entire Codebase into a Queryable Knowledge Graph for AI Coding Assistants</title>
      <dc:creator>WonderLab</dc:creator>
      <pubDate>Mon, 10 Aug 2026 08:23:39 +0000</pubDate>
      <link>https://dev.to/wonderlab/open-source-project-146-graphify-turn-your-entire-codebase-into-a-queryable-knowledge-graph-for-2k1o</link>
      <guid>https://dev.to/wonderlab/open-source-project-146-graphify-turn-your-entire-codebase-into-a-queryable-knowledge-graph-for-2k1o</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"AI coding assistants struggle to understand large codebases because they're grepping, not traversing. They find keywords, not relationships."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is &lt;strong&gt;article #146&lt;/strong&gt; in the "One Open Source Project a Day" series. Today's project is &lt;strong&gt;Graphify&lt;/strong&gt; — a Y Combinator-backed open-source tool that builds your entire project (code, docs, PDFs, images, video) into a queryable knowledge graph and serves it as a context layer for AI coding assistants.&lt;/p&gt;

&lt;p&gt;Ask Claude Code or Cursor to explain how the auth module connects to the database, and you might get an accurate answer or you might get a plausible-sounding answer assembled from a handful of keyword-matched files that missed the critical middle layers. The root issue: AI assistants rely on keyword search and vector similarity to "understand" codebases. Neither approach captures actual structural relationships. Graphify replaces both: every function, class, module, and document becomes a node with explicit typed edges — and the AI traverses the graph to build context instead of guessing.&lt;/p&gt;

&lt;p&gt;73,000 Stars in 2.5 months, 2.2M downloads, now at 101k Stars. Apache-2.0 + MIT.&lt;/p&gt;

&lt;h3&gt;
  
  
  What You'll Learn
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The core difference between Graphify and RAG: graph traversal vs. vector similarity&lt;/li&gt;
&lt;li&gt;tree-sitter AST local parsing: zero API calls for code analysis, nothing leaves your machine&lt;/li&gt;
&lt;li&gt;Edge provenance: EXTRACTED / INFERRED / AMBIGUOUS tagging on every relationship&lt;/li&gt;
&lt;li&gt;God Nodes: automatic high-impact node identification, blast radius visualization&lt;/li&gt;
&lt;li&gt;Incremental updates: 3-file change patches in ~0.8 seconds, no full rebuild&lt;/li&gt;
&lt;li&gt;One-command install and usage in Claude Code&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Experience with Claude Code, Cursor, or a similar AI coding tool&lt;/li&gt;
&lt;li&gt;Basic familiarity with knowledge graph concepts (nodes, edges, relationships)&lt;/li&gt;
&lt;li&gt;Basic Python environment comfort&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Background: The "Project Blindness" Problem
&lt;/h2&gt;

&lt;p&gt;A 500-file codebase. You ask Claude Code: "How does the auth module connect to the database?"&lt;/p&gt;

&lt;p&gt;Its processing looks roughly like:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search context for "auth"-related files&lt;/li&gt;
&lt;li&gt;Pull several matching file contents into context&lt;/li&gt;
&lt;li&gt;Generate an answer from those fragments&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The problem is step 1. The search runs on keywords or vector similarity — &lt;strong&gt;not on the actual structural relationships in the code&lt;/strong&gt;. It might:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Find three files containing the string "auth" but miss the critical middleware layer&lt;/li&gt;
&lt;li&gt;Locate &lt;code&gt;auth.py&lt;/code&gt; and &lt;code&gt;db.py&lt;/code&gt; but not trace the call chain connecting them&lt;/li&gt;
&lt;li&gt;Return a different answer if you ask the same question again&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't a model capability problem. It's a context construction problem.&lt;/p&gt;

&lt;p&gt;Graphify's approach: before you ask anything, parse the entire codebase into a graph. Every function, class, module, and document is a node. Call relationships, import chains, and inheritance are typed directed edges. The AI assistant queries this graph to build context instead of grepping.&lt;/p&gt;




&lt;h2&gt;
  
  
  Core Architecture: Local AST + Optional LLM
&lt;/h2&gt;

&lt;p&gt;Graphify splits project content into two categories and handles each differently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Code files
    → tree-sitter AST local parsing
    → Zero API calls, nothing leaves the machine
    → Extracts function/class/module nodes + calls/imports/inherits edges

Docs / PDFs / images / video
    → Configured LLM backend (Anthropic / OpenAI / Gemini / Ollama / etc.)
    → Extracts semantic nodes and relationships

            ↓
    Unified knowledge graph

Output files:
├── graph.html       ← Interactive browser visualization
├── GRAPH_REPORT.md  ← Human-readable highlights and suggested questions
└── graph.json       ← Full queryable graph data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  tree-sitter: Deterministic Code Parsing
&lt;/h3&gt;

&lt;p&gt;tree-sitter is the industry-standard incremental AST parser used by Neovim, GitHub, and many other tools. Graphify uses it to parse code structure rather than asking an LLM to infer it.&lt;/p&gt;

&lt;p&gt;The benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic&lt;/strong&gt;: same code always produces the same parse result&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero API cost&lt;/strong&gt;: code parsing is fully local, no LLM calls&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast&lt;/strong&gt;: AST parsing runs orders of magnitude faster than LLM inference&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private&lt;/strong&gt;: code never leaves the machine&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Supports &lt;strong&gt;36+ programming languages&lt;/strong&gt;: Python, TypeScript/JavaScript, Go, Rust, Java, C/C++, Ruby, C#, Kotlin, Swift, Scala, PHP, Lua, Zig, SQL, and more.&lt;/p&gt;




&lt;h2&gt;
  
  
  Edge Provenance
&lt;/h2&gt;

&lt;p&gt;This is one of Graphify's most distinctive design decisions. Every edge in the graph carries a source tag:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tag&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EXTRACTED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Derived directly from code structure, deterministic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INFERRED&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Derived from LLM reasoning, some uncertainty&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AMBIGUOUS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Origin unclear, worth human verification&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why it matters&lt;/strong&gt;: when an AI assistant traverses graph paths to answer a question, it knows which relationships are "hard facts from the code" versus "model inferences." That directly affects how confidently the answer should be stated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User asks: "How does the login function trigger a database write?"

AI traverses the graph and finds the path:
login() --[EXTRACTED: calls]--&amp;gt; validate_user()
validate_user() --[EXTRACTED: calls]--&amp;gt; db.query()
db.query() --[INFERRED: writes_to]--&amp;gt; users_table

The answer can explicitly note: the first two hops are code-confirmed;
the final hop is inferred.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  God Nodes: Identifying High-Risk Points
&lt;/h2&gt;

&lt;p&gt;Graphify automatically computes &lt;strong&gt;betweenness centrality&lt;/strong&gt; across the graph to identify "God Nodes" — the files or functions that sit on the most paths between other nodes.&lt;/p&gt;

&lt;p&gt;In a real codebase, God Nodes are typically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A utility function imported by 20 different modules&lt;/li&gt;
&lt;li&gt;The API layer file that bridges frontend and backend&lt;/li&gt;
&lt;li&gt;A single service class holding all database connection logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These nodes share one property: &lt;strong&gt;a bug in them has the widest blast radius&lt;/strong&gt;. Graphify's visualization highlights God Nodes prominently. When reviewing AI-generated code changes, you see immediately whether the changed file is one of these high-centrality nodes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Community Detection: Discovering Hidden Subsystem Boundaries
&lt;/h2&gt;

&lt;p&gt;Graphify runs the &lt;strong&gt;Leiden algorithm&lt;/strong&gt; on the graph to automatically cluster the codebase into functional subsystems — independent of directory structure.&lt;/p&gt;

&lt;p&gt;Why this matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;utils/&lt;/code&gt; folder might contain code that actually belongs to three different subsystems&lt;/li&gt;
&lt;li&gt;Leiden clusters from actual call and import relationships, surfacing which files genuinely work together&lt;/li&gt;
&lt;li&gt;Results appear in &lt;code&gt;graph.html&lt;/code&gt; with distinct color coding per community&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is particularly useful for architecture understanding and refactoring planning in large codebases.&lt;/p&gt;




&lt;h2&gt;
  
  
  Incremental Updates: No Full Rebuild
&lt;/h2&gt;

&lt;p&gt;A common pain with traditional RAG: when code changes, you re-embed the entire index. Hundreds of files might take minutes.&lt;/p&gt;

&lt;p&gt;Graphify patches only the changed files, leaving every other node intact.&lt;/p&gt;

&lt;p&gt;Official numbers: 500,000-node graph, 3 files changed, patch time: &lt;strong&gt;0.8 seconds&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Query Interface
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Natural language query&lt;/span&gt;
graphify query &lt;span class="s2"&gt;"how does the login form connect to the users table?"&lt;/span&gt;
&lt;span class="c"&gt;# → Returns the full path from UI through API layers to DB, with edge provenance tags&lt;/span&gt;

&lt;span class="c"&gt;# Shortest path between two nodes&lt;/span&gt;
graphify path auth.login db.users

&lt;span class="c"&gt;# Ask AI to explain a function using the graph as context&lt;/span&gt;
graphify explain src/auth/handler.py:validate_token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Supported Data Sources
&lt;/h2&gt;

&lt;p&gt;Graphify ingests the full project, not just code:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt; (local AST, zero LLM)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;36+ languages: Python, TS/JS, Go, Rust, Java, C/C++, Ruby, Kotlin, Swift, and more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Documents&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Markdown, HTML, RST, YAML, TXT&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.docx&lt;/code&gt;, &lt;code&gt;.xlsx&lt;/code&gt; (optional extra)&lt;/li&gt;
&lt;li&gt;PDF (optional extra)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Media&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Images: PNG, JPG, WebP, GIF (vision extraction)&lt;/li&gt;
&lt;li&gt;Video/audio: MP4, MOV, MP3, WAV (local transcription via faster-whisper)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Special formats&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP configuration files&lt;/li&gt;
&lt;li&gt;Package manifests: &lt;code&gt;pyproject.toml&lt;/code&gt;, &lt;code&gt;go.mod&lt;/code&gt;, &lt;code&gt;pom.xml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Google Workspace: Docs, Sheets, Slides (via &lt;code&gt;gws&lt;/code&gt; CLI)&lt;/li&gt;
&lt;li&gt;YouTube URLs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Installation and Quick Start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install CLI (uv recommended)&lt;/span&gt;
uv tool &lt;span class="nb"&gt;install &lt;/span&gt;graphifyy   &lt;span class="c"&gt;# Note: PyPI package name is graphifyy (double y)&lt;/span&gt;

&lt;span class="c"&gt;# Register skill with your AI assistant&lt;/span&gt;
graphify &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use in Claude Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# In Claude Code, run:&lt;/span&gt;
/graphify &lt;span class="nb"&gt;.&lt;/span&gt;              &lt;span class="c"&gt;# Build graph for current directory&lt;/span&gt;

&lt;span class="c"&gt;# Then ask project questions naturally —&lt;/span&gt;
&lt;span class="c"&gt;# the AI traverses the graph instead of grepping&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Output Files
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;graphify-out/
├── graph.html       ← Open &lt;span class="k"&gt;in &lt;/span&gt;browser &lt;span class="k"&gt;for &lt;/span&gt;interactive visualization
├── GRAPH_REPORT.md  ← Highlights, surprising connections, suggested questions
└── graph.json       ← Full graph data &lt;span class="k"&gt;for &lt;/span&gt;programmatic queries
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  MCP Server Mode
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start as MCP server&lt;/span&gt;
graphify mcp &lt;span class="nt"&gt;--transport&lt;/span&gt; stdio   &lt;span class="c"&gt;# stdio transport&lt;/span&gt;
graphify mcp &lt;span class="nt"&gt;--transport&lt;/span&gt; http    &lt;span class="c"&gt;# HTTP mode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any MCP-compatible AI tool can then call into your code graph directly via tool calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional Graph Database Backends
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Push to Neo4j&lt;/span&gt;
graphify push &lt;span class="nt"&gt;--backend&lt;/span&gt; neo4j &lt;span class="nt"&gt;--uri&lt;/span&gt; bolt://localhost:7687

&lt;span class="c"&gt;# FalkorDB&lt;/span&gt;
graphify push &lt;span class="nt"&gt;--backend&lt;/span&gt; falkordb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Benchmark Data
&lt;/h2&gt;

&lt;p&gt;From the official BENCHMARKS.md, compared against popular memory/RAG systems:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benchmark&lt;/th&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Graphify&lt;/th&gt;
&lt;th&gt;mem0&lt;/th&gt;
&lt;th&gt;supermemory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LOCOMO (n=300)&lt;/td&gt;
&lt;td&gt;recall@10&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.497&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.048&lt;/td&gt;
&lt;td&gt;0.149&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LOCOMO (n=300)&lt;/td&gt;
&lt;td&gt;QA accuracy&lt;/td&gt;
&lt;td&gt;45.3%&lt;/td&gt;
&lt;td&gt;27.3%&lt;/td&gt;
&lt;td&gt;49.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LongMemEval-S (n=50)&lt;/td&gt;
&lt;td&gt;QA accuracy&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;76%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graph build&lt;/td&gt;
&lt;td&gt;LLM credits&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0 (code)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;per-token&lt;/td&gt;
&lt;td&gt;per-token&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On LongMemEval-S, Graphify ties dense RAG at 76% accuracy — with zero LLM cost for the code portion of the graph.&lt;/p&gt;




&lt;h2&gt;
  
  
  Supported AI Assistants
&lt;/h2&gt;

&lt;p&gt;One command registers the skill across all:&lt;/p&gt;

&lt;p&gt;Claude Code, Cursor, Codex, Gemini CLI, GitHub Copilot, Aider, Kilo Code, OpenCode, Factory Droid, Trae, Amp, Kiro, Devin CLI, and any other skill-compatible tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🌟 &lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/Graphify-Labs/graphify" rel="noopener noreferrer"&gt;Graphify-Labs/graphify&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Website&lt;/strong&gt;: &lt;a href="https://graphify.com" rel="noopener noreferrer"&gt;graphify.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;PyPI&lt;/strong&gt;: &lt;code&gt;graphifyy&lt;/code&gt; (&lt;code&gt;pip install graphifyy&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;🏢 &lt;strong&gt;Backed by&lt;/strong&gt;: Y Combinator&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Graphify's core insight: &lt;strong&gt;context quality determines answer quality more than model capability does.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The same Claude Sonnet given a handful of grep-matched file fragments versus a traced path through actual code relationships produces noticeably different answers in depth and accuracy. Graphify builds the latter: tree-sitter extracts precise code structure, Leiden identifies subsystem boundaries, betweenness centrality surfaces risk nodes, and all of it assembles into an auditable knowledge graph where every edge carries a provenance tag.&lt;/p&gt;

&lt;p&gt;The edge provenance design (EXTRACTED vs INFERRED) deserves particular attention. In a large codebase, "is this relationship code-confirmed or model-inferred" is a question that changes what you do next. Being able to trace an AI answer back to graph paths — and knowing the confidence level of each hop — makes the difference between a useful tool and one you have to second-guess.&lt;/p&gt;

&lt;p&gt;73,000 Stars in 2.5 months is a signal that this pain point is real. The grep-and-hope approach to codebase context has been the default long enough.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Explore &lt;a href="https://primeskills.store" rel="noopener noreferrer"&gt;PrimeSkills&lt;/a&gt; — A marketplace for handpicked AI Agents and skills. Each is validated in real enterprise workflows, stripping away hype and keeping only what truly works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Welcome to my &lt;a href="https://home.wonlab.top/en" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt; for more useful insights and interesting products.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>knowledge</category>
      <category>agents</category>
      <category>ai</category>
    </item>
    <item>
      <title>Codebase Knowledge Base (12): Git History Is the Fourth Retrieval Path</title>
      <dc:creator>WonderLab</dc:creator>
      <pubDate>Mon, 10 Aug 2026 08:21:05 +0000</pubDate>
      <link>https://dev.to/wonderlab/codebase-knowledge-base-12-git-history-is-the-fourth-retrieval-path-2ja6</link>
      <guid>https://dev.to/wonderlab/codebase-knowledge-base-12-git-history-is-the-fourth-retrieval-path-2ja6</guid>
      <description>&lt;h2&gt;
  
  
  The Question That Three Paths Can't Answer
&lt;/h2&gt;

&lt;p&gt;The previous articles demonstrated three-path retrieval repeatedly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;search_graph&lt;/code&gt; (vector path): ask 'which function handles document chunking strategy,' get &lt;code&gt;QueryParam&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;trace_path&lt;/code&gt; (graph path): ask 'what is &lt;code&gt;ainsert&lt;/code&gt;'s full execution chain,' get 36 nodes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;search_code&lt;/code&gt; (symbol path): ask 'where is &lt;code&gt;BaseVectorStorage&lt;/code&gt; used,' get fan_in=268&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But there's a class of question that all three paths fail to answer:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;'Why is this code written this way?'&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;priority_limit_async_func_call&lt;/code&gt; is one of the highest-complexity functions in LightRAG (&lt;code&gt;complexity=233&lt;/code&gt;, function body spanning 1,360 lines). Looking at the current code alone, it's hard to understand why a decorator that 'limits the number of concurrent async calls' needs to be this complex.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;priority_limit_async_func_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;max_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;llm_timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_execution_timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_task_duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_queue_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;cleanup_timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;queue_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit_async&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;concurrency_group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Enhanced priority-limited asynchronous function call decorator with robust timeout handling

    This decorator provides a comprehensive solution for managing concurrent LLM requests with:
    - Multi-layer timeout protection (LLM -&amp;gt; Worker -&amp;gt; Health Check -&amp;gt; User)
    - Task state tracking to prevent race conditions
    - Enhanced health check system with stuck task detection
    - Proper resource cleanup and error recovery
    - Optional cross-process global concurrency gating (gunicorn multi-worker)
&lt;/span&gt;&lt;span class="gp"&gt;    ...&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why 'Multi-layer timeout protection'? Why 'Health check system with stuck task detection'? Why is there a &lt;code&gt;concurrency_group&lt;/code&gt; parameter for multi-process scenarios?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;trace_path&lt;/code&gt; can't answer these. Vector search can't find them either. The comments describe &lt;em&gt;what&lt;/em&gt; the code does — not &lt;em&gt;why&lt;/em&gt; it had to be done this way.&lt;/p&gt;

&lt;p&gt;The answer is in git history.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Nature of the Fourth Question Type
&lt;/h2&gt;

&lt;p&gt;Three-path retrieval covers the &lt;strong&gt;current state of the code&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;th&gt;Question answered&lt;/th&gt;
&lt;th&gt;Data source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Vector&lt;/td&gt;
&lt;td&gt;What does this do, where is this concept&lt;/td&gt;
&lt;td&gt;Semantic embeddings of current code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Graph&lt;/td&gt;
&lt;td&gt;Who calls it, what is the full execution chain&lt;/td&gt;
&lt;td&gt;AST + call graph of current code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Symbol&lt;/td&gt;
&lt;td&gt;Precise location, full blast radius&lt;/td&gt;
&lt;td&gt;Symbol index of current code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;History&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Why is it written this way, when was it added, how many times has it changed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Git commit history&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The history path isn't a supplement to the other three — it's a completely different information dimension. The current state of the code is just one cross-section of its historical evolution; to understand that cross-section, sometimes you have to see how it got there.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;codebase-memory-mcp&lt;/code&gt; encodes git history into queryable knowledge from two angles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;FILE_CHANGES_WITH edges&lt;/strong&gt;: mined from git log — 'which files are frequently modified together' — encoded as explicit relationships in the graph&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;detect_changes history patterns&lt;/strong&gt;: using the &lt;code&gt;since&lt;/code&gt; parameter to look back across any time window, tracking change frequency for any file or module&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  FILE_CHANGES_WITH: Turning Git History into Graph Edges
&lt;/h2&gt;

&lt;p&gt;LightRAG's knowledge graph has &lt;strong&gt;465 FILE_CHANGES_WITH edges&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These edges don't come from static code analysis — no Python import or function call could produce them. They're mined from git commit history: if file A and file B frequently appear in the same commit historically, a bidirectional A ↔ B edge is created in the graph.&lt;/p&gt;

&lt;p&gt;Reading through those 465 edges, three clear patterns emerge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 1: Documentation and code evolve in sync
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FileProcessingPipeline.md ↔ routing.py
FileProcessingPipeline.md ↔ parser.py
FileProcessingPipeline.md ↔ param_schema.py
FileProcessingPipeline.md ↔ test_hint_params.py

LightRAGSidecarFormat-zh.md ↔ pipeline.py
ParagraphSemanticChunking.md ↔ paragraph_semantic.py
ParagraphSemanticChunking.md ↔ test_paragraph_semantic_table_split.py
MilvusConfigurationGuide.md ↔ milvus_impl.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reveals that LightRAG's maintainers have a strong habit: &lt;strong&gt;documentation and code are updated simultaneously&lt;/strong&gt;. When &lt;code&gt;routing.py&lt;/code&gt; changes, &lt;code&gt;FileProcessingPipeline.md&lt;/code&gt; almost always changes too. When &lt;code&gt;paragraph_semantic.py&lt;/code&gt; gets a new feature, the corresponding documentation and test files update at the same time.&lt;/p&gt;

&lt;p&gt;For a codebase knowledge base, this means: when you index a change to &lt;code&gt;routing.py&lt;/code&gt;, &lt;code&gt;FileProcessingPipeline.md&lt;/code&gt; also needs to be in scope — not because they have a call relationship, but because historical evidence says they always move together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 2: Implementation and test coupling
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;backfill.py ↔ test_backfill.py
backfill.py ↔ test_sidecar_backfill_integration.py
_markdown.py ↔ test_markdown.py
anthropic.py ↔ test_anthropic_client_cleanup.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a test coverage health signal: high co-change frequency between implementation files and test files means these modules have had tests keeping pace throughout their evolution.&lt;/p&gt;

&lt;p&gt;The inverse is equally informative: if an implementation file has no FILE_CHANGES_WITH edges pointing to test files, that's worth noting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 3: Cross-module architectural coupling
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;base.py ↔ lightrag.py
addon_params.py ↔ pipeline.py
_vision_utils.py ↔ pipeline.py
azure_openai.py ↔ openai.py
anthropic.py ↔ lmdeploy.py ↔ hf.py ↔ lollms.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most interesting case here is the LLM adapter cluster: &lt;code&gt;anthropic.py&lt;/code&gt;, &lt;code&gt;lmdeploy.py&lt;/code&gt;, &lt;code&gt;hf.py&lt;/code&gt;, and &lt;code&gt;lollms.py&lt;/code&gt; have FILE_CHANGES_WITH edges connecting them to each other.&lt;/p&gt;

&lt;p&gt;From static analysis, these files have no import relationships and no direct call relationships — they're parallel LLM backend adapters, each implementing the same interface. But historically, modifying one almost always means modifying the others at the same time.&lt;/p&gt;

&lt;p&gt;This reveals an important architectural convention: &lt;strong&gt;when the LLM interface spec changes, all adapters must update in sync&lt;/strong&gt;. That rule isn't written in any comment. It only left traces in git history.&lt;/p&gt;




&lt;h2&gt;
  
  
  Using detect_changes to Trace History Windows
&lt;/h2&gt;

&lt;p&gt;Beyond FILE_CHANGES_WITH edges, the &lt;code&gt;since&lt;/code&gt; parameter of &lt;code&gt;detect_changes&lt;/code&gt; can look back across any time window of change patterns.&lt;/p&gt;

&lt;p&gt;In the incremental update article (article 10), we used &lt;code&gt;detect_changes(since="HEAD~5")&lt;/code&gt; for a live demo — 5 commits containing only README and CI changes, zero code changes, the correct answer being 'do nothing.'&lt;/p&gt;

&lt;p&gt;But &lt;code&gt;since&lt;/code&gt; has another use case: &lt;strong&gt;understanding a module's evolution history&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, running a historical window analysis on &lt;code&gt;utils.py&lt;/code&gt; (where &lt;code&gt;priority_limit_async_func_call&lt;/code&gt; lives):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;detect_changes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LightRAG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HEAD~50&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# look at the last 50 commits
&lt;/span&gt;    &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lightrag/utils.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the result shows &lt;code&gt;utils.py&lt;/code&gt; appeared in 15 of the last 50 commits — while the project has around 200 files — then &lt;code&gt;utils.py&lt;/code&gt;'s change frequency is roughly 15 times the average.&lt;/p&gt;

&lt;p&gt;This is exactly what explains why &lt;code&gt;priority_limit_async_func_call&lt;/code&gt; grew to 1,360 lines with complexity 233: it wasn't written this way in one sitting. It was &lt;strong&gt;repeatedly repaired and hardened under production load&lt;/strong&gt; — every new timeout edge case, every new concurrency bug, every new multi-process scenario added another layer of protection.&lt;/p&gt;

&lt;p&gt;The 'Multi-layer timeout protection,' 'stuck task detection,' and 'cross-process concurrency gating' in the docstring are all scars from real production incidents.&lt;/p&gt;




&lt;h2&gt;
  
  
  Four Uses for the History Path in Practice
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use 1: Understanding 'why so complex'
&lt;/h3&gt;

&lt;p&gt;When you encounter a high-complexity function, the history path distinguishes two very different situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Case A&lt;/strong&gt;: The function grew from 100 to 1,000 lines in a single commit — that's a large refactor or feature expansion, and there's usually a complete commit message explaining why&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Case B&lt;/strong&gt;: The function slowly ballooned across dozens of commits, gaining a few dozen lines each time — it's been continuously patching production issues, and each chunk of new code is a hotfix&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;priority_limit_async_func_call&lt;/code&gt; is Case B: 1,360 lines of function body, reflecting every concurrency problem LightRAG has encountered under high-load LLM calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use 2: Finding 'implicit coupling' relationships
&lt;/h3&gt;

&lt;p&gt;Static analysis can surface call relationships (A calls B), inheritance (A extends B), and import relationships (A imports B). But there's one type of relationship it can't extract from current code: &lt;strong&gt;A and B must be modified in sync, or the system breaks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The LLM adapter cluster is the canonical example: &lt;code&gt;anthropic.py&lt;/code&gt; and &lt;code&gt;openai.py&lt;/code&gt; don't call each other, but if you change the interface spec and update only &lt;code&gt;openai.py&lt;/code&gt; while forgetting &lt;code&gt;anthropic.py&lt;/code&gt;, something will break.&lt;/p&gt;

&lt;p&gt;FILE_CHANGES_WITH edges make this 'implicit coupling' into a queryable graph relationship.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use 3: Assessing change risk
&lt;/h3&gt;

&lt;p&gt;When a function is being modified, its historical change frequency is a proxy for risk:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High-frequency changes&lt;/strong&gt; = this area has been historically unstable, modifications are likely to introduce bugs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low-frequency changes&lt;/strong&gt; = this area has been stable, changes are relatively lower risk&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never changed&lt;/strong&gt; = either extremely stable foundational code, or long-neglected dead code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Combining &lt;code&gt;complexity&lt;/code&gt; (current state) with historical change frequency builds a two-dimensional risk matrix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                  Low complexity     High complexity
High change freq  [Watch carefully]  [High risk, full analysis required]
Low change freq   [Relatively safe]  [May be stable complex logic]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use 4: Detecting documentation-code sync gaps
&lt;/h3&gt;

&lt;p&gt;The docs↔code FILE_CHANGES_WITH edges effectively define which documentation should stay in sync with which code.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MilvusConfigurationGuide.md ↔ milvus_impl.py&lt;/code&gt; means: every time &lt;code&gt;milvus_impl.py&lt;/code&gt; has an interface change, &lt;code&gt;MilvusConfigurationGuide.md&lt;/code&gt; should update too. If a diff changes &lt;code&gt;milvus_impl.py&lt;/code&gt; without touching the corresponding documentation — that's an automatically detectable problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Complete Four-Path Picture
&lt;/h2&gt;

&lt;p&gt;With the history path added, the full codebase knowledge base looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Question type                         Path           Core tool
────────────────────────────────────────────────────────────────────
'Where is this feature implemented?'  Vector         search_graph(query=...)
'Who calls it, what's the blast rad?' Graph          trace_path(mode=calls)
'Precise location, all callers'       Symbol         search_code(pattern)
'Why written this way, when added'    History        FILE_CHANGES_WITH + detect_changes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These four paths aren't competing — they're &lt;strong&gt;complementary dimensions&lt;/strong&gt;. An engineer trying to understand unfamiliar code typically needs all four running in parallel: the vector path to find the entry point ('what is this'), the graph path to trace the structure ('how does it work'), the symbol path to confirm scope ('what does changing it touch'), and the history path to understand the context ('why is it this way').&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Git history isn't an optional add-on for a codebase knowledge base — it's the fourth dimension of code understanding, without which the picture is incomplete.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;codebase-memory-mcp&lt;/code&gt; encodes historical knowledge into the graph two ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;FILE_CHANGES_WITH edges&lt;/strong&gt;: mined from commit history, making 'these files always change together' into queryable graph relationships&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;detect_changes historical lookback&lt;/strong&gt;: scanning any time window via the &lt;code&gt;since&lt;/code&gt; parameter, quantifying change frequency, explaining why some areas are more complex than others&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;LightRAG's 465 FILE_CHANGES_WITH edges reveal three patterns: docs↔code synchronization conventions, impl↔test coverage signals, and cross-adapter interface contracts. Each pattern answers a class of 'why' questions — the kind of answer that static code analysis can never provide.&lt;/p&gt;

&lt;p&gt;Next article (the final one): we step back and ask how to evaluate whether a codebase knowledge base is 'good enough' — what metrics matter, how to design evaluation datasets, and what production systems should track when Recall@5 is no longer the only number that counts.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Check out &lt;a href="https://primeskills.store" rel="noopener noreferrer"&gt;PrimeSkills&lt;/a&gt; — a curated marketplace of AI agents and skills that have been validated in real-world, enterprise-grade workflows. No fluff, just what actually works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Find more useful knowledge and interesting products on my &lt;a href="https://home.wonlab.top/en" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>codebase</category>
      <category>codegraph</category>
    </item>
    <item>
      <title>Codebase Knowledge Base (11): Cross-Repo Scenarios — When One Service Calls Another</title>
      <dc:creator>WonderLab</dc:creator>
      <pubDate>Sun, 09 Aug 2026 03:12:27 +0000</pubDate>
      <link>https://dev.to/wonderlab/codebase-knowledge-base-11-cross-repo-scenarios-when-one-service-calls-another-456d</link>
      <guid>https://dev.to/wonderlab/codebase-knowledge-base-11-cross-repo-scenarios-when-one-service-calls-another-456d</guid>
      <description>&lt;h2&gt;
  
  
  An Experiment That Returned Zero
&lt;/h2&gt;

&lt;p&gt;Running &lt;code&gt;cross-repo-intelligence&lt;/code&gt; across LightRAG and graphrag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;index_repository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;repo_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/path/to/LightRAG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cross-repo-intelligence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;target_projects&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mnt-hdd-...-graphrag&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;success&lt;/span&gt;
&lt;span class="na"&gt;cross_http_calls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="na"&gt;cross_async_calls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="na"&gt;cross_channel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="na"&gt;cross_grpc_calls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="na"&gt;total_cross_edges&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="na"&gt;elapsed_ms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;109&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Zero cross-repo edges.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first instinct is 'the tool found nothing — something failed.' That's wrong. &lt;strong&gt;This result is entirely correct, and it's highly informative.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;LightRAG and graphrag are two open-source frameworks that do similar things — both graph-based RAG — but they are parallel alternatives, not an integrated system. No LightRAG code calls graphrag's API, and vice versa. &lt;code&gt;cross-repo-intelligence&lt;/code&gt; finds &lt;strong&gt;integration relationships&lt;/strong&gt;, not &lt;strong&gt;functional similarity&lt;/strong&gt;. There was never an integration relationship between them; returning 0 is the right answer.&lt;/p&gt;

&lt;p&gt;This matters because it draws a clear boundary: &lt;strong&gt;cross-repo analysis solves a completely different class of problem than single-repo analysis.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Single-Repo vs Cross-Repo: Two Different Problems
&lt;/h2&gt;

&lt;p&gt;Looking back at the first ten articles, all the questions a single-repo knowledge base can answer live within one repository boundary:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'Where is this function?' (symbol path)&lt;/li&gt;
&lt;li&gt;'Who calls it?' (graph path, inbound)&lt;/li&gt;
&lt;li&gt;'What does it call?' (graph path, outbound)&lt;/li&gt;
&lt;li&gt;'Which functions frequently change together?' (FILE_CHANGES_WITH)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These answers are all in the same codebase. The call graph is complete. BFS from any node works.&lt;/p&gt;

&lt;p&gt;But when system scope expands across multiple repositories, a class of questions appears that single-repo analysis &lt;strong&gt;physically cannot answer&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'Which interfaces of Service B does Service A call?'&lt;/li&gt;
&lt;li&gt;'If I modify Service B's &lt;code&gt;/query&lt;/code&gt; endpoint, which upstream services are affected?'&lt;/li&gt;
&lt;li&gt;'Service C changed the message format it sends to Service D via message queue — can D detect this?'&lt;/li&gt;
&lt;li&gt;'In the entire microservice network, who are the central nodes, who are the islands?'&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These answers span repository boundaries. A single-repo call graph stops dead at the service boundary — the graph becomes a map with 'dangling terminal nodes' that call some external URL, but don't know who handles that URL.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cross-repo-intelligence&lt;/code&gt; connects those dangling nodes.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Cross-Repo Edges Are Discovered
&lt;/h2&gt;

&lt;p&gt;The core logic of &lt;code&gt;cross-repo-intelligence&lt;/code&gt; mode: &lt;strong&gt;match Route nodes against HTTP_CALLS nodes across indexed projects.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Concretely:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Discover server-side routes&lt;/strong&gt;: Scan all indexed projects for &lt;code&gt;Route&lt;/code&gt; nodes (HTTP endpoint definitions). Build a &lt;code&gt;path → project&lt;/code&gt; routing table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Discover client-side calls&lt;/strong&gt;: Scan &lt;code&gt;HTTP_CALLS&lt;/code&gt; edges (HTTP requests in the code). Extract the target URLs or path patterns.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Path matching&lt;/strong&gt;: For each &lt;code&gt;HTTP_CALLS&lt;/code&gt; edge, look for a matching &lt;code&gt;Route&lt;/code&gt; in other projects. When found, create a &lt;code&gt;CROSS_HTTP_CALLS&lt;/code&gt; edge that crosses the repository boundary, connecting the caller to the callee.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The same logic applies to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CROSS_ASYNC_CALLS&lt;/code&gt;: message queues (Kafka topic names, RabbitMQ exchanges, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CROSS_GRPC_CALLS&lt;/code&gt;: gRPC service/method names&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CROSS_CHANNEL&lt;/code&gt;: other named channels (WebSocket channels, Redis pub/sub keys)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This explains why LightRAG × graphrag returns 0: no LightRAG code sends HTTP requests to graphrag's routes, and graphrag doesn't call LightRAG's API. The tool didn't fail — it correctly reported that there is no integration relationship between these two systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Each System's Route Profile Actually Looks Like
&lt;/h2&gt;

&lt;p&gt;Even without cross-repo edges, examining each system's routes reveals their roles immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LightRAG: REST API server&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route nodes (lightrag/api/routers/):
  GET  /query
  POST /query
  GET  /query/stream
  POST /query/stream
  GET  /health
  POST /login
  GET  /auth-status
  GET  /graph/label/list
  POST /documents/paginated
  ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LightRAG exposes a full HTTP service interface — document management, querying, graph browsing, health checks. From the cross-repo perspective, it's a &lt;strong&gt;callee&lt;/strong&gt;: if another service sends requests to &lt;code&gt;http://lightrag-host/query&lt;/code&gt;, that request becomes one end of a cross-repo edge.&lt;/p&gt;

&lt;p&gt;The corresponding code structure: &lt;code&gt;create_query_routes&lt;/code&gt; and &lt;code&gt;create_document_routes&lt;/code&gt; are massive route registration functions (1,566 lines, complexity 118, cognitive complexity 266) — among the hardest functions in the project, because they handle all the HTTP boundary cases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;graphrag: LLM client&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route nodes (graphrag/):
  PATCH  /            (API root — to LiteLLM)
  external: https://litellm.ai
  external: https://raw.githubusercontent.com/.../cspell.schema.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;graphrag isn't a service — it's a &lt;strong&gt;command-line tool + Python SDK&lt;/strong&gt;. Its 'routes' are HTTP calls it makes to external LLM services (LiteLLM) and GitHub, not endpoints it exposes. From the cross-repo perspective, it's a &lt;strong&gt;pure caller&lt;/strong&gt; — if you deploy both graphrag and LightRAG in the same system, graphrag might call LiteLLM (creating CROSS_HTTP_CALLS edges), but graphrag won't call LightRAG and LightRAG won't call graphrag.&lt;/p&gt;

&lt;p&gt;This role difference is immediately visible from the route profile: one has real REST API routes, the other only has outbound HTTP client calls.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Cross-Repo Analysis Has Real Engineering Value
&lt;/h2&gt;

&lt;p&gt;If LightRAG × graphrag has no cross-repo edges, what kind of system does?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A typical microservice architecture:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frontend App
  └─ CROSS_HTTP_CALLS → API Gateway (gateway-service)
                              └─ CROSS_HTTP_CALLS → User Service
                              └─ CROSS_HTTP_CALLS → Auth Service
                              └─ CROSS_HTTP_CALLS → Order Service
                                    └─ CROSS_ASYNC_CALLS → Kafka: order.created
                                                                └─ CROSS_ASYNC_CALLS → Notification Service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this architecture, if &lt;code&gt;User Service&lt;/code&gt;'s &lt;code&gt;GET /users/{id}&lt;/code&gt; interface is being modified (say, a returned field is being removed), cross-repo analysis tells you which services have &lt;code&gt;CROSS_HTTP_CALLS&lt;/code&gt; edges pointing to that route — and need to be updated in sync. Pure single-repo analysis can't answer this at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;cross_service&lt;/code&gt; mode &lt;code&gt;trace_path&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;trace_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;function_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get_user_by_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user-service&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cross_service&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This call follows &lt;code&gt;HTTP_CALLS → CROSS_HTTP_CALLS → Route&lt;/code&gt; edges across service boundaries, returning the full cross-service call chain — from some frontend handler all the way down to a database query in User Service.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three Practical Cross-Repo Use Cases
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use case 1: Service dependency map&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After indexing all microservice projects, query the cross-repo call graph:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="py"&gt;r:&lt;/span&gt;&lt;span class="n"&gt;CROSS_HTTP_CALLS&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;a.file_path&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r.path&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b.file_path&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is the entire system's service dependency map. Which services are 'hubs' (called by many others), which are 'islands' (no cross-repo calls), whether there are circular dependencies — one query surfaces all of it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case 2: Interface change impact assessment&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 1. Find the interface definition
&lt;/span&gt;&lt;span class="nf"&gt;search_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET /api/v2/payments&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payment-service&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 2. Find cross-repo callers
&lt;/span&gt;&lt;span class="nf"&gt;trace_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get_payment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cross_service&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;direction&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;inbound&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="nb"&gt;all&lt;/span&gt; &lt;span class="n"&gt;upstream&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;CROSS_HTTP_CALLS&lt;/span&gt; &lt;span class="n"&gt;edges&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before modifying &lt;code&gt;/api/v2/payments&lt;/code&gt;, know which services depend on it. Without cross-repo analysis, this requires manually grep-ing that URL across every repository in the organization — a process with frequent misses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case 3: Message contract tracing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If services communicate via Kafka:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;producer&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="py"&gt;r:&lt;/span&gt;&lt;span class="n"&gt;CROSS_ASYNC_CALLS&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;r.channel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"order.completed"&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;producer.file_path&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;consumer.file_path&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find all producers and consumers of the &lt;code&gt;order.completed&lt;/code&gt; message. When the message schema needs to change, the full blast radius is visible immediately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Zero Cross-Repo Edges Still Has Value: Interface Design Comparison
&lt;/h2&gt;

&lt;p&gt;Back to LightRAG and graphrag — no cross-repo edges, but both indexes exist. Holding two indexed projects simultaneously enables something useful even without integration edges: &lt;strong&gt;interface design comparison&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;LightRAG's query interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# LightRAG
&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;aquery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;param&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;QueryParam&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;graphrag's query interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# graphrag
&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;local_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;GraphRagConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;communities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;community_reports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;text_units&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;relationships&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;covariates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;community_level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;response_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two frameworks doing the same category of thing, with radically different interface philosophies. LightRAG encapsulates all configuration in &lt;code&gt;QueryParam&lt;/code&gt; (designed for a service runtime). graphrag expects the caller to manage every DataFrame directly (designed for a batch analytics pipeline).&lt;/p&gt;

&lt;p&gt;These interface designs reflect completely different target use cases — and this kind of &lt;strong&gt;cross-project interface comparison&lt;/strong&gt; is one of the most valuable analyses for technology selection decisions. It's also a side-effect of having both projects indexed at the same time, without requiring any cross-repo edges.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Cross-repo analysis isn't 'single-repo analysis made bigger.' It solves a genuinely new class of problem: &lt;strong&gt;connecting knowledge at service boundaries.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Three core conclusions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Zero cross-repo edges is a meaningful answer&lt;/strong&gt;: it says two systems have no integration relationship — not that the analysis failed. Don't conflate 'the tool found something' with 'the tool worked correctly.'&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cross-repo analysis works by route matching&lt;/strong&gt;: it matches Route nodes exposed by one service against HTTP_CALLS / ASYNC_CALLS edges from another. That's what it can find, and only that. Functional similarity, code style comparison, duplicate logic detection — those are different tools' jobs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Projects with no cross-repo edges still benefit from joint indexing&lt;/strong&gt;: a cross-repo knowledge base lets you query multiple projects simultaneously. Even without call edges, parallel indexes have analytical value — like interface design comparison.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Next article: we turn to &lt;strong&gt;knowledge base evaluation&lt;/strong&gt; — how do you know your knowledge base is 'good enough'? What metrics matter, how to design evaluation datasets, and what production systems should track when Recall@5 is no longer the only metric that matters.&lt;/p&gt;







&lt;p&gt;&lt;em&gt;Check out &lt;a href="https://primeskills.store" rel="noopener noreferrer"&gt;PrimeSkills&lt;/a&gt; — a curated marketplace of AI agents and skills that have been validated in real-world, enterprise-grade workflows. No fluff, just what actually works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Find more useful knowledge and interesting products on my &lt;a href="https://home.wonlab.top/en" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>codebase</category>
      <category>engineering</category>
    </item>
    <item>
      <title>Open Source Project #145: Open Code Review — Alibaba's Battle-Tested AI Code Review Tool, 1/9 the Tokens of a General Agent</title>
      <dc:creator>WonderLab</dc:creator>
      <pubDate>Sun, 09 Aug 2026 03:10:24 +0000</pubDate>
      <link>https://dev.to/wonderlab/open-source-project-145-open-code-review-alibabas-battle-tested-ai-code-review-tool-19-the-6e4</link>
      <guid>https://dev.to/wonderlab/open-source-project-145-open-code-review-alibabas-battle-tested-ai-code-review-tool-19-the-6e4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"The problem with general-purpose agents doing code review isn't that they miss bugs. It's that they don't know which files to read, they drift on line numbers, and they burn 9x the tokens doing it."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is &lt;strong&gt;article #145&lt;/strong&gt; in the "One Open Source Project a Day" series. Today's project is &lt;strong&gt;Open Code Review&lt;/strong&gt; — Alibaba's open-sourcing of its internal AI code review tool, released in 2026 after years of serving tens of thousands of engineers internally and identifying "millions of code defects."&lt;/p&gt;

&lt;p&gt;Tools that use LLMs for code review are common, but most just dump the diff into a model and wait for output. Open Code Review starts from a different place: a &lt;strong&gt;hybrid architecture&lt;/strong&gt; where deterministic engineering pipelines handle the things that must not be wrong (file selection, line positioning, rule matching), and the LLM agent handles only what genuinely requires dynamic judgment. The result: same underlying model, higher precision and F1, roughly one-ninth the token consumption of a general-purpose agent.&lt;/p&gt;

&lt;p&gt;18,100 Stars. 1,200 Forks. Apache 2.0.&lt;/p&gt;

&lt;h3&gt;
  
  
  What You'll Learn
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The hybrid architecture design rationale: why separate "deterministic" from "agent"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ocr review&lt;/code&gt; (incremental diff review) vs &lt;code&gt;ocr scan&lt;/code&gt; (full-file audit)&lt;/li&gt;
&lt;li&gt;Delegation mode: your existing agent runs the review; no OCR API key needed&lt;/li&gt;
&lt;li&gt;Benchmark numbers comparing against Claude Code as a general agent&lt;/li&gt;
&lt;li&gt;GitHub Actions integration and three SLA review levels&lt;/li&gt;
&lt;li&gt;Defect patterns specific to AI-generated code&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Familiarity with Git workflows (branch, diff, PR)&lt;/li&gt;
&lt;li&gt;Basic understanding of CI/CD concepts&lt;/li&gt;
&lt;li&gt;Experience with Claude Code or similar AI coding tools is helpful&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;h3&gt;
  
  
  From Internal Tooling to Open Source
&lt;/h3&gt;

&lt;p&gt;Open Code Review wasn't purpose-built for open-source release — it's Alibaba's production-running internal system published externally. That distinction matters: its design decisions come from real large-scale operational experience, not from first-principles speculation.&lt;/p&gt;

&lt;p&gt;Before open-sourcing, the internal system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Served &lt;strong&gt;tens of thousands of engineers&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Identified &lt;strong&gt;millions of code defects&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Handled the genuine complexity of production-scale codebases&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Problem with General Agents for Code Review
&lt;/h3&gt;

&lt;p&gt;Sending a diff directly to Claude Code or GPT for code review carries systematic weaknesses:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;How It Appears&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Incomplete file coverage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Agent autonomously picks which files to read; misses critical cross-file dependencies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Position drift&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Line numbers in comments land on incorrect lines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Inconsistent quality&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Same diff reviewed twice produces different severity assessments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Token waste&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;General agent reads large amounts of unnecessary context&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The root cause: general agents hand all decisions to the LLM for flexibility, including decisions that deterministic code could handle precisely.&lt;/p&gt;




&lt;h2&gt;
  
  
  Core Architecture: Hybrid Design
&lt;/h2&gt;

&lt;p&gt;Open Code Review's design philosophy: &lt;strong&gt;let deterministic things be handled deterministically; let the agent handle only what genuinely requires dynamic judgment.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Git changes
    ↓
[Deterministic Layer]
  ├── Precise file selection (no misses, no extras)
  ├── Smart bundle grouping (related files → isolated sub-agent contexts)
  ├── Template engine rule matching (NPE, thread safety, XSS, SQL injection)
  └── External positioning + reflection modules (accurate line-level placement)
    ↓
[Agent Layer]
  ├── Scenario-tuned prompts and toolsets
  ├── Optimized from analysis of production tool-call traces
  └── Dynamic context retrieval and tool calls
    ↓
Code review output (precise line-level comments)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Deterministic layer handles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Selecting exactly the right files from git changes — no gaps, no noise&lt;/li&gt;
&lt;li&gt;Grouping related files into Bundles, each processed in an isolated sub-agent context (divide and conquer)&lt;/li&gt;
&lt;li&gt;Matching common defect rules via template engine rather than asking LLM to reason from scratch each time&lt;/li&gt;
&lt;li&gt;Ensuring comment line numbers are accurate with no position drift&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Agent layer handles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompts and toolsets tuned from analyzing production tool-call traces at scale&lt;/li&gt;
&lt;li&gt;Complex cross-file reasoning that genuinely needs inference&lt;/li&gt;
&lt;li&gt;Dynamic tool calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result: higher precision (the deterministic layer removes LLM randomness from structure), lower token usage (the agent processes only the genuinely hard parts).&lt;/p&gt;




&lt;h2&gt;
  
  
  Benchmark Data
&lt;/h2&gt;

&lt;p&gt;The Open Code Review team built a benchmark from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;50 open-source repositories&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;200 PRs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;10 programming languages&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1,505 annotated issues&lt;/strong&gt; (hand-labeled by 80+ engineers)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compared against Claude Code (general agent mode) using the same underlying model:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Open Code Review&lt;/th&gt;
&lt;th&gt;Claude Code (general agent)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Precision&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;F1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Recall&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lower (deliberate)&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Token usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~1/9&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;On the recall tradeoff&lt;/strong&gt;: Open Code Review deliberately designs for lower recall than a general agent. This isn't a limitation — it's a choice. Fewer false alarms and higher precision are more valuable than comprehensive coverage in a CI/CD gate. Noise that blocks PRs creates review fatigue faster than any genuine bug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the token difference means in practice&lt;/strong&gt;: For 100 PRs, Open Code Review consumes roughly 11% of what a general agent would. In CI/CD where every PR triggers a review, this determines whether the tool is financially viable. Nine-to-one cost difference changes the calculation entirely.&lt;/p&gt;




&lt;h2&gt;
  
  
  Two Review Modes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;ocr review&lt;/code&gt;: Incremental Diff Review (Most Common)
&lt;/h3&gt;

&lt;p&gt;Reviews git diffs — staged changes, unstaged changes, branch ranges, or single commits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Review current working tree changes (staged + unstaged)&lt;/span&gt;
ocr review

&lt;span class="c"&gt;# Review a branch range&lt;/span&gt;
ocr review &lt;span class="nt"&gt;--from&lt;/span&gt; main &lt;span class="nt"&gt;--to&lt;/span&gt; feature/new-auth

&lt;span class="c"&gt;# Review a single commit&lt;/span&gt;
ocr review &lt;span class="nt"&gt;--commit&lt;/span&gt; abc1234

&lt;span class="c"&gt;# Output formats&lt;/span&gt;
ocr review &lt;span class="nt"&gt;--output&lt;/span&gt; json
ocr review &lt;span class="nt"&gt;--output&lt;/span&gt; sarif   &lt;span class="c"&gt;# importable into GitHub Security&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;ocr scan&lt;/code&gt;: Full-File Audit
&lt;/h3&gt;

&lt;p&gt;No git history required — reviews file content directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Audit a directory&lt;/span&gt;
ocr scan &lt;span class="nt"&gt;--path&lt;/span&gt; internal/

&lt;span class="c"&gt;# Audit a single file&lt;/span&gt;
ocr scan &lt;span class="nt"&gt;--path&lt;/span&gt; src/auth/handler.go

&lt;span class="c"&gt;# Generate HTML report&lt;/span&gt;
ocr scan &lt;span class="nt"&gt;--path&lt;/span&gt; src/ &lt;span class="nt"&gt;--output&lt;/span&gt; html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Good fit for&lt;/strong&gt;: security audits on inherited codebases, quality assessment of legacy code with no git history, reviewing code snippets without a repository context.&lt;/p&gt;




&lt;h2&gt;
  
  
  Delegation Mode
&lt;/h2&gt;

&lt;p&gt;One of Open Code Review's most interesting design choices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Standard mode&lt;/strong&gt;: OCR's agent layer uses an LLM API you configure (Anthropic/OpenAI key required) to run the review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delegation mode&lt;/strong&gt;: OCR handles only the deterministic layer (file selection, bundle grouping, rule resolution), then &lt;strong&gt;delegates the review task to your existing agent&lt;/strong&gt; (Claude Code, Codex, Cursor, etc.), using that agent's own LLM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Preview the delegation plan (see how OCR intends to split the task)&lt;/span&gt;
ocr delegate preview

&lt;span class="c"&gt;# Generate rule descriptions for specific files for the agent to review&lt;/span&gt;
ocr delegate rule src/main.go src/handler.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it's useful&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You already have a Claude Code subscription or API key — no separate OCR key needed&lt;/li&gt;
&lt;li&gt;OCR's deterministic layer handles file selection and rule resolution; your agent focuses on understanding and judgment&lt;/li&gt;
&lt;li&gt;Integrates into your existing agent workflow without switching tools&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  GitHub Actions Integration
&lt;/h2&gt;

&lt;p&gt;Thirty-second setup. Every PR triggers a review automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AI Code Review&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;review&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;raye-deng/open-code-review@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;sla&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;L2&lt;/span&gt;          &lt;span class="c1"&gt;# Review depth: L1 / L2 / L3&lt;/span&gt;
          &lt;span class="na"&gt;threshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;    &lt;span class="c1"&gt;# Fail if quality score drops below 60&lt;/span&gt;
          &lt;span class="na"&gt;github-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Three SLA Levels
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;L1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fast structural detection, no AI required&lt;/td&gt;
&lt;td&gt;Quick PRs, low-risk changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;L2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Adds semantic analysis and embedding&lt;/td&gt;
&lt;td&gt;Standard feature development&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;L3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full LLM deep scan: cross-file coherence, logic bug detection, confidence scoring&lt;/td&gt;
&lt;td&gt;Core paths, security-sensitive code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  AI-Generated Code Defect Detection
&lt;/h2&gt;

&lt;p&gt;Open Code Review positions itself on GitHub Marketplace as "the first open-source CI/CD quality gate built specifically for AI-generated code" — detecting defect patterns common in LLM output that traditional linters miss entirely:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Defect Type&lt;/th&gt;
&lt;th&gt;What It Looks Like&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hallucinated imports&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Packages that don't exist (verified live against npm/PyPI/Maven)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stale APIs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Deprecated methods present in training data but removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Context window artifacts&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Logic contradictions spanning multiple files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Over-engineering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unnecessary abstractions and dead code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Security anti-patterns&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hardcoded secrets, &lt;code&gt;eval()&lt;/code&gt; usage&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These problems appear at significantly higher rates in AI-generated code than in human-written code — standard linters aren't looking for them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supported languages&lt;/strong&gt;: TypeScript/JavaScript, Python, Java, Go, Kotlin (6 languages).&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation and Configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Install
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# npm (recommended)&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @alibaba-group/open-code-review

&lt;span class="c"&gt;# Requires Git &amp;gt;= 2.41&lt;/span&gt;
git &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configure the LLM
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ocr config provider
&lt;span class="c"&gt;# Interactive setup: choose Anthropic / OpenAI / custom compatible endpoint&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fine-grained configuration via &lt;code&gt;.ocrrc.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;sla&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;L3&lt;/span&gt;
&lt;span class="na"&gt;ai&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;embedding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ollama&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nomic-embed-text&lt;/span&gt;
  &lt;span class="na"&gt;llm&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ollama&lt;/span&gt;       &lt;span class="c1"&gt;# local Ollama supported&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;qwen3-coder&lt;/span&gt;     &lt;span class="c1"&gt;# any OpenAI-compatible model&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  First Run
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my-project

&lt;span class="c"&gt;# Review current changes&lt;/span&gt;
ocr review

&lt;span class="c"&gt;# List sessions (resume support built in)&lt;/span&gt;
ocr session list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🌟 &lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/alibaba/open-code-review" rel="noopener noreferrer"&gt;alibaba/open-code-review&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Docs&lt;/strong&gt;: &lt;a href="https://open-codereview.ai" rel="noopener noreferrer"&gt;open-codereview.ai&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🏪 &lt;strong&gt;GitHub Marketplace&lt;/strong&gt;: &lt;a href="https://github.com/marketplace/actions/open-code-review" rel="noopener noreferrer"&gt;Open Code Review Action&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;npm&lt;/strong&gt;: &lt;code&gt;@alibaba-group/open-code-review&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Open Code Review makes one thing clear: &lt;strong&gt;in the specific domain of code review, using engineering constraints around the LLM produces better results than letting the LLM operate freely.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The problem with general agents for code review isn't insufficient LLM capability — it's that handing all decisions to the LLM introduces unnecessary randomness and token waste where deterministic code could be precise. Handling file selection, line positioning, and rule matching with deterministic pipelines focuses the LLM's attention on the parts that actually need inference.&lt;/p&gt;

&lt;p&gt;This design principle is worth generalizing: not "how do we make the AI do better" but "which parts should the AI never have been doing." It's a conclusion that most AI tooling teams arrive at after hitting the same walls at scale. Alibaba packaged the lessons from that experience and released them along with the code.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Explore &lt;a href="https://primeskills.store" rel="noopener noreferrer"&gt;PrimeSkills&lt;/a&gt; — A marketplace for handpicked AI Agents and skills. Each is validated in real enterprise workflows, stripping away hype and keeping only what truly works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Welcome to my &lt;a href="https://home.wonlab.top/en" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt; for more useful insights and interesting products.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>codereview</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Codebase Knowledge Base (10): Incremental Updates — When to Rebuild the Index, and Which Parts</title>
      <dc:creator>WonderLab</dc:creator>
      <pubDate>Sat, 08 Aug 2026 11:12:47 +0000</pubDate>
      <link>https://dev.to/wonderlab/codebase-knowledge-base-10-incremental-updates-when-to-rebuild-the-index-and-which-parts-4609</link>
      <guid>https://dev.to/wonderlab/codebase-knowledge-base-10-incremental-updates-when-to-rebuild-the-index-and-which-parts-4609</guid>
      <description>&lt;h2&gt;
  
  
  A Problem That's Easy to Overlook
&lt;/h2&gt;

&lt;p&gt;Build the codebase knowledge base, run the first query, watch vector search and graph traversal return exactly what you wanted — and it's tempting to call the job done.&lt;/p&gt;

&lt;p&gt;But the code keeps moving. New PRs merge. Functions get renamed. Interfaces change. New files appear, old modules get deleted. Three months later, the function signatures in your index may be stale, the call graph might point to a function that has been moved, and the embeddings might still represent a rewritten implementation. Your queries return plausible but wrong answers — and the failure is silent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Knowledge base freshness is a harder problem than building the knowledge base in the first place, and it's much easier to ignore.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Full rebuild is simple: code changed, delete the index and rerun everything. For a medium-scale codebase that might take hours — you can't do it on every commit. The opposite extreme is 'never update' — let the index drift permanently away from the actual code, and watch retrieval quality degrade quietly over months.&lt;/p&gt;

&lt;p&gt;This article charts the practical middle path: &lt;strong&gt;precisely determine which changes affect what, and rebuild only the parts that genuinely need it.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Starting From a Real detect_changes Output
&lt;/h2&gt;

&lt;p&gt;Running &lt;code&gt;detect_changes&lt;/code&gt; on the LightRAG codebase (HEAD~5 to HEAD) returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;changed_files&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.github/workflows/copilot-setup-steps.yml"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.github/workflows/tests.yml"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lightrag_webui/bun.lock"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lightrag_webui/package.json"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lightrag_webui/README.md"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;README-ja.md"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;README.md"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;README-zh.md"&lt;/span&gt;
&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;changed_count&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;
&lt;span class="na"&gt;impacted_symbols&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;
  &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;jobs"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Variable"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.github/workflows/..."&lt;/span&gt;&lt;span class="pi"&gt;},&lt;/span&gt;
  &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;LightRAG&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;WebUI"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Section"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lightrag_webui/README.md"&lt;/span&gt;&lt;span class="pi"&gt;},&lt;/span&gt;
  &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Installation"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Section"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lightrag_webui/README.md"&lt;/span&gt;&lt;span class="pi"&gt;},&lt;/span&gt;
  &lt;span class="nv"&gt;...&lt;/span&gt;
&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eight changed files. The &lt;code&gt;impacted_symbols&lt;/code&gt; list contains only CI variables (&lt;code&gt;jobs&lt;/code&gt;, &lt;code&gt;on&lt;/code&gt;) and Markdown headings (&lt;code&gt;Section&lt;/code&gt;) — &lt;strong&gt;zero Functions, zero Methods, zero Classes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The correct response to this change set is: &lt;strong&gt;do nothing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not because the changes are unimportant (updating CI config and README is real work) — but because none of these 8 files have any content that would affect the knowledge base's three retrieval paths. There's nothing from these files in the vector index, no nodes from them in the call graph, nothing to find in the symbol index. A full rebuild would be pure waste: hours of compute time and API costs, for zero improvement in retrieval quality.&lt;/p&gt;

&lt;p&gt;This brings us to the first tier.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tier 1: Does This Change Affect Retrievable Content?
&lt;/h2&gt;

&lt;p&gt;Different file types have very different impacts on the knowledge base:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File type&lt;/th&gt;
&lt;th&gt;Affects vector index&lt;/th&gt;
&lt;th&gt;Affects call graph&lt;/th&gt;
&lt;th&gt;Affects symbol index&lt;/th&gt;
&lt;th&gt;Decision&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;.py&lt;/code&gt; function changes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Incremental update needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;.ts&lt;/code&gt; / &lt;code&gt;.tsx&lt;/code&gt; changes&lt;/td&gt;
&lt;td&gt;Yes (if indexed)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Incremental update needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test files (&lt;code&gt;test_*.py&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;Policy-dependent&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;Configure per team&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CI config (&lt;code&gt;.yml&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Skip&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Markdown / README&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Skip&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;package.json&lt;/code&gt; / lockfiles&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Skip&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Config files (&lt;code&gt;.env&lt;/code&gt;, &lt;code&gt;.toml&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Skip&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The decision rule:&lt;/strong&gt; Does &lt;code&gt;impacted_symbols&lt;/code&gt; contain any entries with &lt;code&gt;label&lt;/code&gt; equal to &lt;code&gt;Function&lt;/code&gt;, &lt;code&gt;Method&lt;/code&gt;, or &lt;code&gt;Class&lt;/code&gt;? If not, skip this update entirely.&lt;/p&gt;

&lt;p&gt;In practice, encode this as a git hook or CI step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Pseudocode — not runnable as-is
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;should_update_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changed_files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;CODE_EXTENSIONS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.py&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.ts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.tsx&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.js&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;suffix&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;CODE_EXTENSIONS&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;changed_files&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For LightRAG's 5-commit window: &lt;code&gt;{'.yml', '.lock', '.json', '.md'}&lt;/code&gt; — no code files. Return &lt;code&gt;False&lt;/code&gt;. Index update cost for this batch = 0.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tier 2: Which Functions Changed — Rebuild Only Those
&lt;/h2&gt;

&lt;p&gt;When Tier 1 determines there are real code changes, enter Tier 2.&lt;/p&gt;

&lt;p&gt;Suppose a change touches &lt;code&gt;lightrag/operate.py&lt;/code&gt; and &lt;code&gt;lightrag/pipeline.py&lt;/code&gt;. &lt;code&gt;detect_changes&lt;/code&gt; returns the specific symbols that changed in those files. The strategy is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Re-embed only the changed functions. Leave everything else untouched.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The underlying assumption: the embedding unit is a function, and functions are relatively self-contained semantic units. When a function's implementation changes, only its position in vector space needs to update — every other function's embedding vector remains valid.&lt;/p&gt;

&lt;p&gt;The same principle applies to call graph updates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;naive_query&lt;/code&gt; in &lt;code&gt;operate.py&lt;/code&gt; adds a new call to &lt;code&gt;_find_related_text_unit_from_entities&lt;/code&gt;, update only &lt;code&gt;naive_query&lt;/code&gt;'s outgoing edges — don't rebuild the whole graph.&lt;/li&gt;
&lt;li&gt;If a function is deleted, remove the corresponding node and all its edges.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Incremental update cost scales as &lt;code&gt;(changed function count / total function count)&lt;/code&gt;.&lt;/strong&gt; LightRAG has 7,761 Function nodes. A change affecting 50 functions costs roughly 0.6% of a full rebuild.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tier 3: High-Impact Changes — Trace the Call Chain
&lt;/h2&gt;

&lt;p&gt;Tiers 1 and 2 handle 'I know which functions directly changed.' Tier 3 answers a deeper question: &lt;strong&gt;do these direct changes affect functions that themselves haven't changed?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Two signals matter here.&lt;/p&gt;

&lt;h3&gt;
  
  
  3a. Call graph propagation
&lt;/h3&gt;

&lt;p&gt;Suppose a low-level function in &lt;code&gt;parse_document.py&lt;/code&gt; changes its interface. It's called by &lt;code&gt;analyze_multimodal&lt;/code&gt; in &lt;code&gt;pipeline.py&lt;/code&gt;, which is called by the top-level API in &lt;code&gt;lightrag.py&lt;/code&gt;. Every function in this chain may have changed behavior in the new version — even though only the leaf function is in the diff.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;trace_path("changed_function", mode=calls, direction=inbound)
→ returns all upstream callers that depend on this function
→ flag these callers as 'potentially affected' (re-analyze, don't necessarily re-embed)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3b. FILE_CHANGES_WITH: the hidden signal of temporal coupling
&lt;/h3&gt;

&lt;p&gt;This is an edge type in &lt;code&gt;codebase-memory-mcp&lt;/code&gt; that's easy to overlook but highly valuable. Its meaning: &lt;strong&gt;in historical git commits, these two files were frequently modified together.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Looking at the LightRAG knowledge graph's FILE_CHANGES_WITH edges reveals a clear pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Selected FILE_CHANGES_WITH pairs:
  FileProcessingPipeline.md ↔ routing.py      # docs and routing code evolve together
  FileProcessingPipeline.md ↔ parser.py       # docs and parser evolve together
  operate.py ↔ utils.py                       # extraction logic and utilities coupled
  operate.py ↔ prompt.py                      # extraction logic and prompts move together
  pipeline.py ↔ utils_pipeline.py             # pipeline core and pipeline utilities
  base.py ↔ lightrag.py                       # abstract base and main class evolve together
  config.py ↔ lightrag.py                     # configuration and main class
  chunk_schema.py ↔ pipeline.py               # chunk schema and pipeline
  document_routes.py ↔ routing.py             # document API and routing layer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These relationships weren't derived from static analysis — they were mined from git history. What they tell you:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When &lt;code&gt;operate.py&lt;/code&gt; changes, history shows a high probability that &lt;code&gt;utils.py&lt;/code&gt; and &lt;code&gt;prompt.py&lt;/code&gt; changed simultaneously — even if this specific diff doesn't show them changing. If you only rebuild &lt;code&gt;operate.py&lt;/code&gt;'s index, you might miss a synchronized adjustment in &lt;code&gt;prompt.py&lt;/code&gt;'s knowledge extraction logic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;This is coupling that static analysis can never surface.&lt;/strong&gt; Function A doesn't call function B. File X doesn't import file Y. But historical evidence says they always move together — that's an implicit architectural convention, only visible in temporal data.&lt;/p&gt;

&lt;p&gt;Practical use: when computing an incremental update, include the &lt;code&gt;FILE_CHANGES_WITH&lt;/code&gt; neighbors of changed files in your inspection scope, even if they didn't change in this specific commit.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Three-Tier Decision Tree
&lt;/h2&gt;

&lt;p&gt;Assembled into an operational flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tier 1: detect_changes(since=last_index_commit)
  ├── impacted_symbols all Section/Variable/Module?
  │   └── Skip. Check again next time.
  └── Function/Method/Class changes present?
      │
Tier 2: Extract list of changed functions
  ├── Re-embed changed functions (overwrite old vectors)
  ├── Update call graph edges locally (add/remove/modify)
  └── Update symbol index (renames/deletes/additions)
      │
Tier 3: Expand impact scope
  ├── trace_path(changed_fn, direction=inbound)
  │   └── Flag upstream callers as 'potentially affected'
  └── FILE_CHANGES_WITH(changed_files)
      └── Add historical co-change neighbors to next review cycle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cost estimates for LightRAG:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Changed functions&lt;/th&gt;
&lt;th&gt;Update cost&lt;/th&gt;
&lt;th&gt;% of full rebuild&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CI + README update&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Small feature (1-2 files)&lt;/td&gt;
&lt;td&gt;5-20&lt;/td&gt;
&lt;td&gt;Minutes&lt;/td&gt;
&lt;td&gt;&amp;lt; 1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Module refactor (5-10 files)&lt;/td&gt;
&lt;td&gt;50-200&lt;/td&gt;
&lt;td&gt;10-30 min&lt;/td&gt;
&lt;td&gt;2-4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Large refactor (20+ files)&lt;/td&gt;
&lt;td&gt;500+&lt;/td&gt;
&lt;td&gt;Trigger full rebuild&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  A Real Data Point: High-Complexity Functions and Change Cost
&lt;/h2&gt;

&lt;p&gt;Querying for the highest-complexity functions in LightRAG:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;f.label&lt;/span&gt; &lt;span class="ow"&gt;IN&lt;/span&gt; &lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Function'&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'Method'&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;f.complexity&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;f.name&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f.file_path&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f.complexity&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f.transitive_loop_depth&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;f.complexity&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Results (excluding the bundled swagger-ui file):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;adelete_by_doc_id      lightrag/lightrag.py      complexity=131  transitive_loop_depth=14
create_document_routes lightrag/api/routers/...   complexity=118
analyze_multimodal     lightrag/pipeline.py       complexity=116  transitive_loop_depth=14
create_app             lightrag/api/lightrag_server.py  complexity=91
openai_complete_if_cache lightrag/llm/openai.py   complexity=89
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;adelete_by_doc_id&lt;/code&gt; has &lt;code&gt;complexity=131&lt;/code&gt; and &lt;code&gt;transitive_loop_depth=14&lt;/code&gt; — its execution path nests 14 levels deep, making it one of the hardest functions in the codebase to reason about and one of the most likely to propagate change effects.&lt;/p&gt;

&lt;p&gt;If this function appears in a change set, Tier 3 isn't optional — every change to it requires a full inbound call-chain trace to verify that upstream callers' behavioral assumptions still hold.&lt;/p&gt;

&lt;p&gt;Conversely, if the change is a paragraph in &lt;code&gt;README.md&lt;/code&gt;, this complexity data is irrelevant to you. &lt;strong&gt;The first value of &lt;code&gt;detect_changes&lt;/code&gt; is that it filters out the noisy commits — CI tweaks, doc fixes, dependency bumps — at Tier 1, before any analysis needs to happen.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Incremental updates are fundamentally a &lt;strong&gt;precision problem&lt;/strong&gt;, not an engineering-effort problem. Full rebuild is simpler to implement. Incremental updates require finer-grained decision logic. But once that logic exists, the payoff compounds.&lt;/p&gt;

&lt;p&gt;A three-tier incremental update system lets roughly 80% of commits (docs, config, test-only) bypass index updates entirely, and the remaining 20% (real code changes) rebuild only the affected fraction. For a continuously evolving codebase, this isn't an optimization — it's what makes the knowledge base viable over months and years.&lt;/p&gt;

&lt;p&gt;Next article: we extend the scope from a single codebase to &lt;strong&gt;multi-repo scenarios&lt;/strong&gt; — when one service calls another service's API, or when microservices communicate through message queues, how should the knowledge base build connections that span repository boundaries?&lt;/p&gt;







&lt;p&gt;&lt;em&gt;Check out &lt;a href="https://primeskills.store" rel="noopener noreferrer"&gt;PrimeSkills&lt;/a&gt; — a curated marketplace of AI agents and skills that have been validated in real-world, enterprise-grade workflows. No fluff, just what actually works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Find more useful knowledge and interesting products on my &lt;a href="https://home.wonlab.top/en" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>codebase</category>
      <category>engineering</category>
    </item>
    <item>
      <title>Open Source Project #144: Omnigent — Databricks' Meta-Harness for Unified Control of Claude Code, Codex, and Cursor</title>
      <dc:creator>WonderLab</dc:creator>
      <pubDate>Sat, 08 Aug 2026 11:03:43 +0000</pubDate>
      <link>https://dev.to/wonderlab/open-source-project-144-omnigent-databricks-meta-harness-for-unified-control-of-claude-code-4fd4</link>
      <guid>https://dev.to/wonderlab/open-source-project-144-omnigent-databricks-meta-harness-for-unified-control-of-claude-code-4fd4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"You use Claude Code for planning and Codex for fast execution. But you're manually copying output between them."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is &lt;strong&gt;article #144&lt;/strong&gt; in the "One Open Source Project a Day" series. Today's project is &lt;strong&gt;Omnigent&lt;/strong&gt; — an AI agent meta-orchestration framework open-sourced by Databricks co-founder Matei Zaharia in June 2026. 8,100 Stars.&lt;/p&gt;

&lt;p&gt;Omnigent's position is specific: it's not another AI coding agent. It's the layer that sits above existing agents — a &lt;strong&gt;meta-harness&lt;/strong&gt;. The analogy Databricks makes: Kubernetes doesn't replace servers, it adds orchestration, policy, and observability on top of them. Omnigent doesn't replace Claude Code; it makes Claude Code, Codex, Cursor, and Pi manageable components of one unified system instead of a pile of independent tools.&lt;/p&gt;

&lt;p&gt;If you've used multiple AI coding tools, you've probably hit this: each tool has its own interface, its own API key management, its own context and session, and configuring team-level permissions and budgets for each separately is its own overhead. Omnigent targets exactly that layer.&lt;/p&gt;

&lt;p&gt;8,100 Stars. 1,200 Forks. Apache 2.0. Alpha stage.&lt;/p&gt;

&lt;h3&gt;
  
  
  What You'll Learn
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;What a "meta-harness" is and how Omnigent relates to agent frameworks&lt;/li&gt;
&lt;li&gt;Policy Governance: three-tier policy stacking for token budgets and tool access&lt;/li&gt;
&lt;li&gt;Cloud sandboxes: local OS isolation (bwrap/seatbelt) plus cloud execution (Modal/E2B/Daytona)&lt;/li&gt;
&lt;li&gt;Multi-agent orchestration: YAML sub-agents, parallel worktrees, cross-vendor reviewers&lt;/li&gt;
&lt;li&gt;Real-time collaboration: session sharing, co-driving, forking&lt;/li&gt;
&lt;li&gt;MLflow Tracing integration: unified observability across harnesses&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Experience with at least one of Claude Code, Codex, or Cursor&lt;/li&gt;
&lt;li&gt;Basic understanding of AI coding agents (context, tool calls, system prompts)&lt;/li&gt;
&lt;li&gt;Familiarity with YAML configuration format&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Background: The Fragmented Agent Landscape
&lt;/h2&gt;

&lt;p&gt;The 2026 AI coding tool landscape: Claude Code with claude-sdk and claude-native modes, Codex with its own CLI, Cursor embedded in the IDE, OpenCode, Hermes, Pi — each with distinct capabilities, each a separate island.&lt;/p&gt;

&lt;p&gt;Matei Zaharia (inventor of Apache Spark, Databricks co-founder) ran into this while driving AI agent adoption across Databricks' 5,000+ engineer organization:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Different agents have different strengths; one task often needs multiple agents working together&lt;/li&gt;
&lt;li&gt;Agent output requires manual transfer between tools&lt;/li&gt;
&lt;li&gt;Team-level governance has no infrastructure (who accesses what tools? what's the token budget?)&lt;/li&gt;
&lt;li&gt;No unified observability — no visibility into which agent spent what, or what decisions it made&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Omnigent distills that deployment experience into a framework that tackles the whole problem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Core Architecture: The Meta-Harness Layer
&lt;/h2&gt;

&lt;p&gt;Omnigent's architecture has three layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────┐
│           Omnigent Server               │
│   Policy governance / collaboration /   │
│   observability / API                   │
├─────────────────────────────────────────┤
│           Omnigent Runner               │
│   Sandboxing / unified API /            │
│   session management                    │
├──────────┬──────────┬───────────────────┤
│ claude-sdk│  codex  │  cursor / pi / …  │
│ (harness) │(harness) │   (harnesses)    │
└──────────┴──────────┴───────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Harness (execution layer)&lt;/strong&gt;: the existing agent tools — claude-sdk, claude-native, codex, codex-native, cursor, hermes, opencode, pi, openai-agents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runner (runtime layer)&lt;/strong&gt;: wraps any harness in a sandboxed session with a uniform API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server (service layer)&lt;/strong&gt;: policy enforcement, session sharing, cross-device sync&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Kubernetes analogy holds: Kubernetes doesn't replace servers — it adds orchestration, elasticity, and policy above them. Omnigent doesn't replace Claude Code — it adds unified control above it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Policy Governance
&lt;/h2&gt;

&lt;p&gt;Policies are one of Omnigent's core differentiators. Three tiers stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server-wide (shared across all agents)
    ↓
Agent-level (defined per agent)
    ↓
Session-level (dynamic adjustments per task)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cost Control
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Token budget in the agent definition&lt;/span&gt;
&lt;span class="na"&gt;policies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;cost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;max_tokens_per_session&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50000&lt;/span&gt;
    &lt;span class="na"&gt;max_tokens_per_turn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5000&lt;/span&gt;
    &lt;span class="na"&gt;alert_at&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;40000&lt;/span&gt;   &lt;span class="c1"&gt;# alert when approaching limit&lt;/span&gt;
    &lt;span class="na"&gt;pause_at&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50000&lt;/span&gt;   &lt;span class="c1"&gt;# pause and wait for human approval&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agents that exceed budget pause automatically, waiting for a human to decide whether to continue. This solves the common problem of agents quietly burning large token budgets on complex tasks with no warning.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tool Access Control
&lt;/h3&gt;

&lt;p&gt;Policies support &lt;strong&gt;stateful conditional restrictions&lt;/strong&gt; — not just static allow/block lists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;policies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# After downloading an npm package, require approval before git push&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;after:tool:npm_install"&lt;/span&gt;
      &lt;span class="na"&gt;require_approval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;git_push"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Never allow the agent to read .env files directly&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;block&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;read_file:.env*"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Agent can call APIs, but credentials injected via proxy — agent never sees them&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;egress_proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://my-credential-proxy"&lt;/span&gt;
        &lt;span class="na"&gt;direct_credential_access&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stateful rules like "require git push approval after npm install" were effectively impossible with per-tool agent configurations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cloud Sandboxes
&lt;/h2&gt;

&lt;p&gt;Omnigent supports two sandboxing approaches:&lt;/p&gt;

&lt;h3&gt;
  
  
  Local OS Sandboxing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linux&lt;/strong&gt;: bwrap (Bubblewrap) namespace isolation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;macOS&lt;/strong&gt;: seatbelt sandbox&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows&lt;/strong&gt;: Windows Job Objects (limited support; no PTY/tmux wrapper)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cloud Execution Environments
&lt;/h3&gt;

&lt;p&gt;Route agent execution to cloud sandboxes instead of local machines:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Modal&lt;/td&gt;
&lt;td&gt;Stateless function-style tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E2B&lt;/td&gt;
&lt;td&gt;Code execution sandbox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daytona&lt;/td&gt;
&lt;td&gt;Development environments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kubernetes&lt;/td&gt;
&lt;td&gt;Enterprise private cloud&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CoreWeave&lt;/td&gt;
&lt;td&gt;GPU-intensive tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Databricks&lt;/td&gt;
&lt;td&gt;Data analytics tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Multi-Agent Orchestration: YAML-Defined
&lt;/h2&gt;

&lt;p&gt;Omnigent agents are defined in YAML. An agent can call other agents as tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Basic agent definition&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my_coder&lt;/span&gt;
&lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;You are an expert Python developer.&lt;/span&gt;
  &lt;span class="s"&gt;Focus on correctness and test coverage.&lt;/span&gt;
&lt;span class="na"&gt;executor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;harness&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;claude-sdk&lt;/span&gt;
&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;run_tests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;function&lt;/span&gt;
    &lt;span class="na"&gt;callable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mypackage.testing.run_pytest&lt;/span&gt;
  &lt;span class="na"&gt;search_docs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mcp&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://docs-mcp.example.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Multi-Agent Pattern: Polly
&lt;/h3&gt;

&lt;p&gt;Omnigent ships a built-in example called &lt;strong&gt;Polly&lt;/strong&gt; — a supervisor orchestrator demonstrating the parallel worktree pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;polly&lt;/span&gt;
&lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
  &lt;span class="s"&gt;You are a supervisor coordinating multiple coding agents.&lt;/span&gt;
  &lt;span class="s"&gt;Delegate coding tasks to sub-agents, then route diffs to reviewers.&lt;/span&gt;
&lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;coder_a&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agent&lt;/span&gt;
    &lt;span class="na"&gt;harness&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;claude-sdk&lt;/span&gt;
    &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Implement&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;feature&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;git&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;worktree"&lt;/span&gt;
  &lt;span class="na"&gt;coder_b&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agent&lt;/span&gt;
    &lt;span class="na"&gt;harness&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;codex&lt;/span&gt;
    &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Implement&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;same&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;feature&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;independently"&lt;/span&gt;
  &lt;span class="na"&gt;reviewer_anthropic&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agent&lt;/span&gt;
    &lt;span class="na"&gt;harness&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;claude-sdk&lt;/span&gt;
    &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Review&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;diff&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;correctness"&lt;/span&gt;
  &lt;span class="na"&gt;reviewer_openai&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agent&lt;/span&gt;
    &lt;span class="na"&gt;harness&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;codex&lt;/span&gt;
    &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Review&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;diff&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;security&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;issues"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Two coders on different harnesses implement the same feature in parallel git worktrees&lt;/li&gt;
&lt;li&gt;Diffs get routed to two reviewers from different vendors&lt;/li&gt;
&lt;li&gt;The supervisor synthesizes review feedback and makes the final call&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Dual-Headed Agent: Debby
&lt;/h3&gt;

&lt;p&gt;The other bundled example is &lt;strong&gt;Debby&lt;/strong&gt; — runs Claude and GPT side-by-side with a &lt;code&gt;/debate&lt;/code&gt; mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User question
    → Claude produces answer A
    → GPT produces answer B
    → /debate triggers: each model critiques the other's answer
    → Debby synthesizes both arguments into a final response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real-Time Collaboration
&lt;/h2&gt;

&lt;p&gt;Omnigent turns agent sessions into multi-person workspaces:&lt;/p&gt;

&lt;h3&gt;
  
  
  Session Sharing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generate a shareable URL&lt;/span&gt;
omnigent share &amp;lt;session_id&amp;gt;
&lt;span class="c"&gt;# → https://omnigent.ai/s/abc123&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Teammates open the URL, see the agent's output in real time, inject commands, and take over the session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Session Forking
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Fork from an existing session — same context, independent development&lt;/span&gt;
omnigent run &lt;span class="nt"&gt;--fork&lt;/span&gt; &amp;lt;session_id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful in code review: the main agent finishes an implementation, fork into two sessions with different reviewer agents, merge the conclusions back into the main session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;OIDC login: Google, GitHub, Okta, Microsoft&lt;/li&gt;
&lt;li&gt;Invite-only accounts via single-use invite links&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  MLflow Tracing Integration
&lt;/h2&gt;

&lt;p&gt;The Omnigent + MLflow integration provides unified observability across all harnesses. Configuration is minimal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv tool &lt;span class="nb"&gt;install &lt;/span&gt;omnigent mlflow

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MLFLOW_TRACKING_URI&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://your-mlflow-server:5000"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OMNIGENT_TELEMETRY_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;

omnigent run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every agent execution automatically logs to MLflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each conversation turn (prompt + response)&lt;/li&gt;
&lt;li&gt;Tool invocations with arguments, results, and timing&lt;/li&gt;
&lt;li&gt;Per-turn token consumption&lt;/li&gt;
&lt;li&gt;Session metadata (model name, agent name, harness type)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Practical uses&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model comparison&lt;/strong&gt;: run the same task with Claude vs. GPT, compare cost and quality&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A/B testing&lt;/strong&gt;: evaluate different MCP server providers on cost/performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team insights&lt;/strong&gt;: which harness excels at planning vs. execution? Which request types run slow? How much time goes to features vs. bugs?&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Installation and Quick Start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install (uv recommended)&lt;/span&gt;
uv tool &lt;span class="nb"&gt;install &lt;/span&gt;omnigent

&lt;span class="c"&gt;# Or pip&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;omnigent

&lt;span class="c"&gt;# Start (picks a model, opens localhost:6767 automatically)&lt;/span&gt;
omnigent

&lt;span class="c"&gt;# Short alias&lt;/span&gt;
omni

&lt;span class="c"&gt;# Upgrade&lt;/span&gt;
omni upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser opens &lt;code&gt;http://localhost:6767&lt;/code&gt; with a GUI for configuring agents and viewing sessions. Terminal interaction also works directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy to a Server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Docker&lt;/span&gt;
docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 6767:6767 omnigentai/omnigent

&lt;span class="c"&gt;# Supported platforms: Render, Railway, Fly.io, Cloudflare&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Server deployment gives teams a shared Omnigent instance with OIDC login — all policies and collaboration features managed centrally.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🌟 &lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/omnigent-ai/omnigent" rel="noopener noreferrer"&gt;omnigent-ai/omnigent&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Website&lt;/strong&gt;: &lt;a href="https://omnigent.ai" rel="noopener noreferrer"&gt;omnigent.ai&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📝 &lt;strong&gt;Databricks blog&lt;/strong&gt;: "Introducing Omnigent: A Meta-Harness to Combine, Control and Share Your Agents"&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;MLflow integration&lt;/strong&gt;: &lt;a href="https://mlflow.org/blog/omnigent-mlflow-tracing" rel="noopener noreferrer"&gt;mlflow.org/blog/omnigent-mlflow-tracing&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;👤 &lt;strong&gt;Lead author&lt;/strong&gt;: Matei Zaharia (Databricks co-founder, inventor of Apache Spark)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Omnigent doesn't try to build a better AI coding agent. It addresses what happens when you already have multiple agents and need to turn them into a coherent system.&lt;/p&gt;

&lt;p&gt;Databricks' experience deploying AI agents across 5,000+ engineers surfaced the problem clearly: tools fragment, policy has no infrastructure, team collaboration has no shared foundation, observability is nearly absent. Omnigent packages the answer — meta-harness layer + policy governance + sandboxing + collaboration + observability — into one operational framework for running agents at scale.&lt;/p&gt;

&lt;p&gt;The "meta-harness" concept itself is worth holding onto. As AI coding tools multiply and specialize, the need for this layer only grows. Today it's Claude Code and Codex. Tomorrow it might be five more specialized tools. The problems Omnigent solves — policy, cost, collaboration, observability — appear in every combination.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Explore &lt;a href="https://primeskills.store" rel="noopener noreferrer"&gt;PrimeSkills&lt;/a&gt; — A marketplace for handpicked AI Agents and skills. Each is validated in real enterprise workflows, stripping away hype and keeping only what truly works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Welcome to my &lt;a href="https://home.wonlab.top/en" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt; for more useful insights and interesting products.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>ai</category>
      <category>agents</category>
      <category>claude</category>
    </item>
    <item>
      <title>Codebase Knowledge Base (09): codebase-memory-mcp in the Wild — Three-Path Retrieval on LightRAG</title>
      <dc:creator>WonderLab</dc:creator>
      <pubDate>Fri, 07 Aug 2026 05:29:27 +0000</pubDate>
      <link>https://dev.to/wonderlab/codebase-knowledge-base-09-codebase-memory-mcp-in-the-wild-three-path-retrieval-on-lightrag-28g3</link>
      <guid>https://dev.to/wonderlab/codebase-knowledge-base-09-codebase-memory-mcp-in-the-wild-three-path-retrieval-on-lightrag-28g3</guid>
      <description>&lt;h2&gt;
  
  
  Eight Articles Built the Ship. Now Let's Sail It.
&lt;/h2&gt;

&lt;p&gt;If you've followed the series so far, your working memory should hold a clear checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Article 03: AST function-level chunking + vector retrieval, Recall@5 = 0.958 — the ceiling for text-only approaches&lt;/li&gt;
&lt;li&gt;Article 05: Graph retrieval rescues Q8, but BFS noise breaks Q1 — it's a one-for-one trade&lt;/li&gt;
&lt;li&gt;Articles 06 &amp;amp; 07: Structure-aware embedding and hybrid search can't actually bridge the gap&lt;/li&gt;
&lt;li&gt;Article 08: Three orthogonal paths — vector for semantics, graph for structure, symbol for exact matches — route by query intent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of that was measured on a 30-function toy codebase. The toy was honest. But it was still a toy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Today we change the venue.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;LightRAG is one of the highest-starred open-source knowledge graph RAG frameworks on GitHub. The codebase has been fully indexed by &lt;code&gt;codebase-memory-mcp&lt;/code&gt;: &lt;strong&gt;20,674 nodes, 94,517 edges&lt;/strong&gt;, covering 409 Python files and 101 TypeScript files (Web UI). That's a medium-scale real project — large enough to make everything from the earlier experiments matter.&lt;/p&gt;

&lt;p&gt;This article's job is straightforward: take three real questions, fire each one down the appropriate retrieval path, and spread the results flat so you can see exactly what each path delivers.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Quick Map Before We Start
&lt;/h2&gt;

&lt;p&gt;Before firing queries, one orientation pass.&lt;/p&gt;

&lt;p&gt;LightRAG's name might imply a simple retrieval utility, but the actual code structure is considerably richer. Running &lt;code&gt;get_architecture&lt;/code&gt; reveals the most important signal first: &lt;strong&gt;layer boundaries&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;entry layer:   kg/, chunker/        ← storage adapters, chunkers
core layer:    base, api, parser    ← abstract base classes, REST API, parsers
internal:      examples/, tests/   ← examples, tests (not exported)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This immediately tells you: if you want to understand 'how does LightRAG process a document,' the main arena is &lt;code&gt;lightrag/&lt;/code&gt;, the entry point is &lt;code&gt;lightrag.py&lt;/code&gt;, and storage implementations live in &lt;code&gt;kg/&lt;/code&gt; (10+ backends: Neo4j, MongoDB, Qdrant, Milvus, PostgreSQL, ...).&lt;/p&gt;

&lt;p&gt;Now for the retrieval runs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Path 1: Vector — Ask in Natural Language, Get a Concept Entry Point
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Question: What retrieval modes does LightRAG support, and when should each one be used?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a classic capability query: the caller doesn't know what the relevant function or class is called — they just know what they want to understand. This is exactly where the vector path excels.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool: &lt;code&gt;search_graph&lt;/code&gt; (BM25 + vector dual index)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;search&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;hybrid&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;retrieval&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;mode"&lt;/span&gt;
&lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Method&lt;/span&gt;
&lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Top result (the rest are test files):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;QueryParam  (lightrag/base.py, line 83)
  "local": Focuses on context-dependent information.
  "global": Utilizes global knowledge.
  "hybrid": Combines local and global retrieval methods.
  "naive": Performs a basic search without advanced techniques.
  "mix": Integrates knowledge graph and vector retrieval.
  "bypass": ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One query, straight to the source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QueryParam&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Configuration parameters for query execution in LightRAG.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;local&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;global&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hybrid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;naive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mix&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bypass&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mix&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;All six retrieval modes, right in the &lt;code&gt;QueryParam&lt;/code&gt; dataclass.&lt;/strong&gt; The docstring explains each one:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;local&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Local context retrieval, focuses on the entity neighborhood around the query&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;global&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Global knowledge retrieval, aggregates relationships across documents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hybrid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;local + global combined&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;naive&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Plain vector search, no knowledge graph&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mix&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Knowledge graph + vector fusion (the default)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bypass&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pass directly to LLM, skip retrieval entirely&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notice what was returned: a &lt;strong&gt;class definition&lt;/strong&gt;, not a function implementation. The vector path is highly effective at 'find the concept entry point' queries — you describe a feature, it returns the most relevant abstraction. From there you drill down.&lt;/p&gt;

&lt;p&gt;A second &lt;code&gt;search_graph&lt;/code&gt; call confirmed the pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query: "insert document knowledge graph extraction"
→ hit: _find_related_text_unit_from_entities (operate.py:5260)
       _find_related_text_unit_from_relations (operate.py:5511)
       run_rebuild_entities_relations (tools/rebuild_vdb.py:900)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The intent 'insert documents, extract knowledge graph' navigated directly to the extraction logic in &lt;code&gt;operate.py&lt;/code&gt; — not a pile of results that happen to contain the word 'insert'.&lt;/p&gt;




&lt;h2&gt;
  
  
  Path 2: Graph — Follow the Call Chain, Understand What a Function Triggers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Question: What does &lt;code&gt;ainsert()&lt;/code&gt; call? What is the full execution path for document ingestion?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a structural query: the caller knows the entry point name and wants to understand the complete execution path downstream. The graph path owns this category.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool: &lt;code&gt;trace_path&lt;/code&gt; (call graph BFS)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;function_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ainsert&lt;/span&gt;
&lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;calls&lt;/span&gt;
&lt;span class="na"&gt;direction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;outbound&lt;/span&gt;
&lt;span class="na"&gt;depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns (hop=1 direct callees, hop=2 indirect):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hop=1 direct:
  apipeline_enqueue_documents   (pipeline.py)
  apipeline_process_enqueue_documents   (pipeline.py)
  generate_track_id   (utils.py)
  resolve_chunk_options   (parser/routing.py)

hop=2 indirect (inside pipeline):
  _run_pipeline_batch
  _validate_and_fix_document_consistency
  _atomic_release_busy_or_consume_pending
  compute_mdhash_id
  sanitize_text_for_encoding
  normalize_document_file_path
  filter_keys        (BaseKVStorage)
  upsert             (BaseVectorStorage)
  get_by_id          (BaseVectorStorage)
  get_docs_by_statuses  (DocStatusStorage)
  get_namespace_data
  get_namespace_lock
  ...  (36 nodes total)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These 36 nodes form the complete document ingestion path. But the node list alone isn't the full story — the source code is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ainsert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;split_by_character&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Async insert documents with checkpoint support (fixed-token chunking only).

    SDK convenience entry point. It **always** chunks with the fixed-token
    (F) strategy: ``process_options`` is intentionally not passed, so the
    document runs the F chunker. ...

    The LightRAG **server / REST API does not call this method** — it
    ingests via :meth:`apipeline_enqueue_documents` +
    :meth:`apipeline_process_enqueue_documents` with a per-document
    ``process_options`` selector, which is how F/R/V/P are chosen there.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;chunk_opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;resolve_chunk_options&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addon_params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;split_by_character&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;split_by_character&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;split_by_character_only&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;split_by_character_only&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apipeline_enqueue_documents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_paths&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;track_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;chunk_opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apipeline_process_enqueue_documents&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;track_id&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a &lt;strong&gt;critical design decision buried in this source&lt;/strong&gt; that you would never see from the function name alone:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;ainsert&lt;/code&gt; only supports the fixed-token chunking strategy (F strategy). If you want recursive-character (R), semantic-vector (V), or paragraph-semantic (P) chunking, &lt;strong&gt;you cannot call &lt;code&gt;ainsert&lt;/code&gt;&lt;/strong&gt; — you must call &lt;code&gt;apipeline_enqueue_documents&lt;/code&gt; + &lt;code&gt;apipeline_process_enqueue_documents&lt;/code&gt; directly with an explicit &lt;code&gt;process_options&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Equally: LightRAG's REST API server doesn't call &lt;code&gt;ainsert&lt;/code&gt; either — it goes directly to the pipeline layer. So SDK users and REST API users are actually running different code paths.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is what the graph path uniquely delivers: not just 'here is a function,' but 'here is what role this function plays in the system.'&lt;/strong&gt; A vector search would probably return &lt;code&gt;ainsert&lt;/code&gt; for 'how to insert documents.' But it wouldn't tell you that this method is intentionally designed as a simplified F-only entry point, and what that means for how you should actually use it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Path 3: Symbol — Precise Hit, Zero Ambiguity
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Question: Which parts of the codebase call &lt;code&gt;BaseVectorStorage.upsert&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is an impact analysis query: the caller wants to do a refactor or security audit and needs to know every caller of a given interface. No semantic understanding is required — only precise matching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool: &lt;code&gt;search_code&lt;/code&gt; (graph-augmented grep)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BaseVectorStorage"&lt;/span&gt;
&lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;compact&lt;/span&gt;
&lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Results show &lt;code&gt;upsert&lt;/code&gt; (the core method of &lt;code&gt;BaseVectorStorage&lt;/code&gt;) has &lt;strong&gt;fan_in = 268&lt;/strong&gt; — one of the most heavily called methods in the entire project.&lt;/p&gt;

&lt;p&gt;A more targeted query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;pattern&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;QueryParam"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Immediately locates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;QueryParam   lightrag/base.py:83    (Class, in_degree=19)
  ↑ called by 19 locations:
  - lightrag/lightrag.py:2056  (method: query)
  - lightrag/lightrag.py:2091  (method: aquery)
  - lightrag/operate.py:4323   (_perform_kg_search)
  - lightrag/lightrag.py:2344  (aquery_llm)
  ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;19 callers, all precisely located with file and line number. If you're modifying &lt;code&gt;QueryParam&lt;/code&gt;'s interface — deprecating a mode, adding a parameter — this list is your blast radius assessment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The symbol path is graph-augmented grep.&lt;/strong&gt; Plain grep returns where a string appears. The symbol path also tells you each hit's position in the call graph — whether it's an entry point, who calls it, how high its in-degree is. That's enough to answer 'how big a change is this?' in seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  All Three in Combination: One Real Engineering Task, Three Perspectives
&lt;/h2&gt;

&lt;p&gt;The three examples above demonstrated each path independently. Now, a scenario closer to real engineering:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Task: Understand LightRAG's full document ingestion flow, in order to modify the chunking strategy&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a question an engineer would ask before making a feature change. The answer isn't in any single function — it needs multiple perspectives assembled into a map.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Vector path — locate the concept entry points&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;search_graph&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;document chunking strategy pipeline insert&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nf"&gt;ainsert &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lightrag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1428&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nf"&gt;ainsert_custom_chunks &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lightrag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;deprecated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nf"&gt;resolve_chunk_options &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The vector path reveals 'which entry points in this system relate to chunking,' and along the way flags that &lt;code&gt;ainsert_custom_chunks&lt;/code&gt; is deprecated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Graph path — trace the execution chain&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;trace_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ainsert&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;calls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;hop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;apipeline_enqueue_documents&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;resolve_chunk_options&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;hop&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;_run_pipeline_batch&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;various&lt;/span&gt; &lt;span class="n"&gt;Storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The graph path shows: chunking strategy selection happens in &lt;code&gt;resolve_chunk_options&lt;/code&gt; (before enqueue), actual chunking happens in &lt;code&gt;_run_pipeline_batch&lt;/code&gt; (pipeline execution), and the result gets written to multiple storage backends. If you want to change chunking strategy, modify &lt;code&gt;parser/routing.py&lt;/code&gt; — not &lt;code&gt;ainsert&lt;/code&gt; in &lt;code&gt;lightrag.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Symbol path — pin the interface definition&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;search_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;resolve_chunk_options&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;lightrag&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;chunk_strategy_key&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;lightrag&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;slim_chunk_options&lt;/span&gt;
&lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="n"&gt;lightrag&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;default_chunker_config&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The symbol path pins three related functions in &lt;code&gt;routing.py&lt;/code&gt;, with their exact reference locations in the &lt;code&gt;ainsert&lt;/code&gt; call chain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After three steps you know:&lt;/strong&gt; change chunking strategy in &lt;code&gt;parser/routing.py&lt;/code&gt;; &lt;code&gt;ainsert&lt;/code&gt; via SDK only supports F strategy, all others require calling the pipeline layer directly; storage writes are abstracted through &lt;code&gt;BaseVectorStorage.upsert&lt;/code&gt;, so chunking changes won't affect storage backends. That's a complete engineering change map — each path contributed exactly what it's best at.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Counter-Intuitive Finding: Scale Makes the Graph Path More Valuable
&lt;/h2&gt;

&lt;p&gt;On the toy codebase (30 functions), &lt;code&gt;trace_path&lt;/code&gt; expanded to a handful of nodes — the graph path's value wasn't obvious. On LightRAG (7,761 functions + 3,569 methods), the same call trace expanded to &lt;strong&gt;36 nodes&lt;/strong&gt; covering the complete path from user API to storage abstraction.&lt;/p&gt;

&lt;p&gt;This isn't linear growth — it's a &lt;strong&gt;scale amplification effect&lt;/strong&gt;: the larger the codebase, the richer any function's neighborhood, the harder it becomes for pure vector retrieval to surface structural relationships, and the greater the relative advantage of the graph path.&lt;/p&gt;

&lt;p&gt;This is the Q8 problem from Article 05 reflected in a real codebase. &lt;code&gt;ainsert&lt;/code&gt; and &lt;code&gt;_run_pipeline_batch&lt;/code&gt; are semantically distant — 'high-level document insertion API' vs 'low-level batch pipeline executor' — no embedding model would bring those two close. But the call graph connects them in one hop.&lt;/p&gt;

&lt;p&gt;When the question is 'what would change if I modify this?' or 'who calls this function?' — those questions have the same answer structure in a 5,000-function codebase as in a 30-function one: &lt;strong&gt;the answer is only in the graph.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Nine articles in, this series has tracked a single thread from first principles to production tooling: measure the ceiling of each single-path approach, identify where each fails, then design around the failure modes.&lt;/p&gt;

&lt;p&gt;A final statement of where each path belongs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vector path&lt;/strong&gt;: You don't know what the function is called, just what it does — &lt;code&gt;search_graph(query=...)&lt;/code&gt; is the first move&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graph path&lt;/strong&gt;: You know the entry point, want to understand its execution chain and blast radius — &lt;code&gt;trace_path&lt;/code&gt; is the workhorse
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Symbol path&lt;/strong&gt;: You know the exact function or class name, want its definition and all references — &lt;code&gt;search_code&lt;/code&gt; returns results in under a second&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't competing approaches. They're orthogonal dimensions. Any task that requires 'understand an unfamiliar codebase' needs all three to build a complete cognitive map.&lt;/p&gt;

&lt;p&gt;The central conclusion, one more time:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Codebase semantic understanding is multi-dimensional. Every single signal has a blind spot. Pick the right tool, keep the paths distinct — that's what engineering-quality retrieval actually looks like.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;For more details on &lt;code&gt;codebase-memory-mcp&lt;/code&gt; and its full feature set, visit the GitHub repository.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Check out &lt;a href="https://primeskills.store" rel="noopener noreferrer"&gt;PrimeSkills&lt;/a&gt; — a curated marketplace of AI agents and skills that have been validated in real-world, enterprise-grade workflows. No fluff, just what actually works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Find more useful knowledge and interesting products on my &lt;a href="https://home.wonlab.top/en" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>codebase</category>
      <category>knowledgebase</category>
    </item>
    <item>
      <title>Open Source Project #143: Better Harness — A Five-Dimension Workflow Evaluator for AI Coding Agents That Reviews the Loop, Not the Diff</title>
      <dc:creator>WonderLab</dc:creator>
      <pubDate>Fri, 07 Aug 2026 05:26:15 +0000</pubDate>
      <link>https://dev.to/wonderlab/open-source-project-143-better-harness-a-five-dimension-workflow-evaluator-for-ai-coding-agents-5ada</link>
      <guid>https://dev.to/wonderlab/open-source-project-143-better-harness-a-five-dimension-workflow-evaluator-for-ai-coding-agents-5ada</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"Your AI coding agent generates code fast. Your workflow is the bottleneck."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is &lt;strong&gt;article #143&lt;/strong&gt; in the "One Open Source Project a Day" series. Today's project is &lt;strong&gt;Better Harness&lt;/strong&gt; — QoderAI's open-source evaluation tool that analyzes the workflow surrounding an AI coding agent, not just the code it produces.&lt;/p&gt;

&lt;p&gt;Most evaluations of AI coding agents focus on output quality: test pass rates, defect density, functional correctness. Better Harness takes a different position: &lt;strong&gt;agents fail not because the model is weak, but because the surrounding workflow has gaps.&lt;/strong&gt; Fuzzy goals, no reusable execution paths, unvalidated changes, bypassed quality checks, lessons that evaporate after each session — these problems don't show up in diffs. They only appear when you audit the workflow itself.&lt;/p&gt;

&lt;p&gt;Better Harness collects project and session evidence, evaluates workflow health across five dimensions, and outputs prioritized findings — each with a scoped, actionable repair plan.&lt;/p&gt;

&lt;p&gt;1,500 Stars. MIT license. Supports Claude Code, Codex, GitHub Copilot, Cursor, and Qwen Code.&lt;/p&gt;

&lt;h3&gt;
  
  
  What You'll Learn
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Better Harness's core model: feedforward guides and feedback sensors&lt;/li&gt;
&lt;li&gt;What each of the five dimensions evaluates and what evidence counts&lt;/li&gt;
&lt;li&gt;The architecture: three independent evidence agents running in parallel&lt;/li&gt;
&lt;li&gt;Report structure: findings, repair plans, historical trends&lt;/li&gt;
&lt;li&gt;Why it's "deliberately honest": never inferring usage from configuration presence&lt;/li&gt;
&lt;li&gt;Installation and usage in Claude Code and Codex&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Experience using Claude Code, Codex, Cursor, or a similar AI coding tool&lt;/li&gt;
&lt;li&gt;Familiarity with AGENTS.md, Hooks, and Skills helps but isn't required&lt;/li&gt;
&lt;li&gt;Basic awareness of software quality practices (CI/CD, testing, code review)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Project Background
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Problem: Agents Move Fast, Workflows Stay Weak
&lt;/h3&gt;

&lt;p&gt;AI coding agents introduce a new failure mode: speed. An agent can finish in minutes what previously took hours — but that speed also skips the slow steps that were actually valuable. Careful goal understanding, working within proven paths, validating changes, passing human review.&lt;/p&gt;

&lt;p&gt;Better Harness identifies five common workflow failure patterns:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Failure Pattern&lt;/th&gt;
&lt;th&gt;How It Shows Up&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fuzzy goals&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Agent doesn't know what "done" looks like; keeps iterating in the wrong direction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Improvised execution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Starting from scratch each time; no reusable execution paths&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Unvalidated changes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Code got modified, but no evidence confirms the modification worked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bypassed safeguards&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AI speed made quality gates optional&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lost lessons&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Insights from this session don't help the next one&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These five problems are typically invisible in code diffs. The code passes review. The workflow problems persist and repeat on the next task.&lt;/p&gt;

&lt;h3&gt;
  
  
  QoderAI and Qoder
&lt;/h3&gt;

&lt;p&gt;Better Harness is built by QoderAI, who also makes a desktop AI coding agent called Qoder. Better Harness is natively integrated in Qoder; the open-source version runs as a plugin in other major agents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Stats
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;⭐ GitHub Stars: &lt;strong&gt;1,500+&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🍴 Forks: 123+&lt;/li&gt;
&lt;li&gt;📄 License: MIT&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime&lt;/strong&gt;: Node.js 22.20.0–25.0.0&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Core Concept: Feedforward + Feedback Dual Signals
&lt;/h2&gt;

&lt;p&gt;Better Harness's evaluation model rests on one framework: effective agent workflows need two signal types working together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Before work starts                After / during work
──────────────────                ──────────────────
Feedforward guides                Feedback sensors

AGENTS.md                         Linters
Spec documents                    Test suites
Skills (reusable steps)           Hooks (event-triggered)
Acceptance criteria               Evaluation agents
                                  Diagnostics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Feedforward guides&lt;/strong&gt; steer the agent before it acts — AGENTS.md establishes rules and goals, specs define task scope, Skills provide proven execution paths, acceptance criteria define what "done" looks like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feedback sensors&lt;/strong&gt; observe results after the agent acts — linters check conventions, test suites validate functionality, Hooks capture signals on trigger events, evaluation agents score output quality.&lt;/p&gt;

&lt;p&gt;The core indicator of a healthy workflow: &lt;strong&gt;both sides are operating, and their results leave evidence.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Five Dimensions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Dimension 1: Task Understanding
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Core question&lt;/strong&gt;: Does the agent know what the goal is and what "done" looks like?&lt;/p&gt;

&lt;p&gt;What gets evaluated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether AGENTS.md exists and contains effective rules and goal definitions&lt;/li&gt;
&lt;li&gt;Whether spec documents define task scope&lt;/li&gt;
&lt;li&gt;Whether explicit acceptance criteria tell the agent when to stop&lt;/li&gt;
&lt;li&gt;Whether the agent can identify the project starting point and appropriate change granularity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Common failure&lt;/strong&gt;: Vague goal descriptions ("improve login flow" vs. "add specific error messages for each error state") leave the agent without a clear stopping point, producing over-engineering or repeated course corrections.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dimension 2: Controlled Execution
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Core question&lt;/strong&gt;: Is the agent working on supported, repeatable paths?&lt;/p&gt;

&lt;p&gt;What gets evaluated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skills configuration: whether reusable SDLC execution steps exist&lt;/li&gt;
&lt;li&gt;MCP tool availability and boundary settings&lt;/li&gt;
&lt;li&gt;Sandbox boundaries: whether agent permissions are appropriately scoped&lt;/li&gt;
&lt;li&gt;Whether the agent uses proven paths rather than improvising each time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Common failure&lt;/strong&gt;: Reinventing the execution process for each task; agent with excessive permissions making changes beyond task scope; no reusable steps, so similar tasks produce inconsistent quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dimension 3: Change Validation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Core question&lt;/strong&gt;: Is there evidence the change actually works?&lt;/p&gt;

&lt;p&gt;What gets evaluated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether tests actually ran after the change (not just "tests exist")&lt;/li&gt;
&lt;li&gt;Whether lint checks actually ran after the change&lt;/li&gt;
&lt;li&gt;Whether Hooks captured validation signals&lt;/li&gt;
&lt;li&gt;Whether re-validation happened after validation failures&lt;/li&gt;
&lt;li&gt;Whether diagnostic tools were actually used&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key distinction&lt;/strong&gt;: Better Harness separates "tests are configured" from "tests were executed." A project can have a complete test suite, but without evidence the agent ran tests after changes, this dimension doesn't score for that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dimension 4: Reliable Delivery
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Core question&lt;/strong&gt;: Did AI speed bypass quality gates?&lt;/p&gt;

&lt;p&gt;What gets evaluated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether task acceptance has verifiable evidence (not just "code is done")&lt;/li&gt;
&lt;li&gt;Whether high-risk operations have human approval paths&lt;/li&gt;
&lt;li&gt;Whether rollback mechanisms exist&lt;/li&gt;
&lt;li&gt;Whether CI/CD pipelines are part of the agent's workflow&lt;/li&gt;
&lt;li&gt;Whether human review actually happened&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Core concern&lt;/strong&gt;: An agent can make extensive modifications without anyone noticing. Reliable Delivery evaluates what validation gates those modifications passed before delivery.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dimension 5: Learning Capture
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Core question&lt;/strong&gt;: Do lessons from this task improve the next one?&lt;/p&gt;

&lt;p&gt;What gets evaluated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether recurring issues get distilled into reusable Rules or Skills&lt;/li&gt;
&lt;li&gt;Whether Loop Discovery is working (pattern recognition generating suggestions)&lt;/li&gt;
&lt;li&gt;Whether the Memory system is in use&lt;/li&gt;
&lt;li&gt;Whether similar tasks reuse existing experience or start from scratch each time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;One signal&lt;/strong&gt;: Better Harness flags "long sessions" (over 45 minutes) for human review — these often indicate the agent spent significant effort on exploration that should be captured to avoid repetition.&lt;/p&gt;




&lt;h2&gt;
  
  
  Analysis Architecture: Three Independent Evidence Agents
&lt;/h2&gt;

&lt;p&gt;Better Harness doesn't use a single agent for all analysis. Three independent read-only sub-agents collect different evidence categories in parallel, and a lead agent synthesizes the results only after independent collection completes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Three independent sub-agents (parallel)
├── Agent 1: Customization asset analysis
│       → Completeness of Rules, Skills, Hooks, and configs
│
├── Agent 2: Real task session analysis
│       → What the agent actually did and how it performed
│
└── Agent 3: Project engineering foundation analysis
        → Whether project structure supports the agent workflow

        ↓ (after independent collection)

Lead Agent: Unified analysis + report generation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why keep them independent&lt;/strong&gt;: Running the three sub-agents separately prevents one category's conclusions from skewing another's interpretation. If Agent 1 finds complete Skills configuration, that shouldn't influence how Agent 2 reads the actual session records — Agent 2 looks at execution evidence only.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Missing evidence handling&lt;/strong&gt;: Unobserved behavior is never inferred. No test execution records → Change Validation is unknown, not assumed based on the presence of test files in the project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Report Structure
&lt;/h2&gt;

&lt;p&gt;Running the analysis produces three files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;report.html&lt;/strong&gt;: Self-contained visual report (open directly in a browser)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;report.md&lt;/strong&gt;: Markdown format for version control and team sharing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;findings.json&lt;/strong&gt;: Structured data for programmatic processing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What the Report Contains
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Five-dimension overview&lt;/strong&gt;: Scored bar chart per dimension + count of related findings&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope snapshot&lt;/strong&gt;: Current configured asset inventory — Rules count, Skills count, custom Agents, MCP tools, Memories, Hooks&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prioritized findings&lt;/strong&gt;: Each finding includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Priority (High / Medium / Low)&lt;/li&gt;
&lt;li&gt;Owning dimension&lt;/li&gt;
&lt;li&gt;Cause: the specific gap in current configuration&lt;/li&gt;
&lt;li&gt;Expected Output: what a successful fix achieves&lt;/li&gt;
&lt;li&gt;Fix instructions: an editable pre-filled prompt starting with &lt;code&gt;/harness&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Session observations&lt;/strong&gt;: Representative patterns extracted from analyzed sessions; sessions over 45 minutes flagged separately&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Historical trend&lt;/strong&gt;: Results compared across multiple runs, showing dimension-level change over time&lt;/p&gt;

&lt;h3&gt;
  
  
  Deliberately Conservative Scoring
&lt;/h3&gt;

&lt;p&gt;Better Harness has an explicit scoring constraint:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Configured assets can establish that a mechanism exists, but only linked task evidence can establish that it was used."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A project with complete Skills configuration doesn't get full marks on Controlled Execution without evidence of actual usage. &lt;strong&gt;Passing a current check proves the intervention was exercised; only a comparable later result can prove the loop improved.&lt;/strong&gt; The history view shows recorded trends, not causal proof of improvement.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation and Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Claude Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/plugin marketplace add QoderAI/better-harness
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Other Platforms
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Install Method&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Codex Desktop&lt;/td&gt;
&lt;td&gt;Settings &amp;gt; Plugins &amp;gt; Add from Marketplace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Codex CLI&lt;/td&gt;
&lt;td&gt;&lt;code&gt;codex plugin marketplace add [repo URL]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub Copilot&lt;/td&gt;
&lt;td&gt;&lt;code&gt;copilot plugin marketplace add QoderAI/better-harness&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qwen Code&lt;/td&gt;
&lt;td&gt;&lt;code&gt;qwen extensions install QoderAI/better-harness&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cursor&lt;/td&gt;
&lt;td&gt;Clone repo locally, source-local install&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Qoder&lt;/td&gt;
&lt;td&gt;Natively built in — no install needed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Run Analysis
&lt;/h3&gt;

&lt;p&gt;After installation, in any supported agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/better-harness analyze this project&lt;span class="s1"&gt;'s AI coding workflow and generate an evidence-backed report
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outputs a self-contained &lt;code&gt;report.html&lt;/code&gt; + &lt;code&gt;report.md&lt;/code&gt; + &lt;code&gt;findings.json&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Repair Workflow
&lt;/h3&gt;

&lt;p&gt;Better Harness never modifies anything directly — it identifies gaps and provides the fix starting point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;High-priority finding → click "Plan a fix"
    ↓
Fix detail opens:
  - Cause: the specific config gap
  - Expected Output: what a fix achieves
  - Fix instructions: editable pre-filled prompt
    ↓
Click "Start Fix" → launches as a Quest task
    ↓
Agent executes fix in an inspectable, reversible Quest task
    ↓
Re-run /better-harness → confirm the loop actually improved
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fix results can be distilled further into Rules, Skills, and Memories, letting subsequent tasks benefit directly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🌟 &lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/QoderAI/better-harness" rel="noopener noreferrer"&gt;QoderAI/better-harness&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📖 &lt;strong&gt;Docs&lt;/strong&gt;: &lt;a href="https://docs.qoder.com/user-guide/knowledge-engine/better-harness" rel="noopener noreferrer"&gt;docs.qoder.com/user-guide/knowledge-engine/better-harness&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Better Harness solves a meta-level problem: an AI coding agent's output quality depends on the surrounding workflow, not just the model's capability. The same Claude Sonnet in a workflow with complete AGENTS.md, clear acceptance criteria, post-change test runs, and experience distilled into Skills produces significantly better outcomes than in a workflow without any of these.&lt;/p&gt;

&lt;p&gt;The five-dimension framework makes "workflow health" measurable — not "the workflow feels off" but "Change Validation scored low because no test execution records were found." Priority ordering tells you what to fix first. Repair plans tell you how. The historical trend confirms fixes actually worked.&lt;/p&gt;

&lt;p&gt;The deliberately conservative scoring is what makes this tool trustworthy. It doesn't infer "tests ran" from "test files exist." It doesn't claim "the repair caused the improvement" from historical score increases. That honesty means the output can be acted on rather than second-guessed.&lt;/p&gt;

&lt;p&gt;If you're using Claude Code, Codex, or Cursor and your sessions occasionally feel inefficient — goals that took too long to clarify, changes that broke unexpectedly, the same problems recurring — &lt;code&gt;/better-harness&lt;/code&gt; surfaces which part of the loop is actually broken.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Explore &lt;a href="https://primeskills.store" rel="noopener noreferrer"&gt;PrimeSkills&lt;/a&gt; — A marketplace for handpicked AI Agents and skills. Each is validated in real enterprise workflows, stripping away hype and keeping only what truly works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Welcome to my &lt;a href="https://home.wonlab.top/en" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt; for more useful insights and interesting products.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>agents</category>
      <category>harness</category>
    </item>
    <item>
      <title>Codebase Knowledge Base Series (08): Production Architecture — How to Combine Vector, Graph, and Symbol Indexes</title>
      <dc:creator>WonderLab</dc:creator>
      <pubDate>Thu, 06 Aug 2026 01:58:35 +0000</pubDate>
      <link>https://dev.to/wonderlab/codebase-knowledge-base-series-08-production-architecture-how-to-combine-vector-graph-and-nph</link>
      <guid>https://dev.to/wonderlab/codebase-knowledge-base-series-08-production-architecture-how-to-combine-vector-graph-and-nph</guid>
      <description>&lt;h2&gt;
  
  
  We Spent Five Articles Measuring the Boundary — Now We Need a Bigger Map
&lt;/h2&gt;

&lt;p&gt;If you've read straight through from Article 03, then together we've laid to rest a ghost that haunted us for five full articles — Q8.&lt;/p&gt;

&lt;p&gt;Let's recap the long chase. Q8 is &lt;code&gt;process payment and create Stripe charge&lt;/code&gt;, and its ground truth includes &lt;code&gt;calculate_order_total&lt;/code&gt;. We threw every trick in the text-retrieval book at catching it: the vector baseline couldn't; three chunking strategies couldn't; encoding &lt;code&gt;called_by&lt;/code&gt; into the embedding only nudged similarity to 0.51 and still couldn't; and finally even the industry's universally endorsed "ultimate weapon" — BM25 + vector hybrid search — crashed, not only failing to fix Q8 but dragging the total from 0.958 down to 0.931.&lt;/p&gt;

&lt;p&gt;The five-article conclusion condensed into a single sentence:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The link between &lt;code&gt;calculate_order_total&lt;/code&gt; and "Stripe payment" is purely &lt;strong&gt;structural&lt;/strong&gt;. It lives on an edge in the call graph (it's called by &lt;code&gt;process_checkout&lt;/code&gt;), and is written in no function's text. Therefore any pure-text approach — vector, BM25, hybrid — physically cannot reach it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That sentence is a hard, number-backed conclusion we bought with five articles of experiments. It's valuable — but it's only one piece of the puzzle.&lt;/p&gt;

&lt;p&gt;Because while chasing Q8, we incidentally mapped out the territory of three distinct retrieval routes: &lt;strong&gt;what vector is good at and what it can't reach; what graph is good at and what it costs; and a whole class of query — "where is the function named &lt;code&gt;validate_jwt_token&lt;/code&gt;" — that needs no semantics at all, where exact matching returns in a millisecond.&lt;/strong&gt; Stitch those three territories together and you get the complete map of codebase retrieval.&lt;/p&gt;

&lt;p&gt;So this article shifts altitude. The previous five held a magnifying glass to the recall of a single retrieval algorithm; this one pulls back to satellite view to draw a system architecture: &lt;strong&gt;how the vector, graph, and symbol signals should actually be organized into a working production system.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A heads-up to keep in mind before you read: &lt;strong&gt;anything in this article with a concrete Recall number is a conclusion already validated by experiments in the previous five articles; anything describing "how to design the system" is an engineering design recommendation derived from those conclusions, not yet validated end-to-end on a full production system.&lt;/strong&gt; I'll flag this repeatedly at the key points — don't mistake design recommendations for experimental conclusions.&lt;/p&gt;




&lt;h2&gt;
  
  
  First, Draw the Three Signals' Territories Clearly
&lt;/h2&gt;

&lt;p&gt;Before designing anything, let's put the three territories the previous five articles measured out on the table. This is the bedrock of the entire architecture, and every brick in that bedrock carries an experiment number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Route one: vector retrieval — the home turf of semantic-similarity queries.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the baseline established in Article 03 and repeatedly validated in the four that followed: AST function-level chunking + raw-code embedding, Recall@5 = 0.958, the strongest vector baseline among all text approaches (experimentally validated). It excels at queries of the form "describe a capability in natural language, find the implementation" — say "find the function that encrypts and securely stores passwords" and it hits &lt;code&gt;hash_password&lt;/code&gt;, even if you never mentioned the function name.&lt;/p&gt;

&lt;p&gt;Its boundary is measured just as clearly: the semantic gap can't be filled (Articles 06, 07). &lt;code&gt;calculate_order_total&lt;/code&gt; and "Stripe payment" are genuinely different things in the real world, and no embedding trick can pull them closer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Route two: graph retrieval — the home turf of structural-relationship queries.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Article 05 proved that the structural information carried by the call graph is an &lt;strong&gt;orthogonal truth vector can't reach&lt;/strong&gt; (experimentally validated): Q8 was scooped back in two hops via the &lt;code&gt;process_checkout → calculate_order_total&lt;/code&gt; call edge. But Article 05 also measured its cost — naive BFS 2-hop expansion bloats the candidate set, squeezing Q1's correctly-hit &lt;code&gt;verify_password&lt;/code&gt; out of the top-5, one fixed and one broken, netting zero.&lt;/p&gt;

&lt;p&gt;The conclusion is subtle: &lt;strong&gt;right direction, crude method.&lt;/strong&gt; The graph signal is valuable, but "doing naive BFS expansion after retrieval" is the wrong way to use it. This lesson directly determines graph retrieval's role in the architecture below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Route three: symbol retrieval — the home turf of exact-match queries.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The previous five articles didn't run dedicated experiments on this route, but its value is self-evident and needs no proof: when your query is itself a precise symbol — "where is the function named &lt;code&gt;validate_jwt_token&lt;/code&gt; defined," "which files import &lt;code&gt;redis.Redis&lt;/code&gt;" — you don't want "semantically close," you want "literal exact hit." Here vector is a sledgehammer for a nut, and easily led astray by semantic approximation; a grep or a function-name → file → line-number symbol table returns precisely in under 10 milliseconds.&lt;/p&gt;

&lt;p&gt;Place the three territories side by side and a beautiful fact emerges — &lt;strong&gt;they barely overlap:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Query type                          Best route    Example
────────────────────────────────  ──────────  ─────────────────────────
NL capability description, find impl   Vector     "find the function that validates JWT"
Exact symbol name / import             Symbol     "where is validate_jwt_token"
Structural relation / call chain       Graph      "who calls createPayment"
────────────────────────────────  ──────────  ─────────────────────────
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "four knowledge layers" framework from Article 01 maps neatly onto this: syntax layer (AST/symbol), semantic layer (vector), architecture layer (graph), plus the intent layer (Git history). &lt;strong&gt;The first principle of a production system is to accept that these four signals are each independent and none is dispensable — there is no single "best retrieval method" that dominates all four layers.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Principle One: Multi-Path Retrieval, Each to Its Own Job
&lt;/h2&gt;

&lt;p&gt;The first principle, and the most counterintuitive: &lt;strong&gt;stop looking for "the one best retrieval method."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's exactly what we did for five articles — endlessly asking "does vector work? does BM25 work? does hybrid work?", each time betting one route could dominate every query. Five straight losses later, we were forced to admit: for structural queries like Q8, the text route physically can't reach.&lt;/p&gt;

&lt;p&gt;Flip the framing: &lt;strong&gt;not one all-rounder, but let each route do only what it's best at.&lt;/strong&gt; Vector for semantics, graph for structure, symbol for exact matching — three routes retrieve in parallel, each covering its own territory.&lt;/p&gt;

&lt;p&gt;An analogy: this is like a hospital's triage desk. You wouldn't expect one general practitioner to handle heart bypass, tooth extraction, and blood tests all at once. You triage first — fractures to orthopedics, toothaches to dental, bloodwork to the lab. &lt;strong&gt;Each department is an expert in its own domain and an amateur outside it.&lt;/strong&gt; Retrieval is the same — using vector for exact symbol matching is like having your dentist do the heart bypass; sure, he technically knows what a heart is, but you really don't want him operating.&lt;/p&gt;

&lt;p&gt;This principle flows directly from the previous five articles' lessons: we've already used five articles' worth of failures to prove what happens when you force one signal to do a job it's bad at. Vector was forced to reach Q8's structural relationship, tried for five articles, and never reached it. So let graph do that job and let vector return to its semantic home turf.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Flag:&lt;/strong&gt; "Multi-path retrieval" as an architectural direction is a design principle derived directly from the experimental conclusions of Articles 05/07. Each route's territory is experimentally backed (vector 0.958, graph fixing Q8, symbol needing no experiment), but "the overall Recall after combining three routes into a full system" has no end-to-end experimental data yet — this is a design recommendation, not an experimental conclusion.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Principle Two: Query Routing, Activate the Right Path by Intent
&lt;/h2&gt;

&lt;p&gt;With three retrieval routes, a question immediately arises: &lt;strong&gt;when a query comes in, which routes do we activate?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If we blindly run all three every time and then fuse, it's not just slow — the routes pollute each other. Article 07 demonstrated this graphically: vector scored a perfect 1.00 on Q7, but BM25 dragged it to 0.67 by over-matching the high-frequency generic word "execute," and once RRF fused them, the good route got pulled down with the bad. &lt;strong&gt;Blind fusion lets the route that's bad at a query drag down the route that's good at it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So we need a &lt;strong&gt;Query Router&lt;/strong&gt;: first judge what type the query is, then decide which routes to activate.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Query "where is the validate_jwt_token function"   → Symbol route (exact match)
Query "the function that validates JWT tokens"      → Vector route (semantic)
Query "what does createPayment call"                → Graph route (structure)
Query "the full payment flow call chain"            → Graph route + Vector route (mixed)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Implementation doesn't require reaching for an LLM up front. The vast majority of query intents can be recognized by a handful of rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The query contains a precise identifier (a &lt;code&gt;snake_case&lt;/code&gt;/&lt;code&gt;camelCase&lt;/code&gt; function name, an &lt;code&gt;import&lt;/code&gt;ed module name) → prefer the symbol route.&lt;/li&gt;
&lt;li&gt;Structural keywords appear — "who calls," "what does it depend on," "call chain," "full flow" → activate the graph route.&lt;/li&gt;
&lt;li&gt;Everything else, natural-language description → the vector route.&lt;/li&gt;
&lt;li&gt;Compound queries (both structural intent and semantic description) → multiple routes jointly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Edge cases the rules can't classify can fall back to a small model for assistance — but that's not a necessity; rules cover the overwhelming majority of scenarios.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Flag (important):&lt;/strong&gt; The "query routing" here is a &lt;strong&gt;pseudocode-level design concept, not an experimentally validated result&lt;/strong&gt;. The "query → route" mapping table above is a set of routing rules I hand-designed based on the three territories; it aligns with the previous five articles' experimental intuition, but questions like "how accurate is the routing, how costly is a misroute" have not been experimented on in this series. Please read it as a design recommendation.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Principle Three: Graph Retrieval Is a First-Class Citizen, Not a Post-Processing Bolt-On
&lt;/h2&gt;

&lt;p&gt;This is the single most important shift in the whole architecture, and a direct correction of Article 05's failure.&lt;/p&gt;

&lt;p&gt;Recall why Article 05 crashed: its flow was &lt;strong&gt;vector-retrieve the top-3 seeds first, then BFS-expand the graph from the seeds&lt;/strong&gt;. Graph traversal was a post-processing step &lt;strong&gt;trailing behind&lt;/strong&gt; vector. That order was wrong — it treated graph as a patch on vector, letting the "structurally related but query-irrelevant" functions dragged in by graph expansion pollute vector's ranking and break Q1.&lt;/p&gt;

&lt;p&gt;The right approach promotes graph retrieval to a &lt;strong&gt;first-class retrieval route on equal footing with vector&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The graph index and vector index are built in parallel&lt;/strong&gt;, both independent first-class retrieval entry points, neither depending on the other.&lt;/li&gt;
&lt;li&gt;The vector route takes its own top-k; the graph route &lt;strong&gt;executes independently&lt;/strong&gt; — it identifies the function/module names mentioned in the query and directly traverses the graph (along &lt;code&gt;CALLS&lt;/code&gt;/&lt;code&gt;CALLED_BY&lt;/code&gt; edges), returning structurally related functions.&lt;/li&gt;
&lt;li&gt;The two routes' results are &lt;strong&gt;fused&lt;/strong&gt; at the end. Note this fusion is not the context-blind RRF of Article 07, but a &lt;strong&gt;weighted merge by query type&lt;/strong&gt;: the graph route weighs high for structural queries, the vector route weighs high for semantic ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One diagram makes the shift clear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    ❌ Article 05 (graph as a post-processing patch)
    Query → Vector top-k → BFS expand → rerank
                            ↑ graph here, trailing vector, polluting the ranking

    ✅ Production architecture (graph as an equal first-class citizen)
    Query ─┬─→ Vector route ─┐
           └─→ Graph route  ─┴─→ weighted fusion by query type → results
              two routes in parallel, each retrieving independently
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why does this change solve Article 05's problem? Because Article 05's root cause was "graph expansion bloated vector's candidate set and diluted vector's ranking." When the graph route becomes an independent route with its own retrieval logic and trigger conditions (Article 07's ending recommended: only trigger on high-confidence functions, only 1 hop, filter neighbors by business rules), it no longer indiscriminately stuffs noise into vector's candidate pool. &lt;strong&gt;The graph route scoops back Q8's &lt;code&gt;calculate_order_total&lt;/code&gt;, the vector route holds Q1's &lt;code&gt;verify_password&lt;/code&gt;, each minds its own business, no interference.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Flag:&lt;/strong&gt; "Graph as a first-class citizen, weighted fusion by query type" is a design-correction direction derived from the failures of Articles 05/07. Article 05's "graph post-processing pollutes ranking" is an &lt;strong&gt;experimentally validated failure&lt;/strong&gt;; but "parallel first-class citizen + weighted fusion can hold both Q1 and Q8 at once" is a &lt;strong&gt;design inference, not yet validated by experiments in this series&lt;/strong&gt;. The direction has experimental backing; the specific fusion weights and trigger conditions need the upcoming hands-on article to tune.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Principle Four: Incremental Updates, Never Full Rebuilds
&lt;/h2&gt;

&lt;p&gt;The first three principles solve "how to query"; the fourth tackles a more brutal engineering reality: &lt;strong&gt;code changes every day.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The previous five articles all ran on a static 28-function toy dataset. But a real project isn't a specimen — dozens to hundreds of commits a day, functions added/removed/modified, signatures changing, call relationships rewiring. If the indexing strategy is "full rebuild every time," then for a codebase of hundreds of thousands of lines, building the vector index alone takes tens of minutes, and the graph and symbol table have to be fully recomputed along with it. A developer waiting ten minutes for re-indexing after changing one line — no one will use that system.&lt;/p&gt;

&lt;p&gt;So the fourth principle: &lt;strong&gt;Git diff-driven incremental updates, never full rebuilds.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Three specifics:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Git diff-driven.&lt;/strong&gt; When a commit comes in, first compute exactly which files and functions it changed, and re-index only those change points. For untouched functions, not a single byte of their embedding, graph nodes, or symbol-table entries needs recomputing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Change propagation.&lt;/strong&gt; This one is easily overlooked but crucial. A function change isn't isolated — if &lt;code&gt;create_payment_intent&lt;/code&gt;'s signature changes, then all functions that call it need their call-graph edges updated too. So incremental updates aren't just "recompute changed functions" — they must also &lt;strong&gt;propagate the change to affected neighbors along the call graph&lt;/strong&gt;. This is yet another benefit of treating graph as a first-class citizen: the graph structure itself is the propagation path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Version snapshots.&lt;/strong&gt; Support querying historical versions by commit hash — which connects to Article 01's fourth layer, the intent layer. "What did this function look like three months ago," "which commit introduced this line and what problem was it solving" — these queries want not the current code but the code's &lt;strong&gt;evolution history&lt;/strong&gt;, and the answer lives in Git.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    Code Change (git commit)
             │
       ┌─────▼──────┐
       │  Git Diff  │   ← find only changed files / functions
       └─────┬──────┘
             │
       ┌─────▼──────┐
       │ AST Parser │   ← re-parse only changed files
       └──┬──────┬──┘
          │      │
      ┌───▼──┐ ┌─▼──────┐
      │Embed │ │ Graph  │   ← two routes update incrementally in parallel
      │Update│ │ Update │      Graph also propagates changes
      └──────┘ └────────┘      to neighbors along call edges
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Flag:&lt;/strong&gt; Incremental updating is a &lt;strong&gt;pure design recommendation&lt;/strong&gt; — all five prior articles experimented on a static dataset and ran no incremental-update experiments whatsoever. But this direction is uncontroversial — it's standard equipment for any production-grade indexing system, and a direct response to the "dynamism is the biggest challenge" point Article 01 already made.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Complete System Architecture
&lt;/h2&gt;

&lt;p&gt;Assemble the four principles and you get a complete system architecture. View it from two angles: what happens at &lt;strong&gt;query time&lt;/strong&gt;, and what happens at &lt;strong&gt;index time&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query flow (online, when a user issues a query):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                        Query
                          │
                   ┌──────▼──────┐
                   │Query Router │  ← recognize query intent (rules first)
                   └──┬───┬───┬──┘
                      │   │   │
              ┌───────▼┐ ┌▼──────┐ ┌▼────────┐
              │ Vector │ │ Graph │ │ Symbol  │
              │ Index  │ │ Index │ │ Index   │
              │(AST +  │ │(CALLS/│ │(grep /  │
              │embedding│ │CALLED_│ │AST      │
              │)       │ │BY)    │ │symbols) │
              └───┬────┘ └──┬────┘ └────┬────┘
                  │         │           │
              ┌───▼─────────▼───────────▼────┐
              │        Result Merger          │
              │  (weighted merge by query     │
              │   type, deduplicate)          │
              └──────────────┬────────────────┘
                             │
                        Top-k Results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three index routes retrieve in parallel (the Router decides which to activate), then the Result Merger merges by query-type weighting, deduplicates, and produces the final results. Note the Merger isn't a blind RRF — it knows whether this is a structural or a semantic query and adjusts each route's weight accordingly. This is exactly what Article 07 taught us: &lt;strong&gt;fusion must be context-aware, or the good route gets dragged down by the bad.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Index flow (offline, Git hook triggered):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's the Git diff-driven incremental-update diagram from the previous section. The three index routes update incrementally in parallel on commit, with the graph index additionally handling change propagation.&lt;/p&gt;

&lt;p&gt;Put the two diagrams together and you have the full picture of this architecture: &lt;strong&gt;at query time, three routes retrieve in parallel and fuse with intent-aware weighting; at index time, Git diff drives three routes' parallel incremental updates.&lt;/strong&gt; Every design decision traces to an experimental lesson from the previous five articles.&lt;/p&gt;




&lt;h2&gt;
  
  
  Implementation Complexity of Each Index Layer
&lt;/h2&gt;

&lt;p&gt;Design is design; when it comes to landing it, you need to know each route's engineering cost. The table below lays out the three routes (plus the intent layer): build cost, update cost, query latency, applicable scenarios.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Index type&lt;/th&gt;
&lt;th&gt;Build cost&lt;/th&gt;
&lt;th&gt;Update cost&lt;/th&gt;
&lt;th&gt;Query latency&lt;/th&gt;
&lt;th&gt;Applicable queries&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Symbol index (grep / AST symbols)&lt;/td&gt;
&lt;td&gt;Low (seconds)&lt;/td&gt;
&lt;td&gt;Very low (incremental)&lt;/td&gt;
&lt;td&gt;&amp;lt; 10ms&lt;/td&gt;
&lt;td&gt;Exact symbol queries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vector index (AST + embedding)&lt;/td&gt;
&lt;td&gt;Medium (minutes)&lt;/td&gt;
&lt;td&gt;Medium (changed funcs only)&lt;/td&gt;
&lt;td&gt;~100ms&lt;/td&gt;
&lt;td&gt;Semantic queries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Call-graph index (AST parse)&lt;/td&gt;
&lt;td&gt;Low (seconds)&lt;/td&gt;
&lt;td&gt;Low (changed files only)&lt;/td&gt;
&lt;td&gt;&amp;lt; 50ms&lt;/td&gt;
&lt;td&gt;Structural queries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Git history index&lt;/td&gt;
&lt;td&gt;High (initial full scan)&lt;/td&gt;
&lt;td&gt;Low (incremental commit)&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;td&gt;Intent / history queries&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A few things worth noting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The symbol index is the value king.&lt;/strong&gt; Seconds to build, 10ms to query, near-negligible cost, yet it cleanly covers an entire class of exact queries. Any system should ship it first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The vector index is the most expensive route.&lt;/strong&gt; Embedding runs a model, build is measured in minutes, and query latency is highest (~100ms). This is exactly why incremental updates matter most for it — you absolutely don't want to re-run full embedding on every commit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The call-graph index is surprisingly cheap.&lt;/strong&gt; It's just AST parsing plus an edge table, seconds to build, fast to query. Article 05 already proved its value, and its cost is so low there's no reason not to ship it. &lt;strong&gt;Graph retrieval has been neglected not because it's expensive, but because people never figured out how to use it (Article 05's lesson).&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Git history index is priciest on the first run.&lt;/strong&gt; A full scan of commit history isn't cheap, but every new commit afterward is incremental, with low marginal cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Flag:&lt;/strong&gt; The costs and latencies in the table are &lt;strong&gt;order-of-magnitude estimates&lt;/strong&gt; (seconds/minutes/milliseconds), drawn from the actual run experience of the previous five demos and ordinary engineering experience, not precise benchmarks on production-scale codebases. Use it to judge relative priority (ship the cheap symbol and graph routes first, the expensive vector route later), don't treat it as an SLA.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Implementation Path: Small to Large, Three Phases
&lt;/h2&gt;

&lt;p&gt;No matter how pretty the architecture, shipping it all at once will choke you. The right posture is a phased rollout where &lt;strong&gt;each phase delivers standalone value; get one working before moving to the next.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 1: Vector + Symbol (minimum viable system)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ship the two cheapest, least controversial routes first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Symbol index: ripgrep + an AST symbol table (function name → file → line-number dictionary). Seconds to build, covers all exact queries.&lt;/li&gt;
&lt;li&gt;Vector index: AST function-level chunking + raw-code embedding. This is the strongest vector baseline validated in Article 03 (Recall@5 = 0.958, experimentally validated), copy it directly.&lt;/li&gt;
&lt;li&gt;Query routing: start with the simplest rule — precise identifier in the query goes to symbol, otherwise vector.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This phase already covers the two big classes of "exact symbol query" and "semantic description query," a system usable immediately. &lt;strong&gt;Don't underestimate it — the vast majority of daily code retrieval falls into these two classes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 2: Add the call graph (cover structural queries)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once Phase 1 runs smoothly, add the third route:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Call-graph index: AST parsing to build &lt;code&gt;CALLS&lt;/code&gt;/&lt;code&gt;CALLED_BY&lt;/code&gt; edge tables. Low cost (seconds), high value (Article 05 validated it fixes Q8).&lt;/li&gt;
&lt;li&gt;Wire the graph route in as an &lt;strong&gt;independent first-class retrieval route&lt;/strong&gt; — identify function names from the query, traverse the graph independently, absolutely no Article-05-style "BFS trailing behind vector" post-processing.&lt;/li&gt;
&lt;li&gt;Upgrade the query router: recognize structural keywords like "who calls," "call chain," and activate the graph route.&lt;/li&gt;
&lt;li&gt;Upgrade the Result Merger: from "single-route passthrough" to "weighted fusion by query type."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This phase fills in the Q8 class of structural queries — the piece of the map the text route physically can't reach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 3: Add Git history + incremental updates (productionize)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first two phases are "can query accurately"; this phase is "can survive production":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git history index: connect to Article 01's intent layer, support queries like "why is this line written this way," "the version three months ago."&lt;/li&gt;
&lt;li&gt;Incremental updates: refactor all three routes' index building to be Git diff-driven. This is the critical leap from "demo" to "production" — without incremental updates, the architecture above won't run on a real project.&lt;/li&gt;
&lt;li&gt;Change propagation: when a function signature changes, update affected neighbors' edges along the call graph.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The point of phasing is that each phase is a complete system that can ship independently and create value independently.&lt;/strong&gt; Phase 1 solves most retrieval needs; Phase 2 covers the structural blind spot; Phase 3 lets it survive a real project's daily evolution. You needn't wait for all three phases to deliver — on the contrary, you should collect real queries after Phase 1 ships and use them to guide the priorities of Phases 2 and 3.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tool Selection Recommendations
&lt;/h2&gt;

&lt;p&gt;Finally, down to the actual screws. This part is conventional engineering selection advice, not experimental conclusions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vector storage:&lt;/strong&gt; pgvector (a PostgreSQL extension) or Qdrant. The key reason to pick them is &lt;strong&gt;support for metadata filtering&lt;/strong&gt; — you can attach conditions like "only in the payment module," "only in these few files" during vector retrieval, which is extremely useful for code retrieval (many queries naturally carry a module scope).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Graph storage: no Neo4j needed.&lt;/strong&gt; This deserves emphasis, because the moment you say "knowledge graph," many people reflexively reach for a graph database. Every demo's call graph in this series is a Python &lt;code&gt;dict&lt;/code&gt; (&lt;code&gt;{function_name: [called functions]}&lt;/code&gt;) held in memory and serialized to a file, and that's entirely sufficient (validated in Article 05). For a large project where memory won't hold it, NetworkX or simply an edge table in SQLite is still far lighter than Neo4j. &lt;strong&gt;The scale of a code call graph can't justify the operational cost of a dedicated graph database.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Symbol index:&lt;/strong&gt; ripgrep (version 15.1.0 supports PCRE2 + JIT, fast enough) for full-text exact matching, plus an AST-parsed symbol table (function name → file → line number) for definition-level queries. The two together cover all exact-symbol needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Incremental-update triggers:&lt;/strong&gt; a Git &lt;code&gt;pre-push&lt;/code&gt; hook, or an index-update step in the CI/CD pipeline. The former updates instantly and locally; the latter is centralized, suited to a team-shared index.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query router implementation:&lt;/strong&gt; rules first (keyword recognition + identifier pattern matching), LLM assistance second (and non-essential). Don't reach for LLM classification up front — rules cover the overwhelming majority, and they're fast, free, and explainable.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Ready-Made Landing Case: codebase-memory-mcp
&lt;/h2&gt;

&lt;p&gt;After all this design talk, you might ask: is there anything running that implements this architecture? Yes.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;codebase-memory-mcp&lt;/code&gt; MCP Server introduced in Article 02, held up against this article's architecture design, is essentially a complete landing case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It already implements &lt;strong&gt;vector retrieval + call graph + symbol index, three-route retrieval&lt;/strong&gt; — exactly this article's Principle One, multi-path retrieval.&lt;/li&gt;
&lt;li&gt;It's exposed directly to Claude Code via the MCP protocol — within Claude Code you can directly call its &lt;code&gt;search_graph&lt;/code&gt; (symbol/semantic search), &lt;code&gt;trace_path&lt;/code&gt; (call-chain tracing), &lt;code&gt;query_graph&lt;/code&gt; (graph queries), and other tools.&lt;/li&gt;
&lt;li&gt;It organizes the three signals into a unified knowledge-graph interface — exactly this article's idea of "combining three routes into one system."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, the architecture diagram in this article isn't armchair theory — it has an implementation that already works and is already wired into the Claude Code workflow. &lt;strong&gt;In the next hands-on article, we'll take &lt;code&gt;codebase-memory-mcp&lt;/code&gt; and run an end-to-end demo on a real project&lt;/strong&gt;, to see how this multi-path retrieval architecture actually performs on a real codebase — and that's when all the experimental intuition accumulated over the previous five articles finally faces the test of a real project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Five experiments measured the three signals' territories, and they barely overlap.&lt;/strong&gt; Vector for semantic-similarity queries (0.958, validated), graph for structural queries (fixing Q8, validated), symbol for exact-match queries (no experiment needed). The first principle is accepting there's no "best method" that dominates all four layers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Principle one: multi-path retrieval, each to its own job.&lt;/strong&gt; Stop looking for an all-rounder, let each route do only what it's best at — a design direction derived from five articles of consecutive failure at "forcing one signal to dominate."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Principle two: query routing, activate the right path by intent.&lt;/strong&gt; Precise identifiers to symbol, structural keywords to graph, natural language to vector, rules first and LLM second. (Pseudocode-level design concept, not experimentally validated.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Principle three: graph retrieval is a first-class citizen, not a post-processing bolt-on.&lt;/strong&gt; Directly correcting Article 05's failure — graph and vector retrieve independently in parallel, fused by query-type weighting, rather than letting graph trail behind vector doing BFS and polluting the ranking. (Direction experimentally backed, fusion details to be validated hands-on.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Principle four: Git diff-driven incremental updates, never full rebuilds.&lt;/strong&gt; Recompute only changed functions, propagate changes along the call graph, support commit version snapshots connecting to the intent layer. (Pure design recommendation, responding to Article 01's "dynamism is the biggest challenge.")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Land it in three phases, each delivering standalone value.&lt;/strong&gt; Phase 1 vector+symbol (minimum viable) → Phase 2 add call graph (cover structural blind spot) → Phase 3 add Git history + incremental updates (productionize).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool selection:&lt;/strong&gt; pgvector/Qdrant for vectors (need metadata filtering), no Neo4j for graph (a Python dict / SQLite edge table suffices), ripgrep + AST symbol table for exact matching, Git hook or CI to trigger incremental updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;codebase-memory-mcp&lt;/code&gt; is a ready-made landing case for this architecture&lt;/strong&gt;, already implementing three-route retrieval and wired into Claude Code. The next article uses it for an end-to-end hands-on demo on a real project.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From Article 03's single vector baseline to this article's three-route architecture, we've completed the shift in vantage point from "retrieval algorithm" to "system architecture." The sentence Q8's story taught us is the very bedrock of this architecture:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Some links are inherently not in the text — so what we've always needed isn't a smarter single route, but multiple routes each doing its own job.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;codebase-memory-mcp tool introduction: see Article 02 of this series&lt;/li&gt;
&lt;li&gt;The four knowledge layers framework: see Article 01 of this series&lt;/li&gt;
&lt;li&gt;The graph-retrieval double-edged-sword experiment: see Article 05 of this series&lt;/li&gt;
&lt;li&gt;The text-route boundary experiment: see Article 07 of this series&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Check out &lt;a href="https://primeskills.store" rel="noopener noreferrer"&gt;PrimeSkills&lt;/a&gt; — a curated marketplace of AI agents and skills that have been validated in real-world, enterprise-grade workflows. No fluff, just what actually works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Find more useful knowledge and interesting products on my &lt;a href="https://home.wonlab.top/en" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>codebase</category>
      <category>knowledgebase</category>
      <category>engineering</category>
    </item>
    <item>
      <title>Open Source Project #142: Buzz — Block Rebuilds Team Collaboration on Nostr, Where AI Agents Hold Their Own Cryptographic Identity</title>
      <dc:creator>WonderLab</dc:creator>
      <pubDate>Thu, 06 Aug 2026 01:57:22 +0000</pubDate>
      <link>https://dev.to/wonderlab/open-source-project-142-buzz-block-rebuilds-team-collaboration-on-nostr-where-ai-agents-hold-54an</link>
      <guid>https://dev.to/wonderlab/open-source-project-142-buzz-block-rebuilds-team-collaboration-on-nostr-where-ai-agents-hold-54an</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"Not agents assisting humans. Agents and humans in the same room, working on the same thing."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is &lt;strong&gt;article #175&lt;/strong&gt; in the "One Open Source Project a Day" series. Today's project is &lt;strong&gt;Buzz&lt;/strong&gt; — the open-source team workspace released by Block (Jack Dorsey's company) on July 21, 2026. Its core premise: AI agents should join teams as full members, not be bolted on as bots or plugins.&lt;/p&gt;

&lt;p&gt;Slack, Teams, GitHub — existing collaboration tools integrate AI roughly like this: configure a bot token, let the bot monitor a channel, trigger a response when @mentioned. The agent has no independent identity, no persistent history, no auditable action record, and permissions controlled by the platform rather than the organization.&lt;/p&gt;

&lt;p&gt;Buzz takes a different approach. Built on the Nostr protocol, every participant — human or agent — holds a keypair that belongs to them, not the platform. Identity, behavior, and history are all cryptographically signed and portable to any Nostr-compatible system. A human member and an agent member look identical in the channel.&lt;/p&gt;

&lt;p&gt;21,300 Stars. Apache 2.0. That's six days after launch.&lt;/p&gt;

&lt;h3&gt;
  
  
  What You'll Learn
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Why Buzz chose Nostr instead of building its own identity system&lt;/li&gt;
&lt;li&gt;How agents become full members in Buzz, not bots&lt;/li&gt;
&lt;li&gt;How the ACP protocol drives Claude Code, Codex, Goose, and other agents&lt;/li&gt;
&lt;li&gt;buzz-cli's machine-first design: built for LLM tool calls&lt;/li&gt;
&lt;li&gt;The YAML workflow engine: triggers, steps, and action types&lt;/li&gt;
&lt;li&gt;The Rust + Axum backend, Tauri desktop app, full technical stack&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Familiarity with team collaboration tools (Slack/Discord-type workflows)&lt;/li&gt;
&lt;li&gt;Basic understanding of AI agent tool-calling&lt;/li&gt;
&lt;li&gt;Knowing what a keypair (public/private key) is helps&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Project Background
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why Block Built Buzz
&lt;/h3&gt;

&lt;p&gt;Block spent two years building AI tools internally and reached one conclusion: productive work happens when humans and agents are in the same context together. Separate tools, separate systems, separate histories produce fragmentation and repeated context-rebuilding.&lt;/p&gt;

&lt;p&gt;The problem with existing platforms isn't missing features — it's the wrong design assumption: they treat AI as "assistants" rather than "members."&lt;/p&gt;

&lt;p&gt;Buzz's starting point: agents should have the same participation rights as human members — independent identity, auditable behavior, persistent history, configurable permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Timeline
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;July 21, 2026&lt;/strong&gt;: Public launch with simultaneous open-source release&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: 21,300 Stars within days of launch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hosted&lt;/strong&gt;: buzz.xyz (Block's instance)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosted&lt;/strong&gt;: Full Docker + Rust toolchain support&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Author / Team
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Company&lt;/strong&gt;: Block, Inc. (founded by Jack Dorsey)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License&lt;/strong&gt;: Apache-2.0&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Primary language&lt;/strong&gt;: Rust (backend) + TypeScript/React (desktop via Tauri) + Dart (mobile via Flutter)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project Stats
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;⭐ GitHub Stars: &lt;strong&gt;21,300+&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🍴 Forks: 2,300+&lt;/li&gt;
&lt;li&gt;📄 License: Apache-2.0&lt;/li&gt;
&lt;li&gt;📅 Launch date: 2026-07-21&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Nostr
&lt;/h2&gt;

&lt;p&gt;Buzz's identity system runs entirely on the Nostr protocol. That decision shapes the entire product architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem Nostr Solves
&lt;/h3&gt;

&lt;p&gt;Traditional collaboration platform identity: the platform issues accounts, controls access, owns the identity and history. Switching platforms means rebuilding everything.&lt;/p&gt;

&lt;p&gt;Nostr's model: each participant generates their own secp256k1 keypair. The private key belongs to them. Every message is signed with that key. Identity belongs to no platform, history is portable, behavior is non-repudiable.&lt;/p&gt;

&lt;p&gt;What this means for agents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Traditional bot model:
  Platform issues bot token → agent calls API with token → token revoked = agent gone
  Identity belongs to the platform, history belongs to the platform

Buzz / Nostr model:
  Agent generates its own keypair → signs every message with its private key → key belongs to agent
  Identity is portable, history lives in the relay, switching relays preserves identity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Nostr NIPs in Use
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NIP-01&lt;/strong&gt;: Base event format (the underlying structure of every message)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NIP-42&lt;/strong&gt;: Authentication (verifying key ownership when connecting to the relay)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NIP-34&lt;/strong&gt;: Git integration (patch submissions, repo announcements, commit status)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  "The Relay URL Is the Community"
&lt;/h3&gt;

&lt;p&gt;One Buzz design decision: a community (workspace) is identified by its relay URL. &lt;code&gt;wss://your-org.buzz.xyz&lt;/code&gt; is your workspace — the URL itself is the authoritative identifier. Different relays are different communities. All state on one relay shares a single event log.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Agents Become Full Members
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Not a Bot, a Member
&lt;/h3&gt;

&lt;p&gt;Traditional platform bots: a service account that monitors specific channels and triggers responses on @mention. In the permission model, typically a separate category from human members.&lt;/p&gt;

&lt;p&gt;Buzz agents: hold their own keypair, join channels exactly as humans do, and their messages are signed Nostr events that appear in channel history indistinguishably from human messages.&lt;/p&gt;

&lt;p&gt;Adding an agent to a channel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Same operation used for adding a human member&lt;/span&gt;
buzz channels add-member &lt;span class="nt"&gt;--channel&lt;/span&gt; CHANNEL_ID &lt;span class="nt"&gt;--pubkey&lt;/span&gt; AGENT_PUBKEY &lt;span class="nt"&gt;--role&lt;/span&gt; member
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What Cryptographic Identity Means in Practice
&lt;/h3&gt;

&lt;p&gt;Every message an agent sends carries a signature from that agent's private key:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Non-repudiable&lt;/strong&gt;: anyone can verify which agent produced any given message&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auditable&lt;/strong&gt;: agent actions in the audit log have unambiguous attribution — not "some bot"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portable&lt;/strong&gt;: the agent's keypair isn't bound to Buzz; the same identity works on any Nostr-compatible system&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How ACP Drives Agents
&lt;/h3&gt;

&lt;p&gt;Buzz routes relay events to agent processes through ACP (Agent Client Protocol):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Buzz relay (WebSocket event stream)
        ↓
buzz-acp (standalone binary, runs outside the relay)
        ↓
ACP (JSON-RPC over stdin/stdout)
        ↓
Agent process (Claude Code / Codex / Goose / custom)
        ↓
MCP tool calls → message posted back to channel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key design: &lt;strong&gt;one active prompt per channel at a time&lt;/strong&gt;. Subsequent @mentions queue while the current prompt is in flight, preventing overlapping context windows from race conditions. Agent process crashes trigger automatic harness restarts. Conversation history lives in the relay's Postgres database, not the ACP process — agents restart with full context intact.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supported Agents
&lt;/h3&gt;

&lt;p&gt;Built-in support (auto-detected from locally installed harnesses):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code (Anthropic)&lt;/li&gt;
&lt;li&gt;Codex (OpenAI)&lt;/li&gt;
&lt;li&gt;Goose (Block's own agent)&lt;/li&gt;
&lt;li&gt;Grok (xAI)&lt;/li&gt;
&lt;li&gt;Any custom ACP-compatible agent&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  buzz-cli: An Interface Built for Machines
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Machine-First Design Principles
&lt;/h3&gt;

&lt;p&gt;The Buzz CLI is designed for programmatic consumption, not human convenience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JSON to stdout&lt;/strong&gt;: all output is structured JSON, parseable by programs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured errors to stderr&lt;/strong&gt;: error output is separated from result output&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Meaningful exit codes&lt;/strong&gt;: 0 = success, non-zero = typed failure, scriptable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Configuration via environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BUZZ_RELAY_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'http://localhost:3000'&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BUZZ_PRIVATE_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'nsec...'&lt;/span&gt;   &lt;span class="c"&gt;# agent's or user's private key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Core Operations
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Channel management&lt;/span&gt;
buzz channels list
buzz channels create &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"dev-ops"&lt;/span&gt;

&lt;span class="c"&gt;# Send a message&lt;/span&gt;
buzz messages send &lt;span class="nt"&gt;--channel&lt;/span&gt; CHANNEL_ID &lt;span class="nt"&gt;--text&lt;/span&gt; &lt;span class="s2"&gt;"Deploy complete, v2.3.1"&lt;/span&gt;

&lt;span class="c"&gt;# Full-text search (covers messages + canvases + git events — all one index)&lt;/span&gt;
buzz messages search &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"deploy failed"&lt;/span&gt; &lt;span class="nt"&gt;--since&lt;/span&gt; 24h

&lt;span class="c"&gt;# Read a thread&lt;/span&gt;
buzz threads &lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;--thread-id&lt;/span&gt; THREAD_ID

&lt;span class="c"&gt;# Canvas read/write (documents)&lt;/span&gt;
buzz canvases write &lt;span class="nt"&gt;--canvas-id&lt;/span&gt; ID &lt;span class="nt"&gt;--content&lt;/span&gt; &lt;span class="s2"&gt;"..."&lt;/span&gt;

&lt;span class="c"&gt;# Workflow management&lt;/span&gt;
buzz workflows list
buzz workflows run &lt;span class="nt"&gt;--workflow-id&lt;/span&gt; ID

&lt;span class="c"&gt;# Agent memory storage&lt;/span&gt;
buzz memory &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;--key&lt;/span&gt; &lt;span class="s2"&gt;"deployment-config"&lt;/span&gt; &lt;span class="nt"&gt;--value&lt;/span&gt; &lt;span class="s2"&gt;"..."&lt;/span&gt;
buzz memory get &lt;span class="nt"&gt;--key&lt;/span&gt; &lt;span class="s2"&gt;"deployment-config"&lt;/span&gt;

&lt;span class="c"&gt;# Git repo announcements (NIP-34)&lt;/span&gt;
buzz repos announce &lt;span class="nt"&gt;--url&lt;/span&gt; https://github.com/org/repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The intended use: agents call these commands via MCP tools to post reports to channels, read context, update canvases, and query history — without directly manipulating the relay protocol.&lt;/p&gt;




&lt;h2&gt;
  
  
  YAML Workflow Engine
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Trigger Types
&lt;/h3&gt;

&lt;p&gt;Workflows support four trigger types:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;message_posted&lt;/span&gt;       &lt;span class="c1"&gt;# when a message is posted&lt;/span&gt;
  &lt;span class="c1"&gt;# on: reaction_added     # when someone adds an emoji reaction&lt;/span&gt;
  &lt;span class="c1"&gt;# on: schedule           # cron expression&lt;/span&gt;
  &lt;span class="c1"&gt;# on: webhook            # external HTTP webhook&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Full Example: Release Request Workflow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Release&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;request"&lt;/span&gt;
&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;message_posted&lt;/span&gt;
  &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;str_contains(trigger_text,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'ship&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;it')"&lt;/span&gt;
&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;announce&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;send_message&lt;/span&gt;
    &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{trigger.channel_id}}"&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Release&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;requested&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;by&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{trigger.author}}&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;—&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;starting&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;deployment&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pipeline."&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;notify-ops&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;send_dm&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ops-lead-pubkey"&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Manual&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;approval&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;needed&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;release&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;from&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{trigger.author}}"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wait-approval&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wait_approval&lt;/span&gt;
    &lt;span class="na"&gt;approvers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ops-lead-pubkey"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;eng-lead-pubkey"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30m&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;trigger-deploy&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webhook&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://ci.internal/deploy"&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{"version":&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"{{vars.release_tag}}"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every step emits events into the relay's event log. Search queries across workflow execution history the same way they search channel messages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supported Action Types
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;send_message&lt;/code&gt; — post to a channel&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;send_dm&lt;/code&gt; — send a direct message&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;add_reaction&lt;/code&gt; — add an emoji reaction&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;webhook&lt;/code&gt; — trigger an external HTTP request&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;wait_delay&lt;/code&gt; — pause for a specified duration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;wait_approval&lt;/code&gt; — wait for human approval (partially implemented)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Technical Architecture
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Backend (Rust)
&lt;/h3&gt;

&lt;p&gt;Buzz's relay is a Rust workspace with focused crates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="err"&gt;buzz-relay&lt;/span&gt;          &lt;span class="err"&gt;Axum&lt;/span&gt; &lt;span class="err"&gt;WebSocket&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="err"&gt;REST&lt;/span&gt; &lt;span class="err"&gt;HTTP&lt;/span&gt; &lt;span class="err"&gt;server&lt;/span&gt;
&lt;span class="err"&gt;buzz-store&lt;/span&gt;          &lt;span class="err"&gt;Postgres&lt;/span&gt; &lt;span class="err"&gt;event&lt;/span&gt; &lt;span class="err"&gt;storage&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="err"&gt;full-text&lt;/span&gt; &lt;span class="err"&gt;search&lt;/span&gt;
&lt;span class="err"&gt;buzz-pubsub&lt;/span&gt;         &lt;span class="err"&gt;Redis&lt;/span&gt; &lt;span class="err"&gt;pub/sub&lt;/span&gt; &lt;span class="err"&gt;(real-time&lt;/span&gt; &lt;span class="err"&gt;message&lt;/span&gt; &lt;span class="err"&gt;fan-out)&lt;/span&gt;
&lt;span class="err"&gt;buzz-media&lt;/span&gt;          &lt;span class="err"&gt;S3/MinIO&lt;/span&gt; &lt;span class="err"&gt;media&lt;/span&gt; &lt;span class="err"&gt;file&lt;/span&gt; &lt;span class="err"&gt;storage&lt;/span&gt;
&lt;span class="err"&gt;buzz-acp&lt;/span&gt;            &lt;span class="err"&gt;ACP&lt;/span&gt; &lt;span class="err"&gt;protocol&lt;/span&gt; &lt;span class="err"&gt;harness&lt;/span&gt; &lt;span class="err"&gt;(standalone&lt;/span&gt; &lt;span class="err"&gt;binary)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;One event log&lt;/strong&gt;: chat messages, canvas updates, code reviews, CI events, and workflow step results are all Nostr events in the same Postgres table with the same full-text index. Searching "deploy" returns related chat discussion, canvas docs, and Git commit statuses from a single query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security model&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tenant context resolved from server hostname, not client-supplied tags — agents can't forge cross-community access&lt;/li&gt;
&lt;li&gt;Channel-scoped tokens cannot publish global events&lt;/li&gt;
&lt;li&gt;Subscription delivery re-checks permissions at fan-out time, catching changes after subscription&lt;/li&gt;
&lt;li&gt;Ephemeral events (typing indicators, presence) are verified and access-checked but never written to Postgres&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Desktop App (Tauri + React)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start relay + desktop together&lt;/span&gt;
just dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tauri provides system capabilities (file access, notifications) via Rust; React handles UI rendering. The result is a native desktop app with lower memory footprint than Electron.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mobile (Flutter)
&lt;/h3&gt;

&lt;p&gt;iOS and Android clients are Flutter-based, currently in active development.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Local Development
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/block/buzz.git
&lt;span class="nb"&gt;cd &lt;/span&gt;buzz

&lt;span class="c"&gt;# Use Hermit to manage the toolchain (recommended)&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt; ./bin/activate-hermit

&lt;span class="c"&gt;# Or install manually: Rust 1.88+, Node 24+, pnpm 10+, just&lt;/span&gt;

just setup   &lt;span class="c"&gt;# initialize dependencies&lt;/span&gt;
just build   &lt;span class="c"&gt;# build all components&lt;/span&gt;
just dev     &lt;span class="c"&gt;# start relay (ws://localhost:3000) + desktop app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Docker
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Includes relay, Postgres, Redis, and MinIO (media storage).&lt;/p&gt;

&lt;h3&gt;
  
  
  Railway One-Click Deploy
&lt;/h3&gt;

&lt;p&gt;A Railway deployment template is included in the repo — one click to deploy a private Buzz instance in the cloud.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connect an Agent
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install buzz-cli&lt;/span&gt;
cargo &lt;span class="nb"&gt;install &lt;/span&gt;buzz-cli

&lt;span class="c"&gt;# Set environment variables&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BUZZ_RELAY_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'wss://your-relay.buzz.xyz'&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;BUZZ_PRIVATE_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'nsec...'&lt;/span&gt;

&lt;span class="c"&gt;# Add agent to a channel&lt;/span&gt;
buzz channels add-member &lt;span class="nt"&gt;--channel&lt;/span&gt; CHANNEL_ID &lt;span class="nt"&gt;--pubkey&lt;/span&gt; AGENT_PUBKEY &lt;span class="nt"&gt;--role&lt;/span&gt; member

&lt;span class="c"&gt;# Start the ACP harness (auto-detects locally installed agents)&lt;/span&gt;
buzz-acp &lt;span class="nt"&gt;--relay&lt;/span&gt; wss://your-relay.buzz.xyz &lt;span class="nt"&gt;--key&lt;/span&gt; nsec...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🌟 &lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/block/buzz" rel="noopener noreferrer"&gt;block/buzz&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Hosted&lt;/strong&gt;: &lt;a href="https://buzz.xyz" rel="noopener noreferrer"&gt;buzz.xyz&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📖 &lt;strong&gt;Launch post&lt;/strong&gt;: &lt;a href="https://block.xyz/inside/introducing-buzz-where-humans-and-agents-work-together" rel="noopener noreferrer"&gt;block.xyz/inside/introducing-buzz&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;strong&gt;Hacker News&lt;/strong&gt;: &lt;a href="https://news.ycombinator.com/item?id=48632977" rel="noopener noreferrer"&gt;news.ycombinator.com/item?id=48632977&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Buzz bets everything on one design decision: AI agents should join teams as full members, not as attached tools. That decision drives every subsequent choice — Nostr (identity not controlled by any platform), cryptographic keypairs (behavior is auditable), buzz-cli's JSON output (LLM-callable), ACP protocol (unified agent integration standard).&lt;/p&gt;

&lt;p&gt;The one-event-log design is worth noting. Chat messages, code reviews, CI notifications, and workflow execution steps all go into the same Nostr event stream with the same full-text index. An agent querying history doesn't need to know "is this a chat event or a code event" — one search surfaces all relevant context. That's an agent-native data model, not a human-designed taxonomy with an agent adapter bolted on.&lt;/p&gt;

&lt;p&gt;Buzz is early. Some workflow actions return &lt;code&gt;NotImplemented&lt;/code&gt;, the mobile client is in progress, and the ecosystem is just forming. But Block has done something important: it moved the agent collaboration problem from "API integration" to "platform design," then open-sourced the whole platform for the community to evolve.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Explore &lt;a href="https://primeskills.store" rel="noopener noreferrer"&gt;PrimeSkills&lt;/a&gt; — A marketplace for handpicked AI Agents and skills. Each is validated in real enterprise workflows, stripping away hype and keeping only what truly works.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Welcome to my &lt;a href="https://home.wonlab.top/en" rel="noopener noreferrer"&gt;Homepage&lt;/a&gt; for more useful insights and interesting products.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>agents</category>
      <category>tauri</category>
      <category>rust</category>
    </item>
  </channel>
</rss>
