<?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: Dhrupo Nil</title>
    <description>The latest articles on DEV Community by Dhrupo Nil (@dhrupo).</description>
    <link>https://dev.to/dhrupo</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1151170%2Ff3f2b324-73c2-4df0-9f8a-ffc109194198.jpeg</url>
      <title>DEV Community: Dhrupo Nil</title>
      <link>https://dev.to/dhrupo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dhrupo"/>
    <language>en</language>
    <item>
      <title>Your AI Coding Agent Wastes 80% of Its Context. Fixed That with Graph Theory.</title>
      <dc:creator>Dhrupo Nil</dc:creator>
      <pubDate>Mon, 25 May 2026 13:45:00 +0000</pubDate>
      <link>https://dev.to/dhrupo/your-ai-coding-agent-wastes-80-of-its-context-fixed-that-with-graph-theory-1mfa</link>
      <guid>https://dev.to/dhrupo/your-ai-coding-agent-wastes-80-of-its-context-fixed-that-with-graph-theory-1mfa</guid>
      <description>&lt;h2&gt;
  
  
  The problem nobody admits
&lt;/h2&gt;

&lt;p&gt;When you give Claude Code, Cursor, or Codex a task like &lt;em&gt;"fix the login validation bug"&lt;/em&gt;, here's what they usually do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;grep -l login src/&lt;/code&gt; → 17 files&lt;/li&gt;
&lt;li&gt;Read all 17 files top-to-bottom (because context is "free")&lt;/li&gt;
&lt;li&gt;Spend 80% of the model's context window on irrelevant imports, type aliases, and helper functions the bug doesn't touch&lt;/li&gt;
&lt;li&gt;Generate a fix using whatever 20% of attention is left&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This works. Sort of. But it's wasteful — and on big codebases, it's wrong: the agent runs out of context before it sees the actual buggy function.&lt;/p&gt;

&lt;p&gt;The instinct is to throw a bigger model at it. Bigger context window, fancier RAG, vector embeddings. All of which trade real cost for diminishing returns.&lt;/p&gt;

&lt;p&gt;There's a better answer that's been sitting in classical CS the whole time: &lt;strong&gt;treat the repo as a graph&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdhrupo%2Fmincut-context%2Fmain%2Fdocs%2Fdemo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fdhrupo%2Fmincut-context%2Fmain%2Fdocs%2Fdemo.gif" alt="demo" width="760" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The idea, in one paragraph
&lt;/h2&gt;

&lt;p&gt;Your codebase already &lt;em&gt;is&lt;/em&gt; a graph. Functions call functions. Modules import modules. Classes extend classes. Pick a node (the symbol your task is about), and the structurally-closest neighborhood is almost certainly what an agent needs to see.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;&lt;code&gt;mincut-context&lt;/code&gt;&lt;/strong&gt; — an npm package that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parses your repo into a &lt;strong&gt;symbol graph&lt;/strong&gt; (tree-sitter, supports TS/JS/Vue/Python/PHP)&lt;/li&gt;
&lt;li&gt;Derives &lt;strong&gt;seed nodes&lt;/strong&gt; from your task description (keyword IDF on symbol names + file paths)&lt;/li&gt;
&lt;li&gt;Runs &lt;strong&gt;personalized PageRank&lt;/strong&gt; with the seeds as the restart vector&lt;/li&gt;
&lt;li&gt;Picks the &lt;strong&gt;minimum-cut subgraph&lt;/strong&gt; that fits a token budget you choose&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The output: a list of files + line ranges that an agent should look at. Nothing more, nothing less.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show me the numbers
&lt;/h2&gt;

&lt;p&gt;I built an evaluation suite into the repo itself. 28 hand-labeled tasks across 3 real codebases at a 4,000-token budget:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;strategy&lt;/th&gt;
&lt;th&gt;precision&lt;/th&gt;
&lt;th&gt;recall&lt;/th&gt;
&lt;th&gt;F1&lt;/th&gt;
&lt;th&gt;token-efficiency&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;mincut&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.27&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.83&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.39&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.270&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mincut + &lt;code&gt;--embed&lt;/code&gt; (semantic)&lt;/td&gt;
&lt;td&gt;0.27&lt;/td&gt;
&lt;td&gt;0.83&lt;/td&gt;
&lt;td&gt;0.39&lt;/td&gt;
&lt;td&gt;0.270&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;grep keyword baseline&lt;/td&gt;
&lt;td&gt;0.11&lt;/td&gt;
&lt;td&gt;0.42&lt;/td&gt;
&lt;td&gt;0.16&lt;/td&gt;
&lt;td&gt;0.105&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;random selection (control)&lt;/td&gt;
&lt;td&gt;0.01&lt;/td&gt;
&lt;td&gt;0.04&lt;/td&gt;
&lt;td&gt;0.01&lt;/td&gt;
&lt;td&gt;0.009&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Per-repo breakdown:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;repo&lt;/th&gt;
&lt;th&gt;tasks&lt;/th&gt;
&lt;th&gt;mincut recall&lt;/th&gt;
&lt;th&gt;grep recall&lt;/th&gt;
&lt;th&gt;mincut F1&lt;/th&gt;
&lt;th&gt;grep F1&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;mincut-context (self)&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.97&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.56&lt;/td&gt;
&lt;td&gt;0.44&lt;/td&gt;
&lt;td&gt;0.30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FluentForm (PHP+Vue+JS)&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.88&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.13&lt;/td&gt;
&lt;td&gt;0.43&lt;/td&gt;
&lt;td&gt;0.04&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fluent Player (TS/JSX)&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.63&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.56&lt;/td&gt;
&lt;td&gt;0.31&lt;/td&gt;
&lt;td&gt;0.13&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;mincut catches ~2× more of the correct files than grep, at ~2.5× better token efficiency.&lt;/strong&gt; Reproducible with &lt;code&gt;npm run eval&lt;/code&gt;. Add your own labeled tasks under &lt;code&gt;eval/fixtures/&lt;/code&gt; to score against your own codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  The math, briefly
&lt;/h2&gt;

&lt;p&gt;Given a symbol graph $G = (V, E, w)$ where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$V$ are code units (functions, classes, methods)&lt;/li&gt;
&lt;li&gt;$E$ are dependency edges (imports, calls, references)&lt;/li&gt;
&lt;li&gt;$w(v)$ is the token cost of including symbol $v$&lt;/li&gt;
&lt;li&gt;$B$ is your token budget&lt;/li&gt;
&lt;li&gt;$S \subseteq V$ are seed nodes derived from the task&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Find $T \supseteq S$ with $\sum_{v \in T} w(v) \le B$ minimizing the &lt;strong&gt;boundary cut cost&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;$$\text{cut}(T, V \setminus T) = \sum_{e \in E, \text{ crossing}} w(e)$$&lt;/p&gt;

&lt;p&gt;In plain English: pick a connected, low-token region that has few "loose ends" pointing outside it. The inside of the cut is what the agent needs; the outside is safely ignorable.&lt;/p&gt;

&lt;p&gt;The objective is submodular, so a greedy algorithm gives a $(1 - 1/e) \approx 0.63$ approximation guarantee. The full pseudocode is in the README; the implementation is ~200 lines in &lt;a href="https://github.com/dhrupo/mincut-context/blob/main/src/core/select.ts" rel="noopener noreferrer"&gt;&lt;code&gt;src/core/select.ts&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three ways to use it
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. As an MCP server — recommended for agents
&lt;/h3&gt;

&lt;p&gt;Drop this block into your Claude Code / Codex / Cursor settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mincut-context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mincut-context"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mcp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your agent now has six new tools: &lt;code&gt;pack_context&lt;/code&gt;, &lt;code&gt;expand_node&lt;/code&gt;, &lt;code&gt;find_callers&lt;/code&gt;, &lt;code&gt;find_callees&lt;/code&gt;, &lt;code&gt;search_symbols&lt;/code&gt;, &lt;code&gt;explain_selection&lt;/code&gt;. They operate on the cached graph from the most recent &lt;code&gt;pack_context&lt;/code&gt; call — effectively free traversal after the first pack.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. As a CLI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; mincut-context

mcx pack &lt;span class="s2"&gt;"fix the login validation bug"&lt;/span&gt; &lt;span class="nt"&gt;--budget&lt;/span&gt; 4000             &lt;span class="c"&gt;# plain output&lt;/span&gt;
mcx pack &lt;span class="s2"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; tree                                       &lt;span class="c"&gt;# directory-grouped&lt;/span&gt;
mcx pack &lt;span class="s2"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; json | jq                                  &lt;span class="c"&gt;# pipe to anything&lt;/span&gt;
mcx pack &lt;span class="s2"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;--interactive&lt;/span&gt;                                       &lt;span class="c"&gt;# Ink TUI: vim keys + preview&lt;/span&gt;
mcx pack &lt;span class="s2"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;--embed&lt;/span&gt;                                             &lt;span class="c"&gt;# semantic seeding&lt;/span&gt;
mcx pack &lt;span class="s2"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;--cache&lt;/span&gt;                                             &lt;span class="c"&gt;# 5× warm-run speedup&lt;/span&gt;
mcx watch &lt;span class="s2"&gt;"..."&lt;/span&gt; &lt;span class="nt"&gt;--debounce&lt;/span&gt; 300                                     &lt;span class="c"&gt;# re-pack on file change&lt;/span&gt;
mcx doctor                                                         &lt;span class="c"&gt;# environment self-check&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;mcx doctor&lt;/code&gt; is my favorite — it tells you in 6 lines what's installed and what isn't:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzw1c7rjfwuh340i0s9dx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzw1c7rjfwuh340i0s9dx.gif" alt="doctor" width="799" height="276"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. As a library
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;pack&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mincut-context&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fix the login validation bug&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;budget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;parallel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;maxTokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&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="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;·&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reasons&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// → src/auth/login.ts        0.541  612 · seed — matched directly by task&lt;/span&gt;
&lt;span class="c1"&gt;// → src/auth/session.ts      0.408  483 · attached (60%)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What I learned by building this
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Embeddings are oversold for this problem
&lt;/h3&gt;

&lt;p&gt;Adding semantic embeddings (&lt;code&gt;--embed&lt;/code&gt; flag, via &lt;code&gt;@xenova/transformers&lt;/code&gt; running locally) &lt;strong&gt;did not improve recall on any of my three eval task sets.&lt;/strong&gt; Why? Because the labels were named honestly. When you label "stripe payment processor" → &lt;code&gt;StripeProcessor.php&lt;/code&gt;, the keyword match catches it without help. Embeddings only earn their keep when your task vocabulary diverges from the code's — "centrality and ranking" → &lt;code&gt;PageRank&lt;/code&gt;, that kind of gap.&lt;/p&gt;

&lt;p&gt;I left &lt;code&gt;--embed&lt;/code&gt; in because it doesn't hurt, and there are real users whose mental model doesn't match the code. But the marketing-friendly "AI-powered" framing for this stuff is mostly noise.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Greedy beats CELF for this objective
&lt;/h3&gt;

&lt;p&gt;I implemented CELF (Cost-Effective Lazy Forward, Leskovec 2007) hoping for a free speedup over the naive greedy. It diverged — not just slower (8× slower on FluentForm) but &lt;strong&gt;wrong&lt;/strong&gt;: it produced smaller, structurally weaker selections.&lt;/p&gt;

&lt;p&gt;Why: our "no isolated nodes" acceptance rule (a candidate must have at least one edge into the current selection) breaks CELF's submodular-monotone assumption. A candidate's eligibility flips discontinuously when a node with an edge to it joins T. The lazy cache becomes unreliable.&lt;/p&gt;

&lt;p&gt;I wrote the dead end up in &lt;a href="https://github.com/dhrupo/mincut-context/blob/main/eval/ALGORITHM-RESEARCH.md" rel="noopener noreferrer"&gt;&lt;code&gt;eval/ALGORITHM-RESEARCH.md&lt;/code&gt;&lt;/a&gt; so nobody re-treads it. &lt;strong&gt;Honest negative results are worth shipping.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Sub-symbol chunking matters more than I expected
&lt;/h3&gt;

&lt;p&gt;Big legacy codebases have huge functions. A 500-line function is one symbol in the graph, and if it gets selected, the whole thing eats your budget. So &lt;code&gt;--chunk&lt;/code&gt; splits big functions at statement boundaries — each chunk becomes its own sub-symbol, individually selectable.&lt;/p&gt;

&lt;p&gt;On FluentForm: indexing without chunking → 4,333 symbols. With &lt;code&gt;--chunk&lt;/code&gt; → 4,878 symbols (+545 chunks). Same budget, much finer-grained selection. The greedy can pick &lt;em&gt;just the relevant &lt;code&gt;if/for/try&lt;/code&gt; block&lt;/em&gt; instead of all-or-nothing.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Test coverage of 88% isn't the whole story
&lt;/h3&gt;

&lt;p&gt;The CI gates on 85% statements / 80% branches / 90% functions / 85% lines. But the genuinely-untestable files — worker scripts, lazy-loaded LSP clients — are excluded from the calc. Honest reporting means saying &lt;em&gt;what&lt;/em&gt; is tested, not just the headline number.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest tradeoffs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Honest tradeoff&lt;/th&gt;
&lt;th&gt;What we do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;True optimal min-cut is NP-hard&lt;/td&gt;
&lt;td&gt;Greedy submodular — &lt;code&gt;(1−1/e)&lt;/code&gt; bound&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tree-sitter symbols are syntactic, not type-aware&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;--lsp&lt;/code&gt; refines TS/JS via typescript-language-server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Embedding model adds ~22 MB on first run&lt;/td&gt;
&lt;td&gt;Opt-in behind &lt;code&gt;--embed&lt;/code&gt; flag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LSP startup is slow (~1–5s)&lt;/td&gt;
&lt;td&gt;Opt-in; cached after init&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cold start parses whole repo&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;--cache&lt;/code&gt; (5× speedup) + &lt;code&gt;--parallel n&lt;/code&gt; (2.7× speedup)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What I'd build next if you asked
&lt;/h2&gt;

&lt;p&gt;The roadmap that's &lt;em&gt;not&lt;/em&gt; checked off yet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pyright / Intelephense LSP adapters&lt;/strong&gt; — type-aware calls for Python and PHP (~1–2 days each on the existing LSP infrastructure)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Svelte / Rust / Go parsers&lt;/strong&gt; — one file each on the parser template&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incremental neighborhood caching in the greedy&lt;/strong&gt; — keep &lt;code&gt;attach(v, T)&lt;/code&gt; cached and update only when a node with an edge to v is added. Expected 3–5× speedup on graphs with bounded degree.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each is bounded effort and additive. The core is done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stop building, start using
&lt;/h2&gt;

&lt;p&gt;The hardest lesson: &lt;strong&gt;a tool's value comes from someone actually using it on real work, not from feature count.&lt;/strong&gt; mincut-context is at v1.7.0 — 261 tests, 88.6% coverage, CI green on Ubuntu + macOS × Node 18/20/22. There's no honest "but it's not ready" excuse left.&lt;/p&gt;

&lt;p&gt;If you've watched an AI agent burn 80% of its 200k-token context on imports it doesn't care about, install it now and tell me what breaks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; mincut-context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🔗 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/dhrupo/mincut-context" rel="noopener noreferrer"&gt;github.com/dhrupo/mincut-context&lt;/a&gt;&lt;br&gt;
📦 &lt;strong&gt;npm:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/mincut-context" rel="noopener noreferrer"&gt;npmjs.com/package/mincut-context&lt;/a&gt;&lt;br&gt;
📊 &lt;strong&gt;Reproducible benchmarks:&lt;/strong&gt; &lt;a href="https://github.com/dhrupo/mincut-context/blob/main/eval/CROSS-REPO-RESULTS.md" rel="noopener noreferrer"&gt;&lt;code&gt;eval/CROSS-REPO-RESULTS.md&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love feedback — especially "your numbers don't replicate on my codebase" feedback. That's literally what the eval suite is for.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you got value from this, ⭐ the repo or drop a comment about a tooling problem you're solving. mincut-context is open-source MIT; the eval suite welcomes new fixtures.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>llm</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
