Topic 01

Mapping a Codebase With an Agent

Legacy Code

The fastest way into a codebase you did not write is to ask the agent to read it and draw you a map. The map arrives in a minute, reads like the work of someone who has been on the team for years, and is partly invented. The habit this page teaches is treating the map as a hypothesis: every box on it gets checked against a file and a line before you rely on it.

Cragmoor's booking service is about 60,000 lines, three years old, and written mostly by people who have left. Ines wants the untested pricing module made safe to change, and before anyone touches it, you need to know where money is actually computed, which is not the same question as where the module called pricing is.

Asking for the Map

"Explain this codebase" produces an essay. The request that works names the questions a newcomer actually needs answered and asks for the evidence alongside each answer. Where does a booking request enter? Which module writes the booking? Where is money computed? Where is time computed? What runs on a timer? Which modules have tests? For every answer, give the file and the function. A claim that arrives with a location can be checked in seconds; a claim without one can only be believed.

Six questions, each answered with a place in the code
Youthe request
Map the booking service for me. Where does a booking request enter? Which module writes the booking? Where is money computed? Where is time computed? What runs on a timer? Which modules have tests? Give a module and function for every answer, and list the files you opened.
The agentthe answer, abridged
Requests enter through the HTTP handlers, the booking routes. booking writes the booking, in its confirm function. All money is computed in pricing: the class price and the pack price. Time goes through schedule's time-zone helper. The waitlist sweep runs every 30 seconds and expires the 15-minute holds. booking and waitlist have tests; pricing has none.

The answer is useful and it is fluent. One sentence in it is wrong, and nothing in its tone tells you which.

Where Maps Go Wrong

The agent cannot read three years of code into one session. Chapter 4 explained why: the context window holds a sample, and long sessions blur what was read early. So the agent opens some files, reads names and folder layout for the rest, skims a README written when the service was new, and extrapolates. Where the code follows its own names, the extrapolation is right. Where it does not, the map is wrong in exactly the places that matter.

A module called pricing gets credited with all of the pricing. That is the natural reading of the name, and it is how Cragmoor's map misses that refunds recomputes the member discount with its own copy of the 10% rule, so a refund for a member is computed by code nobody thinks of as pricing. Ask the agent which files it actually opened. On a service of several hundred files, the honest answer is usually about a dozen. Everything else on the map came from names and conventions.

Two other patterns produce confident errors. Renamed concepts are one: the first version of the service called classes "sessions", and some old code still does, so a map built from names can report that sessions and classes are two different things. Modules whose names promise more than they hold are the other, and pricing is the example at hand. Both have the same signature. The map is most confident exactly where the names are most misleading, because names are what it was built from.

Checking the Map

Checking is mechanical. For each claim, open the file and function it names and confirm the claim in a minute. Then do the one check that finds what the map hid: search the whole repository for every fact the map says lives in one place. The discount rate, the 16:00 off-peak cut-off, the 15-minute hold. Every second hit is a correction to the map.

The agent can help with the first kind of check, provided it checks rather than restates. "For each claim on your map, quote the line that supports it" turns the map into a list of quotations you can open one by one. A claim the agent cannot quote is a claim it extrapolated, and it goes on the list of things to read yourself.

The search for the discount rate takes less than a minute. The rate is written as 90 percent or as 0.90, depending on who wrote the line, so search for both as whole words:

Searching for the discount rate
$ git grep -l -w -e 90 -e 0.90 -- src
src/cragmoor/pricing.py
src/cragmoor/refunds.py
$ git log --since="1 year ago" --format= --name-only -- src | sort | uniq -c | sort -rn
  64 src/cragmoor/booking.py
  41 src/cragmoor/waitlist.py
  29 src/cragmoor/schedule.py
  17 src/cragmoor/refunds.py
  12 src/cragmoor/members.py
   2 src/cragmoor/pricing.py
Searching for the discount rate
$ git grep -l -w -e 90 -e 0.90 -- src
src/pricing.ts
src/refunds.ts
$ git log --since="1 year ago" --format= --name-only -- src | sort | uniq -c | sort -rn
  64 src/booking.ts
  41 src/waitlist.ts
  29 src/schedule.ts
  17 src/refunds.ts
  12 src/members.ts
   2 src/pricing.ts
Searching for the discount rate
$ git grep -l -w -e 90 -e 0.90 -- src
src/main/java/org/cragmoor/Pricing.java
src/main/java/org/cragmoor/Refunds.java
$ git log --since="1 year ago" --format= --name-only -- src | sort | uniq -c | sort -rn
  64 src/main/java/org/cragmoor/Booking.java
  41 src/main/java/org/cragmoor/Waitlist.java
  29 src/main/java/org/cragmoor/Schedule.java
  17 src/main/java/org/cragmoor/Refunds.java
  12 src/main/java/org/cragmoor/Members.java
   2 src/main/java/org/cragmoor/Pricing.java

Two files, not one. The second command, in the same block, is the subject of the next section. The first is the whole correction: the map's confident "all money is computed in pricing" has a second home for the same rule, which means any change to the discount must change both, and nothing in the code says so. The agent's paragraph had hidden it; a search that does not interpret anything found it.

Questions History Answers

Git answers questions the code cannot. Which files change most? The churn list points at the parts of the service people work in every week, and the parts nobody dares to touch. Who wrote a module, and are they still here? When did a module's tests last change? The second command in the block above counts commits per file over the last year.

The output tells a story the map did not. booking and waitlist change constantly: 64 and 41 commits in a year. pricing changed twice. That is not stability. A module that computes every price in the business and changes twice a year with no tests is a module nobody dares to touch, which makes it the riskiest code in the service, not the safest. The agent can run these commands and read the output for you. The output is evidence in a way its summary is not, because churn and authorship are counts, and counts cannot be misremembered.

Which tool answers which question about unfamiliar code
How do the parts fit together, roughly?→Ask the agent for a map with locations
Does this rule live in one place?→Search the repository
Is this claim on the map true?→Open the file and function it names
What changes often, and who knows it?→Read the history

What the Map Is For

The map is not documentation. Its job is to decide where you read carefully. At Cragmoor it points at one module: untested, rarely changed, handling money, with a duplicate of its central rule elsewhere. That module gets the next two pages, first pinned with tests and then changed in safe steps.

The map also produces facts worth keeping, and here the rule from Chapter 4 applies with force. Checked facts go into the project instructions file or the team's notes: "the member discount is applied in two places, pricing and refunds; change both". Unchecked ones do not. A wrong fact written into the instructions file becomes the context of every future session, and each of those sessions will act on it with the same confidence the map was written with. Write down only what you verified, and say how.

The check also teaches you the code. By the time every claim on the map is confirmed or corrected, you have opened a dozen files with a question in mind, which is how most engineers learn a codebase anyway. The agent made the first draft fast. The checking made it yours.

Misconceptions
  • "The agent read the whole codebase." It read what fit in its window and what it chose to open. On a service with several hundred files that is a sample, and the parts it did not open are filled in from names and conventions.
  • "A detailed map is a checked map." Detail is cheap to generate. Cragmoor's map named forty functions correctly and still left out the copy of the discount rule in refunds.
  • "The tests describe the behaviour." Only where tests exist. pricing has none, so for the module that handles money, the code is the only specification and the map is a guess about it.
  • "Reading the code myself is the slow path." Map first, then a targeted check of each claim, is faster than either reading everything or trusting the map, and it is the only one of the three that ends with facts.
Why It Matters
  • Ask for a file and function behind every claim on the map. A claim with a location can be checked in seconds; one without can only be believed.
  • Search the whole repository for every rule the map says lives in one place. Duplicated business rules are where legacy code hides its second behaviour.
  • Run the history commands and read their output, not a summary of it. Churn and authorship are counts the agent cannot misremember.
  • Write only checked facts into the instructions file. A wrong entry there misleads every later session, with full confidence.

Knowledge Check

The agent produces a detailed map of a service with several hundred files after opening about a dozen. Where did the rest of the map come from?

  • From a full index of the repository that the agent builds before answering any question
  • From names, folder layout and conventions, extrapolated from the files it actually opened
  • From the test suite, which the agent runs in the background to learn each module's behaviour
  • From the project's git history, which records which functions call which across all files

Where is a confident map of legacy code most likely to be wrong?

  • In the modules with the most commits, because frequent change makes them hard to summarise
  • In the framework code at the edges, because the agent does not recognise third-party libraries
  • In the test files, because tests are written in a different style from production code
  • Where a rule is duplicated or a module's name promises more than it actually holds

You want to know whether the 16:00 off-peak cut-off is applied in more than one module. What is the best tool?

  • Ask the agent whether the cut-off appears anywhere other than pricing
  • Search the whole repository for the cut-off value, and read every hit
  • Read the history of the pricing module to see when the cut-off changed
  • Run the test suite and check whether any test fails at 16:00 exactly

After mapping, what belongs in the project instructions file?

  • The agent's whole map, so that future sessions start with a complete picture of the service
  • Nothing from the map, since instructions files should hold only commands and code style rules
  • The facts you checked, such as the discount being applied in both pricing and refunds
  • A note to always read the whole repository before answering any question about pricing

You got correct