Side quest: anchors (early results)
Static analysis plus LLM enhancement, and a PoC that found a bug 32x faster than an AI agent crawling the code.
In the last post I talked about the code archaeology problem, AI tools getting lost in big codebases. This is what I've been building since.
# The workflow
You drop an anchor comment on an entry point:
// @anchor:get-recommendations
public CompletableFuture
Then you run the analyzer, which uses tree-sitter to parse the code, builds a call graph from that entry point and spits out an .anchor.yaml file. Then you run enhance. The LLM reads the method signatures and adds business context, parameter descriptions, debug keywords, stuff that helps future prompts understand what the code does and not only how it's structured.
# What an anchor file looks like for now
anchor_name: "get-recommendations"
methods:
- id: "ApiService.getRecommendationsAsync"
file: "src/.../ApiService.java"
line_range:
method_signature: "public CompletableFuture<Page<Item>> getRecommendationsAsync(...)"
# LLM-enhanced fields
business_context: |
Main API endpoint for recommendations feature. Returns paginated items
based on user's history and subscription preferences.
parameters:
- name: "userId"
description: "User identifier"
- name: "type"
description: "Type of recommendation view (TRENDING, RECENT, etc.)"
debug_keywords:
calls_methods:
called_by_methods:
business_context says what the method does in human terms, debug_keywords help you find it when you're searching for a problem, and calls_methods gives you the full graph without the LLM having to crawl.
# The PoC
I tested this with a real bug I had already fixed. Old items from years ago were showing at the top of a feed, above recent ones. A sorting issue somewhere in the codebase.
When I fixed it myself it was maybe like 10 minutes of context switching and another 10 creating a test to replicate the behaviour and debug. I don't really remember...
Without anchors, Claude CLI crawled through the codebase for 8 minutes. Reading files, backtracking, reading more files. It eventually found the right spot (somewhat impressive).
With anchors I gave the same prompt to a basic chat model with just the anchor file. 15 seconds. It pointed to the exact line in SortingUtils.java:x-y.
Same answer, 32x faster, and the anchor version didn't need an agentic model burning tokens on file exploration. I think it works because the anchor file front-loads the hard work. The LLM doesn't have to figure out where the sorting logic is, the call graph already traced it, and it doesn't have to guess what userId means because the enhanced params explain it. It just reads structured context and reasons about it, which is the thing it's good at.
# What's next
Still early, not sure this proves anything. It was an overly optimized duct-taped test, and I need to build something a bit more solid to be able to test it systematically. Like using fingerprints (hashes of method bodies) to detect when code changes, so I don't re-enhance unchanged methods. Cause right now it takes forever to generate these files...
Not sure how far this goes yet, but the early results are promising enough that I'm going to keep poking at it. What surprised me is that I thought the main reason to do this was to reduce the hallucinations, but honestly now I see it being very useful for speed/token reduction. Even more for large codebases with large teams...