Legacy Software + Agentic Discovery

The Code Base as a Crime Scene: Understanding Software Truth

Speaker G opens with a metaphor comparing an existing code base to a crime scene, arguing that working code is the ultimate source of truth but is largely inaccessible to non-engineers. He explains how engineers act as gatekeepers of this truth and how even simple button clicks can involve complex, cross-system logic that's hard to trace manually or via AI tool calls.

From Code to Feature Definitions: Building a Readable Layer

The speaker introduces the concept of 'feature definitions'—a readable layer that explains software functionality in plain language while maintaining traceability to underlying code. He discusses the importance of linking related features rather than duplicating documentation, and notes that current AI coding tools like Claude Code or Codex often fall short on large, complex legacy systems, motivating UserDoc's 'Code to Docs' approach.

Version One: A 30-Step LLM Pipeline

Speaker G details the architecture of Version One, a 30-step LLM pipeline built over 14 months to reverse-engineer code into detailed software definitions. He walks through key steps including creating a language-agnostic 'codenalysis' JSON representation, building a cross-architectural code map using tools like TreeSitter and Roslyn, and grouping code into business-domain themes using vector embeddings to manage context window limitations.

Extracting Features and Managing Relationships

The speaker explains the challenge of defining and sizing 'features' from code, noting the subjectivity involved in determining feature boundaries. He describes how thousands of LLM passes were used to identify features and their relationships, including cross-cutting features like soft deletes, culminating in a knowledge graph that synthesizes accurate, trustworthy feature definitions for customers considering modernization or rebuilds.

Version One's Success and Rigorous Validation

Speaker G describes six months of rigorous manual testing across multiple languages, frameworks, and five large open-source code bases, achieving 85% accuracy—comparable to human accuracy on complex systems. This version delivered significant early value, helping five customers save months of manual documentation work by generating results in hours.

Breaking Point: A 12-Million-Line Legacy Nightmare

The speaker recounts a breaking-point case: a 30-year-old Visual Basic system with 52,000 files and 12 million lines of code, featuring million-token files and deeply nested logic. Despite nearly abandoning the project, his team spent two months customizing the pipeline to deliver 7,500 feature definitions, though the solution proved unscalable for future customers with equally unique complexities.

Pivoting to Agents: Rethinking the Approach

Facing scalability limits after spending $250,000 on Version One, Speaker G explains his decision in February to abandon the rigid pipeline model and rebuild from scratch as an agent-first system. He describes initial failed attempts to have agents orchestrate the old pipeline, realizing agents needed a fundamentally different communication and collaboration mechanism to thrive.

Agent Missions: Mapping the Software Sphere

The speaker introduces a new metaphor of software as a 'sphere,' with agents sent on discovery missions to map entry points (the surface) and then mine inward through execution tunnels to uncover features and dependencies. He explains how an orchestration agent coordinates communication between agents, removes duplication, and enables deep excavation of data lineage—ultimately reaching the same 85% accuracy as Version One's 30-step pipeline, but through simpler agentic 'missions.'

Custom Agent Tools: Questions, Hints, and Deterministic Hooks

Speaker G details three custom tools given to agents to handle software's unique complexities: the ability to ask questions instead of making assumptions, dropping reusable 'hints' for expensive discoveries so the swarm collectively gets smarter, and writing deterministic hooks for repetitive patterns like translation lookups. These tools allow the agentic system to codify weirdness into reusable infrastructure, with human approval required for hooks.

Version Two Results and the UserDoc Platform Demo

The agentic rebuild achieved 92% accuracy, processing over 7 million lines of code in five weeks, including a 47-year-old obscure programming language that previously required two months of custom pipeline work. Speaker G shows a low-resolution demo of the UserDoc platform, showcasing features organized by business domain, their relationships, detailed definitions, and links to supporting code, plus collaborative and AI-integration capabilities.

Closing Reflections: The Future of Software Definitions

Speaker G reflects on the dramatic efficiency gain—Version One took 14 months while the agentic rebuild took under four weeks—crediting the right harness, model, and agent collaboration tools as the future of software engineering. He closes by advocating for 'software definitions' as a shared, accurate, and accessible organizational asset for technical and non-technical teams alike, as well as AI agents, wrapping up his 14-month journey.

Awesome. Thank you, team. An existing code base is a crime scene. You arrive after the incident, it's been tampered with sometimes thousands of times, there are many witnesses, most are no longer around and the ones that are around, maybe they're not that great at communicating. There's millions of clues, every product decision, business decision, architectural compromise, they're all leaving evidence. But what exactly is the truth?

The working software is the truth. I can see the truth. I click a button on the screen and I can visually see what happens. But I only see the external effects. It's not clear that that button is only there because I'm in this user permission. I also don't understand that when I click it, something behind the scenes happens invisibly.

We can't understand exactly how software systems work solely from interacting with them. Now we know that code is the source of truth and it doesn't matter if that code is messy, gross, over engineered or scattered across thousands of different code files that you

would love to

refactor. As engineers, we've spent our careers learning to wield these mystical programming languages so we can communicate to computers using code. But most people in your organizations cannot read code. This made engineers the interpreters or the gatekeepers of that truth. Now to understand what happens when I click this button, it might seem, you know, easy but it could be deceptively complex.

It might involve hundreds of invocations across front end, APIs, back end, maybe the database logic, microservices if you went down that route. And whether that's a developer manually reading and navigating these files or an AI agent traversing via many tool calls, understanding the truth of how this feature works just from reading the files and functions every time is a really cumbersome and splintered process.

But if we roll up that complex call graph of files and functions, we can build a feature definition, a readable layer that explains in plain language that everyone can understand what this feature does. It doesn't replace the code by any means, but it augments it with traceability back to the exact files that implement this feature and how.

Now features don't live in isolation. Understanding the relationships between software features is just as important as understanding their individual functions. One feature might navigate to another feature. It might contain child features or it might include or reference functionality in global features. For maintaining knowledge, this content needs to be centralized and linked, not repeated again and again.

Duplication is the slow death of documentation. Now you can ask Claude Code or Codex to document what happens when I click that button. And for a small system, that might be perfect. But as Matt mentioned in the last talk, like whilst amazing at coding, these coding harnesses often stop and fall short just as it gets to good enough.

It might miss like tracing every conditional branch and pathway to the very end. And when we're talking about perhaps gigantic complex legacy software, the devil is in those details. And this is what we've been tackling at UserDoc with a feature called Code to Docs where we reverse engineer code, whether that's COBOL or React or everything in between, into those detailed software definitions.

Over the next fifteen minutes, I'll take you through the journey of this process, what works, didn't work, lessons learned, all that stuff. Hopefully you guys can find some repeatable patterns that you can take away to your own work. So version one of this and I'll just say version one was started about fourteen months ago. And I think in AI years, that's about seventy two years ago.

It was a 30 step LLM pipeline where each one of these individual steps in the chain was its own complex subsystem. For a large code base, we might be talking tens of millions of LLM calls with a token cost of, you know, 30 to $40,000. And we were optimizing for quality over cost. I wanted this to be self serve so you could rock up, connect your code, answer a few questions, and depending on the size of the code base, you know, between two hours or twenty hours, you would have your detailed software specs.

As this was just version one, I'm not going to go through every step, but I'll give you a high level overview of how we initially tackled this. First thing, we turned every code file in the system into a single language agnostic JSON representation called a codenalysis. It contained a brief overview of what it did, the functions, the arguments, the data flow, categorization to metadata, etcetera.

As future steps in this pipeline could get ridiculously expensive, this gave us a very token efficient artifact to work with. We then built a code map, which is essentially like Yellow Pages to quickly look up file dependencies and relationships. We could we could leverage static analysis tools like TreeSitter or Roslyn if it's dot net.

But importantly, this needed to work across architectural boundaries. So if a front end TypeScript component calls a URL in the back end for an API, we needed to map what API endpoint resolved that data. If that API then wrote to a database table and that triggered a database trigger on the SQL layer, we needed to map that dependency as well.

We used vector embedding to then group those artifacts into high level themes by business domain. So in a fictional system, this could be authentication, ordering, invoicing, etcetera. We grouped every code file into those themes, so essentially slicing a large piece of software into small little domain specific code bases. This was primarily for context window limitations.

But even still, with like 1,000,000 context windows we have today, a large code base can be 1,000,000,000 tokens. So we're talking ginormous amount of information here. These themes often were actually really useful as well as a first human in the loop checkpoint so customers could take an initial look to make sure that, you know, it was covering everything their system had.

For every theme, we did thousands of LLM passes to basically tease out and uncover the features. So the features are submit order, add to cart, process order, receive notification, etcetera. The tricky part here is if you ask 10 people in a room what a feature is, you'll get 10 different responses. It's not a scientific unit. Is it a screen?

Is this individual address lookup component, should that be factored into its own feature? It's actually super complex. So correctly sizing and splitting those features into like maintainable documentation is a real art. And we spend a lot of time working with beta customers to refine that. As I mentioned, features have relationships. So not just that feature a links to feature b, but also that, you know, once we process a giant code base, we might find out that there are cross cutting features.

By that, I mean very repeatable bits of information such as soft deletes or like handling, you know, notifications that are referenced from thousands of features. So very very importantly, we want them linked and not repeated. Basically, after all these 30 complex steps and human and loop sign offs, we had a detailed knowledge graph that we could then synthesize into that feature definition that I showed you.

All those upstream steps were simply in place to make sure that this was accurate and trustworthy enough for customers to use moving forward. They might want to do a modernization. They might want to rebuild. But either way, they needed to be able to trust the artifact. And version one worked. We did rigorous testing over six months, evaluations across different languages, frameworks, and five very large open source code bases.

These were manual testing. There is no way we could really actually get another LLM to be a judge there. So we spent a lot of time, yeah, doing a lot of business analysis essentially. We hit our goal of 85 accuracy. And that, you know, that doesn't sound a 100% perfect, but we figured out quite quickly from feedback that humans are around 85% accurate when looking at a very large complex code base.

And this provided significant value to early customers. We got five customers very fast in in the next couple of months of launch, and we saved them man months of manual documentation and and did it in hours. It worked until it didn't work. Along came a customer with a piece of software with 52,000 files.

It was 12,000,000 lines of a thirty year old Visual Basic system. They were about to embark on a mammoth rebuild over the coming years, and they, first of all, needed to understand what was the current state. No one in their organization knew all the features and how it all worked, and they certainly didn't have accurate documentation. A new legacy systems had skeletons in the closet, but this was next level. There were single files which were well over 1,000,000 tokens.

Their inheritance changed like a 100 levels deep, and core logic mainly lived in deeply nested stored procedures in the database. I nearly closed down my business and ran away, but we got it done. Instead, we worked, full time for two months, many meetings with the customer and their subject matter experts, traversing the code base, finding those skeletons. We ultimately either replaced or highly customized nearly every step in that 30 step pipeline just to work on this system.

But it was a success. We delivered seven and a half thousand detailed feature definitions where the customer came back and said they estimate that that would have taken them around five years to do internally. But it certainly couldn't scale. Our next couple of customers had equally weird, gigantic software in a completely different flavor of weirdness.

It was those unknown unknowns which couldn't scale. You know, we'd spent around $250,000 building out version one and testing it. And whilst those learnings were priceless, we couldn't keep adding steps to it like a state machine workflow to deal with the unique complexities of software. So probably by the name of the talk, it's not surprising to know that agents are the answer.

I knew that with the right resources and setting that agents can deal with those uncertainties. I tried initially letting an agent just orchestrate the version one pipeline, but it just wasn't it was too rigid. And agents need agents thrive with a different kind of communication mechanism. So in early February this year, I made the decision to throw away version one and completely start version two from scratch as an agent first CLI. And this is how I did it.

If you picture software as a sphere on the surface, on the outside of the parts that other systems and people touch. You might have a user interface, screens for human, systems integrations from other systems or a process or batch job for like scheduled tasks. Now not all code, not all files in a code base are equal. Everything inside this sphere exists to support that surface.

It's the plumbing, the logic, the persistence layer. So first, we send agents on a discovery mission, map the surface of the sphere and report back what they find. It's a preflight mission that also does discovery and can is used in these later steps. From each of the entry points that have been found, agents then mine the execution tunnels inwards to the sphere, finding both direct and indirect file dependencies and figuring out those relationships as they move through it. Whilst mining the tunnels, they report any of the high level features that they're finding to an overarching orchestration agent, and they're taking into account those feature sizing and slicing rules I mentioned, again, as they work. This orchestration agent allows, you know, the communication between agents, and importantly, it can remove duplication as it goes.

Each high level feature is then deeply excavated, finding the data lineage throughout the system and building the relationships between features. Agents don't often need to read the entire file. We can use static analysis and, you know, LSPs to pluck individual functions and and variables so it can get what it needs in a token efficient manner. And the output of those three steps I showed you is that same detailed feature definition that we got from the 30 steps in version one. And we hit parity.

So with tens of thousands of agents using those deceptively simple steps, we hit 85% accuracy on our eval code bases. I call these missions as opposed to steps because in a pipeline, obviously, an agent might do like a 120 tool calls to actually get something done. But importantly, this didn't solve those unique weirdnesses I I spoke of. For that, we had to give the agents the ability, with three custom tools.

So the first one, like any AI, it will make it will make assumptions if it doesn't have context. And in a code base, this would be unresolved references, logic outside the repo, maybe something important in a CSV file on some shared drive that it can't read. So we want the agents to stop and ask questions instead of assuming. Those questions are initially to other agents in the swarm.

If they don't have the correct answers, it bubbles up to our team, and we can actually bubble that up to subject matter experts on the customer side. Those questions and their authority of answers then become shared context for the rest of the agents. Some discoveries are expensive via tool calls, and they're reusable. So resolving an API endpoint string might involve 20 tool calls across routes, middlewares, inheritance, etcetera.

Once an agent figures something like this out, it can, drop a hint for other agents which they can then use to upskill. So instead of repeating the same boring nuance again and again, the swarm gets smarter as it progresses. As thousands of agents are doing this through a code base, deterministic patterns can sometimes emerge. They might find something that shouldn't be left up to AI.

For example, say all the user interface text comes from a giant XML file of translations. Right? Agents have to keep on grepping again and again. To solve this, we allow agents to actually write deterministic hooks. So they can write a hook, for example, that when the other a next agent requests a user interface file, the hook fires and the translations are automatically replaced in line.

So that a Next agent doesn't even need to know about this complexity. It's automatically being solved. Those hooks are approved by a human. And as we go, the weirdness becomes the infrastructure. The agentic rebuild worked with those three separate missions and those agent tools. It was faster, significantly cheaper, and importantly, more scalable.

We hit 92% accuracy on our eval benchmarks. In the last five weeks, we've processed over 7,000,000 lines of code through this agentic rebuild. The last one was a forty seven year old programming language that I'm sure no one in this room has heard of. And that system alone probably would have taken again another two months of custom work on that original pipeline.

The customer again said it would have taken multiple team members, multiple years to get that result. And this is a very low resolution image of what the customers end up with. So this is the UserDoc platform. We can see the code organized by their business domains. You can see the individual features and their relationships between each other.

You can click and dig down into those features, seeing their detailed definitions with links to their supporting features. And you can also see the code files that back up and implement those features and how they do so. Customers then use the broader UserDoc platform to collaborate, make version control changes, use AI to make new features, generate test cases, and ultimately integrate that with AI coding tools or other AI tools.

The research development iterations of v one took a bit over twelve months, about fourteen months for for two people. The AgenTic rebuild took me just under four weeks from scratch. Part of that is because in 2026, an experienced software developer armed with a state of the art coding model and a few grand in tokens can do amazing things.

But I think the main reason is that when agents are using the right harness, the right model, they have the correct tools. They can ask each other questions and other people questions. They can then share that knowledge, and they can importantly identify and build deterministic hooks that this is the future of software engineering. And something that is significantly less code can do amazing things.

That's the journey. That's the adventure I've taken over the net the last fourteen months. If you guys are familiar with spec driven development, you might think that, you know, this sounds a lot like specs. I think specs are kind of future historically facing. The word documentation also sounds a bit historic. So I like the term software definitions, but irrespective of what we call it, I don't think these should be trapped inside a code repo just for developers.

My general belief is a shared accurate definition of what your software actually does readable by technical, nontechnical teams alike and your AI agents is gonna be a huge organizational asset for every business moving forward. It's my story. Thanks, team.

An existing codebase is a crime scene

Working software shows the truth

Code is the source of truth

SUBMIT ORDER

A blue button with a futuristic design, labeled "SUBMIT ORDER", is shown with a white pixelated mouse cursor pointing at it, as if to click.

SUBMIT ORDER

A blue button with the text "SUBMIT ORDER" and a mouse cursor pointing to it, as if clicking.

Feature have relationships

Detailed definitions, not summaries

v1. LLM Pipeline

A diagram illustrating an LLM pipeline composed of 30 square nodes arranged in five rows of six, connected by horizontal arrows indicating sequential steps. Curved arrows depict feedback loops or parallel processing, with one from the end of the second row looping back to the first row, one from the end of the fourth row looping back to the third row, and one from the end of the fifth row looping back within itself.

v1. LLM Pipeline

Code analysis

A diagram illustrating a pipeline for code analysis. It shows a grid of four rows and five columns of connected square nodes with blue outlines. The first node in the top row is highlighted white. Arrows indicate data flow, entering the first column of nodes from the left, and curved arrows on the right side suggest a feedback loop or iterative process across the rows.

v1. LLM Pipeline

Code map

A diagram illustrating a "Code map" shows a grid of 24 squares, arranged in 4 rows and 6 columns, representing a process or dependencies. In the first row, the first five squares are filled light green, and the last is an empty outline. In the second row, the first square is light green, the second is solid white, and the remaining four are empty outlines. The third and fourth rows consist entirely of empty outlined squares. Arrows indicate a flow: one arrow points into the first square of the top row, and curved arrows show a wrap-around flow from the end of each row to the beginning of the next, across all four rows. Additionally, straight arrows point outwards from the right end of each row.

v1. LLM Pipeline

Themes

A diagram depicting a grid of squares arranged in 5 rows and 6 columns. The squares in the top three rows are mostly light green with a blue border, with some squares in the last two columns being dark with a blue border, and one square in the third row, fifth column, is white with a blue border. The bottom two rows consist entirely of dark squares with a blue border. Horizontal arrows point from left to right, indicating a flow across each row. Additionally, curved arrows suggest feedback loops from the end of each row back to the beginning of the previous row. This visual represents a multi-stage pipeline or a process of grouping and iteration.

v1. LLM Pipeline

Feature overview

A diagram illustrating a pipeline or process flow, composed of a grid of 5 rows and 6 columns of rounded squares. The first three rows and the first five squares of the fourth row are light green with light blue borders. The last square in the fourth row is white with a light blue border. The entire fifth row consists of dark, almost black, squares with light blue borders. Arrows show a left-to-right progression within rows and curved arrows indicate a flow from the end of one row to the beginning of the next, suggesting sequential processing.

v1. LLM Pipeline

Relationships

A diagram showing a grid of 24 square boxes, arranged in 4 rows and 6 columns. Most boxes are light green with a blue border. The bottom row contains one white box and three dark gray boxes, all with blue borders. Three horizontal arrows point into the first column of boxes from the left. Several curved arrows indicate connections and feedback loops between boxes within rows and across columns, illustrating relationships or flow within a pipeline.

v1. LLM Pipeline

Feature definition

A diagram illustrates a grid of 25 squares, arranged in 5 rows and 5 columns. Most squares are green, while the last square in the bottom right corner is white. Three horizontal arrows point from left to right, each entering the first square of the first, third, and fifth rows. Three curved double-headed arrows indicate feedback loops: one is below the second square of the first row, one below the second square of the third row, and one below the second square of the fifth row, suggesting iterative processing.

And it worked

... until it didn't work

We got it done

... but it couldn't scale

V2 == Agents

Software is a Sphere

A glowing blue wireframe sphere made of interconnected lines.

Mine the tunnels

A 3D wireframe sphere with a blue triangular marker on its surface. A jagged white line representing a path or tunnel extends from the triangle, moving inwards into the sphere.

Excavate the features

A 3D wireframe sphere composed of interconnected nodes and lines, with a complex network of lines highlighted in green on one side. A light blue triangular pointer extends from above the sphere, connected by a line to a green node on its surface.

... and we hit parity.

From 30 steps, to 3 missions

Don't guess. Ask

Don't hints

Build hooks

Software Definition Graph

Screenshot of the UserDoc platform displaying a "Software Definition Graph" with interconnected modules representing different business domains like Account Management, Catalog, Environment, Storage, Billing, and Purchase Order.

Software Definition Graph

A screenshot of a software platform interface showing a "Software Definition Graph" titled "Ordering". The graph displays a flow of interconnected functional blocks representing steps in an ordering process, such as "Search Medical Supplies", "View Supply Details", "Add Supply to Cart", "View Cart", "Update Cart Item Quantity", "Remove Supply from Cart", "Address Lookup", "Select Shipping Method", "Submit Order", "Order Confirmation", "View Order History", "View Order Details", "Cancel Order", "Reorder Supplies", and "Log Audit Entry".

View Cart

Screenshot of the UserDoc platform showing a Software Definition Graph interface with details for the 'View Cart' feature, including a user story and a list of associated code files.

V1 > 12 months

Software definitions

Code will never die.

But it's no longer enough.

Technologies & Tools

  • .NET
  • Claude Code
  • CLI
  • COBOL
  • Codex
  • LSP
  • React
  • Roslyn
  • SQL
  • TreeSitter
  • TypeScript
  • Visual Basic

Concepts & Methods

  • Agentic Rebuild
  • Code to Docs
  • Codenalysis
  • Feature Definition
  • Knowledge Graph
  • Spec Driven Development
  • Vector Embedding

Organisations & Products

  • UserDoc