Platform Engineering7 November 20269 min read

Codebase Intelligence for AI-Assisted Engineering — Part 1 of 5

Your coding agent does not need more context. It needs a map

When a coding agent misses a downstream effect, the reflex is to give it more files. Part 1 of Codebase Intelligence for AI-Assisted Engineering argues that what it lacks is structure: symbols, references, calls and dependencies it can query before it reads, so that it reads the right files for a stated reason.

#AI Coding#Coding Agents#Platform Engineering#AI Engineering#Software Delivery
A dense block of small translucent tiles representing an old software system, with a luminous graph map floating above it; one amber node sends lines down to the few tiles a change would touch.

Komati Commerce, a fictional South African online retailer, runs a commerce platform that is ten years old. Pricing, inventory, orders and fulfilment grew up as separate teams, then separate services, then a shared database that nobody quite owns. When the business asked for a new delivery-fee rule, a coding agent made the change in the pricing engine in about twenty minutes. The unit tests passed, the reviewer approved it, and it went live on a Tuesday.

On Friday, the finance team found that invoices produced by the fulfilment service no longer matched the totals customers had paid. The fulfilment service recomputes the total from line items, with its own copy of the fee rule. A nightly reconciliation view in the database had a third copy. The agent had read about sixty files during the task. It had simply never been shown that those two mattered.

The team's first instinct was to give the agent more context: a bigger model window, the whole fulfilment folder, the database scripts. This article argues for a different fix. The agent did not lack text. It lacked a map of how the code is connected, and a way to ask that map a question before it started reading.

Why more context stops helping

There are three reasons why loading more files is a poor answer to a missed dependency.

The model uses long inputs unevenly. Research on long-context behaviour keeps finding the same thing. The Lost in the Middle study (Liu and others, published in TACL) found that performance "can degrade significantly when changing the position of relevant information" in a long input. Chroma's Context Rot report (July 2025) tested 18 models and found that "model performance consistently degrades with increasing input length". Neither study is about code specifically, but both describe the conditions a coding agent creates when it fills its window with files.

Volume hides the signal. Sixty files that mention totals, fees or orders contain the two that matter. They also contain a README, a deprecated helper, test fixtures and the user-interface code that formats the total for display. Adding more of the same kind of file adds more distractions in the same proportion.

It costs time and money on every turn. Every extra file is re-read on every step of the agent's loop. Context trimming without losing the evidence covers the economics. The short version is that context you did not need is paid for repeatedly.

The underlying problem is that "which files are relevant?" is not a question about text. It is a question about structure: what calls this function, what reads this column, which tests exercise this path. Text search can only guess at it.

More context versus a mapLOAD MORE CONTEXTTask: change the delivery-fee rulepricing/engine.tsorders/service.tsREADME.mdui/cart-total.tsxtest/fixtures/totals.jsonand 55 more filesRule changed once; two copies missedASK THE MAP FIRSTTask: change the delivery-fee rulePricingEngine.totalOrderServicePricing testsInvoice copyRecon SQL copyRead 6 files, each with a reason
Komati Commerce's agent was asked to change the delivery-fee rule. Loading 60 files found the rule once and missed two copies of it. Asking a map where the rule is used first returned the callers, the tests and the invoice copy, and the sweep for the column name that follows found the reconciliation SQL copy (dashed), so the agent read six files, each with a stated reason. File names and counts are illustrative.

What a map contains

A code map is a model of the repository that an agent can query, not a picture for people to admire. It has layers, and each layer answers a different question.

What a code map containsLAYERQUESTION IT ANSWERSTYPICAL SOURCETextWhich files mention "delivery fee"?grep, embeddingsSyntaxWhich functions and classes exist?tree-sitter parsersSymbols and referencesWhere is this defined and used?LSP, SCIP indexersDependencies and callsWhat calls this, and what does it call?call graph, build graphRuntime and dataWhat actually runs, and what does it write?traces, schemas, SQLIntent and ownershipWhy is it like this? Who decides?ADRs, CODEOWNERS
Each layer answers a different question, and each comes from a different source. Text search is the layer most agents start and stop with. The layer Komati Commerce's agent lacked was dependencies and calls: it could find the rule, but not what else depended on it. No single tool fills every layer, and the intent and ownership layer is mostly maintained by people.
  • Text. Which files contain a phrase. This is grep or an embedding index, and it is where most agents start.
  • Syntax. Which functions, classes and modules exist, and where each begins and ends. A parser provides this without understanding types.
  • Symbols and references. Where a name is defined and every place it is used. This is what "go to definition" and "find all references" do in an editor.
  • Dependencies and calls. What calls this function, what it calls, which modules import which. This is the layer that answers "what else will this change touch?"
  • Runtime and data. What actually executes in production and which tables a path reads and writes. Static analysis cannot see all of it.
  • Intent and ownership. Why the code is shaped this way, and who has to agree to a change. Decision records, code-owner files and the people who maintain them supply it.

The Komati agent had the text layer and nothing else. It could find the pricing engine. It could not ask what depended on it.

Where each layer comes from

None of this needs to be invented. Most of the layers already exist in established tooling, and they differ mainly in how precise they are.

Parsers give you syntax quickly. Tree-sitter, an MIT-licensed project, describes itself as "a parser generator tool and an incremental parsing library" that can "build a concrete syntax tree for a source file and efficiently update the syntax tree as the source file is edited". It is fast and covers many languages, but it works on syntax alone. It knows that a function called total is defined in a file. It does not know, on its own, which of three total functions a given call resolves to.

Language servers and indexers give you precise references. The Language Server Protocol defines how an editor asks a language server for definitions and references. The specification has included call hierarchy requests since version 3.16 and type hierarchy since 3.17, and the site listed 3.18 as the latest version when we checked on 7 November 2026. SCIP, the Apache-2.0 code-indexing protocol that originated at Sourcegraph (its old sourcegraph/scip address now redirects to the scip-code organisation on GitHub), describes itself as "a language-agnostic protocol for indexing source code" and lists indexers for Java, TypeScript, Python, C and C++, .NET, Ruby, Rust and others. The strongest language servers and SCIP indexers build on compiler or type-checker analysis, so they resolve names the way the build does, at the cost of needing a working build for each language.

Graph tools join it up. A newer class of open-source tools parses a repository and writes a queryable graph of calls, imports and inheritance for an agent to use directly. Part 2 examines one of them, Graphify, in detail, including what we could and could not verify.

People supply the top layer. No parser knows why the fulfilment service recomputes totals. A decision record might, or a comment, or the engineer who wrote it in 2019. The Diagrams as Code series covers how repository-derived views and intended architecture are kept honest, and this series does not repeat it.

How an agent should use the map

A map changes the order of work, not the agent itself. The pattern Komati Commerce adopted has five steps.

  1. Orient. Before opening files, ask the map where the concept lives: which symbols, which modules, which owners.
  2. Expand, within a budget. Follow callers, callees and data dependencies a fixed number of hops, and stop. Two hops from the pricing engine reached the order service, the repository, the invoice builder and the tests.
  3. Read with reasons. Open only the files the map pointed to, and record why each one was opened. "Called by OrderService.place" is a reason, while "mentions total" is not.
  4. Sweep for what the map cannot see. Search for the column name, event name and configuration key. Part 3 explains why this step is not optional.
  5. Change, then check the map again. After the change, ask whether anything new now depends on the changed code. Part 5 turns this into a comparison of predicted and actual impact.

This fits the harness thinking in Guides, Guards, Checks and Sensors. The map is a guide that tells the agent where to look before it acts, and it becomes a sensor when the agent queries it again after the change. It also supports the agent-legible repository described in Harness engineering: the workshop around the agent, which made the case for instructions and checks but assumed the agent could find its way around.

What a map cannot tell you

A map is a model, and models leave things out. Be clear about where it is blind before you rely on it.

  • Dynamic wiring. Dependency injection, reflection, plug-in registries and configuration-driven routing create edges that static analysis cannot always resolve.
  • Strings. SQL written as strings, event names, feature-flag keys and URLs connect components without any import between them. Komati's reconciliation view was connected to the order table only by a column name in a SQL file.
  • Other repositories. A map of one repository says nothing about the partner feed in another one, or the job a different team runs against the same database.
  • Runtime. Code that is reachable is not necessarily code that runs. Traces and logs say what actually happens. Generated from reality covers that source.
  • Intent. A graph can show that two functions compute the same thing. It cannot say whether that is an accident or a deliberate separation.
  • Staleness. A map built last month describes last month's code. It has to be rebuilt as part of the delivery path, or it misleads.

None of this argues against maps. It argues for treating the map as an index that points to the code, with the files remaining the source of truth.

Starting small

Komati Commerce did not begin with a platform. It began with one question it could not answer quickly ("what depends on the order total?") and three weeks of effort.

StepWhat Komati didWhy it mattered
Choose a seamPricing, orders and fulfilment, the area with the most escaped defectsValue shows up where misses are costly
Build the cheapest mapA parser-based graph of calls and imports, rebuilt on every mergeSyntax and calls cover most questions at first
Add precise references where it hurtsA language-server index for the two main languagesRemoves ambiguity about which total is meant
Teach the agent the order of workOrient, expand, read with reasons, sweep, check again, written into the repository's agent instructionsWithout the instruction, the agent goes back to searching
Record what the map missedEach surprise becomes an issue: a missing edge, a string reference, a comment to addThe map improves where the system is least obvious
Measure one thingDownstream misses found after merge, per month (tracked, not targeted)Shows whether the map is earning its keep

Key points

  • A missed downstream effect is usually a missing relationship, not a missing file. Adding more context dilutes the signal and costs more on every turn.
  • Long-context research consistently finds that models use long inputs unevenly and degrade as inputs grow.
  • A code map has layers: text, syntax, symbols and references, dependencies and calls, runtime and data, and intent and ownership. Each comes from a different source.
  • Use the map to decide what to read, read with stated reasons, and sweep for the string references the map cannot see.
  • Treat the map as an index. It goes stale, it misses dynamic and cross-repository edges, and it cannot supply intent.

This is part 1 of Codebase Intelligence for AI-Assisted Engineering. It builds on The Coding Agent Harness and Spec-Driven Development. Next: What Graphify actually adds to a coding agent.

Background reading: Lost in the Middle, Context Rot, the Language Server Protocol, Tree-sitter and SCIP. Tool facts were checked on 7 November 2026.

How CloudNala can help

CloudNala runs codebase intelligence reviews for teams whose coding agents are fast but keep missing downstream effects. We pick the seam where misses are most expensive, establish which layers of a code map you already have in your editors, build pipeline and repositories, add the cheapest missing layer, and write the orient-expand-read-sweep pattern into your agent instructions, so the agent reads the files that matter for a reason it can state.


Work with CloudNala

CloudNala helps organisations move from technology ambition to practical execution across cloud, AI, data, platform engineering and digital services.

Whether you are exploring AI, modernising your cloud environment, building a public-sector digital service, or turning an idea into a working MVP, we can help you shape the roadmap and deliver the next step.

Book a Codebase Intelligence Review or write to us at consult@cloudnala.co.za