<?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: Alex Punnen</title>
    <description>The latest articles on DEV Community by Alex Punnen (@alexcpn).</description>
    <link>https://dev.to/alexcpn</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%2F376643%2F066507e0-ad14-4448-bcd8-74cb77cbdfe6.jpeg</url>
      <title>DEV Community: Alex Punnen</title>
      <link>https://dev.to/alexcpn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexcpn"/>
    <language>en</language>
    <item>
      <title>I spent 3.8 million tokens finding which service to change</title>
      <dc:creator>Alex Punnen</dc:creator>
      <pubDate>Fri, 04 Sep 2026 14:36:00 +0000</pubDate>
      <link>https://dev.to/alexcpn/i-spent-38-million-tokens-finding-which-service-to-change-7dm</link>
      <guid>https://dev.to/alexcpn/i-spent-38-million-tokens-finding-which-service-to-change-7dm</guid>
      <description>&lt;p&gt;&lt;em&gt;Code: &lt;a href="https://github.com/alexcpn/catalogify" rel="noopener noreferrer"&gt;github.com/alexcpn/catalogify&lt;/a&gt; · &lt;code&gt;uv tool install catalogify&lt;/code&gt; · MIT&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Take a monorepo with ninety microservices in it. A spec lands that will touch maybe three of them. Before anyone writes code, somebody has to work out which three, and on a repo that size that is most of the job.&lt;/p&gt;

&lt;p&gt;I wanted to know what it costs to let an agent answer that. So I did the obvious thing and gave it a map.&lt;/p&gt;

&lt;p&gt;There are good tools for this now. I used &lt;a href="https://github.com/Graphify-Labs/graphify" rel="noopener noreferrer"&gt;Graphify&lt;/a&gt;, which parses your code with tree-sitter and builds a queryable graph of every symbol and call edge. It runs locally, needs no API key, and tags every edge with whether it was extracted or inferred. I pointed it at one service and it chewed through 706 files in twenty seconds.&lt;/p&gt;

&lt;p&gt;Then I looked at what it produced.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;graph.json&lt;/code&gt;, 14.5 MB. About 3.8 million tokens for one service.&lt;/p&gt;

&lt;p&gt;Ten candidate services would be 38 million. Ninety would be 343 million. And routing is a comparison problem, so you can't just load the winner. You have to load everything you're choosing between.&lt;/p&gt;

&lt;p&gt;That was the moment I realised I'd been solving the wrong problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two questions, opposite shapes
&lt;/h2&gt;

&lt;p&gt;There are two questions people lump together as "give the agent context on the codebase."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which service does this touch?&lt;/strong&gt; Wide and shallow. You need a little about everything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inside that service, what changes?&lt;/strong&gt; Narrow and deep. You need everything about a little.&lt;/p&gt;

&lt;p&gt;Graphify is superb at the second one. &lt;code&gt;graphify affected "UpdateApiUsageCount" --depth 2&lt;/code&gt; gives you a precise impact radius in a few hundred tokens. Nothing I write by hand will ever beat that, and I'm not going to pretend otherwise.&lt;/p&gt;

&lt;p&gt;But the artifact backing those queries has to be complete, and completeness is exactly the wrong property for the first question. You're not asking about symbols. You're asking which service owns pod eviction, or image pulls, or volume mounting, and a call graph doesn't know that, because ownership isn't a topological fact.&lt;/p&gt;

&lt;p&gt;You can see it in the filenames. Graphify will export a markdown wiki, which is the right instinct. For one service it wrote 446 articles called things like &lt;code&gt;basicWorkQueue.md&lt;/code&gt; and &lt;code&gt;allPrimitiveFieldPaths.md&lt;/code&gt;. Those are symbols, clustered by how tightly the code couples. Useful for tracing. Useless for picking a service.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the opposite costs
&lt;/h2&gt;

&lt;p&gt;So I built the other thing. One small markdown file per service, in the language the spec is written in, with typed frontmatter and links to its neighbours.&lt;/p&gt;

&lt;p&gt;For the same Kubernetes component, same 108,648 lines of Go:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt;Tokens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Structural graph&lt;/td&gt;
&lt;td&gt;14.5 MB&lt;/td&gt;
&lt;td&gt;3,813,486&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Its markdown wiki&lt;/td&gt;
&lt;td&gt;1,004 KB&lt;/td&gt;
&lt;td&gt;256,968&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;One service entry&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.6 KB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;676&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Ninety of those is 61,000 tokens. That fits in one cheap call with the spec still sitting next to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that surprised me
&lt;/h2&gt;

&lt;p&gt;I wrote the generator to mine git history, on a hunch that the interesting stuff lives in reverts. Then I ran it against the kubelet's container manager and got this back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;508709d007e  cpumanager: improve V4 checkpoint corruption error
bc752cdfdb0  Fix V3 checkpoint checksum for rollback compatibility
76100602564  Revert "Fix CPU checkpoint migration V2 to V3"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chase that revert to the commit it reverted and the story comes out. When a V3 checkpoint has a bad checksum, restore falls back to V2, but the V3 fields it already read stay in the struct. You get a hybrid. Someone fixed that, and the fix got reverted, so it may still be sitting there.&lt;/p&gt;

&lt;p&gt;Nobody wrote that in a comment. There's no ADR. It exists in the commit log and in the head of whoever was on call that week.&lt;/p&gt;

&lt;p&gt;That's the stuff I actually want in a routing catalog, and it's the stuff no parser can reach, because the engineer fixing production at 2am was not writing documentation.&lt;/p&gt;

&lt;p&gt;Peter Naur got here in 1985. His argument in &lt;a href="https://pages.cs.wisc.edu/~remzi/Naur.pdf" rel="noopener noreferrer"&gt;&lt;em&gt;Programming as Theory Building&lt;/em&gt;&lt;/a&gt; is that the real product of programming is the theory of the system carried in the developers' heads, not the code, and that no amount of program text or documentation carries it for them. A program whose original team has dispersed is, in his word, dead. A new team patching a dead program makes fixes that look fine locally and quietly wreck the design.&lt;/p&gt;

&lt;p&gt;That is the position an AI agent is in on its first commit to your repository. It arrives after the team dispersed, holding the artifacts and none of the theory, and it patches with total confidence.&lt;/p&gt;

&lt;p&gt;Writing a better spec does not get you out of it. Brooks settled that one: the complexity of software is essential rather than accidental, so descriptions that abstract it away abstract away the essence. The ceiling is the same whether a human or a model wrote the spec.&lt;/p&gt;

&lt;p&gt;A revert is not the theory. It is a fossil of one place where the theory and the code collided hard enough that somebody had to act at speed. Fossils are cheap to collect, and they are worth more than anything else in the catalog.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do instead
&lt;/h2&gt;

&lt;p&gt;Two layers, and let each tool do the thing it's good at.&lt;/p&gt;

&lt;p&gt;Route with markdown. Small files, domain language, one per service, cheap enough to read all of them.&lt;/p&gt;

&lt;p&gt;Reach with the graph. Run it inside the one service you picked, call it as a CLI, keep &lt;code&gt;graph.json&lt;/code&gt; in &lt;code&gt;.gitignore&lt;/code&gt; and out of your context window entirely.&lt;/p&gt;

&lt;p&gt;The composition costs less than either half does alone once you're past a few dozen services.&lt;/p&gt;

&lt;p&gt;One more thing, since I'd rather say it than have it found: the first time I ran my own tool against Kubernetes it crashed. Exit 141. A &lt;code&gt;head -N&lt;/code&gt; closing a pipe under &lt;code&gt;set -o pipefail&lt;/code&gt;, which never fires on a small repo because the producer finishes writing before &lt;code&gt;head&lt;/code&gt; walks away. Every test I'd written passed. If you only test on small repos, you're only testing the easy case.&lt;/p&gt;

&lt;p&gt;Fixed, measured, and the numbers above are all reproducible:&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;catalogify
catalogify &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then ask your agent for a knowledge bundle. On a monorepo, start coarse.&lt;/p&gt;

&lt;p&gt;Source and issues: &lt;a href="https://github.com/alexcpn/catalogify" rel="noopener noreferrer"&gt;github.com/alexcpn/catalogify&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Package: &lt;a href="https://pypi.org/project/catalogify/" rel="noopener noreferrer"&gt;pypi.org/project/catalogify&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For &lt;a href="https://github.com/github/spec-kit" rel="noopener noreferrer"&gt;Spec Kit&lt;/a&gt; projects the same workflows ship as slash commands in &lt;a href="https://github.com/alexcpn/speckit_okf" rel="noopener noreferrer"&gt;speckit_okf&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It is a few days old and I would rather hear where it breaks than where it shines.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;MIT licensed. Measurements against &lt;code&gt;kubernetes/kubernetes&lt;/code&gt; at &lt;code&gt;d5ccf7968e5&lt;/code&gt;, tokens estimated at bytes ÷ 4. The comparison tool is &lt;a href="https://github.com/Graphify-Labs/graphify" rel="noopener noreferrer"&gt;Graphify&lt;/a&gt;, run AST-only without an API key.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>opensource</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
