- In short
- Legacy codebase decomposition is the application of dynamic adaptive decomposition to code whose structure and dependencies are unknown upfront. You map the codebase first, identify high-impact areas from dependency analysis, then build a prioritised plan that adapts as new dependencies emerge.
What legacy codebase decomposition means
Legacy codebase decomposition is a specific, practical application of dynamic adaptive decomposition: you are pointing the adaptive strategy at real code whose structure and dependencies are not documented and not known in advance. This is an apply-level knowledge point, so the exam is less interested in whether you can define the strategy and more interested in whether you can carry it out in the right order on an unfamiliar codebase.
The defining condition is uncertainty about structure. When you inherit a legacy service, you do not yet know which modules are central, how data flows, or where the risky coupling lives. That uncertainty is exactly why a predetermined plan fails and an adaptive one succeeds: you cannot enumerate the steps until you have looked, so the looking has to come first and the plan has to emerge from it.
- Legacy codebase decomposition
- Applying dynamic adaptive decomposition to a codebase whose structure and dependencies are unknown upfront. The agent maps the codebase first, uses dependency analysis to find high-impact areas, and builds a prioritised plan that continues to adapt as new dependencies are discovered.
The sequence: map, prioritise, then plan adaptively
The order of operations is the heart of this knowledge point, and getting it wrong is what the exam penalises. There are three moves, and they must happen in this sequence.
Map the structure first. Before proposing any change, the agent surveys the codebase, directory layout, modules, entry points, and the dependency relationships between them. This converts an opaque pile of files into a navigable map. Mapping is itself a discovery step, and it is the foundation every later decision rests on.
Identify high-impact areas. With a dependency map in hand, the agent finds the areas that matter most, the heavily-depended-upon modules, the central data paths, the code whose change would ripple widest. Prioritisation is driven by the structure you just discovered, not by guesswork.
Build a prioritised plan that adapts. Only now does the agent propose concrete work, ordered by impact. Crucially, the plan stays adaptive: as the agent acts on high-impact areas, it discovers new dependencies that can reshuffle what comes next. The plan is a living thing, not a frozen pipeline.
Why mapping cannot be skipped
The temptation on a legacy task is to jump straight to changes, start writing tests, start refactoring, because action feels like progress. On unmapped code it is the opposite of progress. Without the structural map, the agent has no basis for prioritising, so it spends effort on peripheral code while the high-impact, high-risk areas go untouched. Worse, it makes changes blind to dependencies and triggers breakage it could not foresee.
It is worth naming what "mapping" actually produces, because vague mapping is barely better than none. A useful map is concrete: the entry points, the module boundaries, a dependency graph with directions, and the locations of shared state. Producing it is itself a discovery activity that the agent decomposes dynamically, a broad first pass to list the modules, then targeted passes to trace the dependencies the broad pass flagged as dense. The map is not handed down; it is built by the same adaptive process that will later guide the changes, which is why legacy decomposition is dynamic from its very first step.
Mapping first is what makes the rest of the work targeted. It is also why delegation fits so well here: the heavy, context-hungry job of reading large swathes of unfamiliar code is a natural candidate for a subagent that explores in its own context window and returns a distilled map. Anthropic's Claude Code subagents are designed for precisely this, a side investigation that would otherwise flood the main conversation runs independently and returns only the summary, and the orchestrator-workers pattern lets a coordinator generate mapping and analysis subtasks it could not have planned before seeing the code.
Reading the map to find high-impact areas
The middle move, identify high-impact areas, is where legacy decomposition succeeds or fails, so it is worth being concrete about what "high-impact" means. It is not the biggest file or the oldest one; it is the code whose change would ripple furthest. The dependency map you built in step one is what makes impact visible, and a few signals on it do most of the work. Fan-in is the strongest: a module imported by many others is, by definition, load-bearing, and a regression there propagates everywhere it is used. Hot paths matter next, code on the critical request or data-flow route carries more risk than code that runs rarely. And shared mutable state is a flashing light, because anything several modules read or write is both high-impact and easy to break in surprising ways.
Prioritising by these signals turns an unbounded legacy task into a ranked queue. You attack the load-bearing, hot, state-touching code first, because that is where effort buys the most safety per unit of work, and you defer the leaf modules that almost nothing depends on. This is the opposite of the file-order or alphabetical instinct, which spends effort by accident of naming rather than by importance.
Impact ranking has a safety corollary the exam cares about: the most-depended-upon code is exactly the code you least want to change blind. So the adaptive plan schedules not only what to touch first but how to touch it safely, characterising existing behaviour with tests before changing it, so a regression in a load-bearing module is caught immediately rather than discovered in production. Mapping reveals where risk concentrates, prioritising sends your effort there, and changing behind a safety net keeps high-impact work from becoming high-damage work. That sequence, understand, prioritise, protect, change, is the disciplined shape of every good legacy intervention.
Capturing the map with CLAUDE.md and just-in-time retrieval
Mapping is far more useful when the map is written down somewhere the agent will reread it. Anthropic's guidance on context engineering frames Claude Code as a hybrid retrieval agent: it reads a CLAUDE.md context file at the start of a session, then navigates the code just in time with tools like glob and grep rather than preloading the whole repository into context. For a legacy task this is the efficient shape, because pulling an entire unfamiliar codebase into one context window is exactly the overload that mapping exists to avoid; the same guidance notes that agents can compress redundant history while preserving the architectural details that matter.
A practical move is to record the discovered structure as a hierarchical set of CLAUDE.md files: a lightweight root map that lists the top-level folders with a one-line description each, plus deeper subdirectory files that capture local conventions and the gotchas you only learn by reading the code. The map you build in step one then persists, so later sessions start oriented instead of rediscovering the layout. Anthropic's Code Modernization Playbook describes the same archaeology-first posture, using the agent to surface job flows, data dependencies, and the business rules buried in old subroutines before any rewrite, so modernization decisions are grounded in the system that actually exists rather than in assumptions about it.
How it differs from a fixed pipeline approach
It helps to see the contrast directly. A fixed pipeline would commit to steps like "read the README, write tests for each public function in order, refactor module by module" before looking at the code. On a legacy codebase that plan is fiction: there may be no README, the public surface may be unclear, and module order tells you nothing about impact. The pipeline runs to completion having spent its effort by file order rather than by importance.
Legacy codebase decomposition refuses to commit until it has mapped. It lets the structure decide the priorities and lets discoveries during the work reshape the plan. That is the same dynamic-versus-fixed tension you weigh in choosing a decomposition strategy, and on unknown-structure legacy work, the unknown scope is precisely the signal that pushes the decision toward the adaptive approach.
Worked example
An architect must add meaningful test coverage to a legacy billing service with almost no documentation and no existing tests.
Jumping in to write tests file-by-file would be a fixed-pipeline reflex, and it would waste effort. The architect instead applies legacy codebase decomposition.
First, the agent maps the service. A subagent reads the codebase and returns a structural summary: the entry points, the modules, and a dependency graph showing that pricing.py and tax.py are imported by almost everything, while several reporting modules are leaf nodes used nowhere else.
With that map, the agent identifies high-impact areas. The dependency analysis makes the priority obvious: pricing.py and tax.py are central, so a regression there would ripple across the whole service, whereas the leaf reporting modules are low-risk. Testing effort should concentrate on the central modules first.
Because pricing.py was load-bearing, the agent did not start by altering it. It first wrote characterisation tests that pinned the module's current behaviour, including a couple of quirks that turned out to be relied upon downstream, so that any later change would trip a test rather than ship a silent regression. The fan-in that made pricing.py the top priority is the same fan-in that made changing it blind so dangerous, and the plan accounted for both.
The agent then builds a prioritised plan, test pricing.py, then tax.py, then the invoicing flow that depends on both, and starts executing. While writing tests for pricing.py, it discovers an undocumented dependency on a currency-conversion helper that mutates shared state. That discovery feeds straight back into prioritisation: the helper is now a high-impact area too, and the plan reshuffles to cover it before invoicing. None of this could have been scheduled in advance, because the dependency was invisible until the work surfaced it. Mapping first, prioritising by impact, and letting discoveries reshape the plan is the application skill the exam is checking.
Common misconceptions
Misconception
For a legacy codebase you can use a fixed pipeline as long as you write a detailed enough plan first.
What's actually true
Misconception
The fastest way to make progress on legacy code is to start changing the most obvious files immediately.
What's actually true
How this shows up on the exam
Because this is apply-level, exam scenarios describe a legacy or unfamiliar-codebase task and ask how an agent should approach it, or they show an approach and ask what is wrong with it. The credited answer almost always leads with mapping the structure before planning changes, then prioritising high-impact areas from dependency analysis, then keeping the plan adaptive. The reliable trap is an option that applies a fixed pipeline to unknown-structure code, or one that starts making changes before any mapping. Anchor on the order, map, prioritise, adapt, and remember that the unknown structure is what makes a legacy task an open-ended investigation rather than a predictable process, which is why it belongs to dynamic decomposition and not to a fixed pipeline.
An engineer asks an agent to modernise an undocumented legacy module. The agent immediately begins rewriting files in alphabetical order. Midway it breaks a downstream service that depended on behaviour in a file it had not yet reached. What should the agent have done instead?
People also ask
How should an agent approach a legacy codebase task?
Why map a legacy codebase before planning changes?
Should you use a fixed pipeline on a legacy codebase?
Watch and learn
Official Anthropic Academy lessons first, then hand-picked walkthroughs. Videos load only when you press play.
Environment inspection
Why watch: Mapping unknown structure first before planning changes is the legacy/unknown-codebase approach this KP teaches.
More videos for this concept
References & primary sources
Master this concept with Archie
Practice it inside an adaptive study session. Archie, your Socratic AI tutor, tracks your mastery with Bayesian Knowledge Tracing and schedules the perfect next review.