GOne To Two

Chapter 5: Reading the Codebase You Inherited

7 min read

Three weeks into Apex, the config management system started eating itself. Users were losing settings. Containers were launching with stale values. I opened the codebase to fix it — my codebase, the one I‘d been building every day — and I couldn’t find the bug. Not because the code was complex. Because I didn't recognize it.

I sat there scrolling through files I‘d committed, functions I’d reviewed, a system I‘d watched come into existence over the course of days. And I had the disorienting realization that I didn’t understand how any of it worked. Not really. I knew what it was supposed to do. I knew what I‘d asked for. But the actual implementation — why this data structure, why this particular flow, why config values were being read from three different places — none of that was mine. I’d been present for every commit. 95.5% of those commits were AI co-authored. And I was a stranger to my own work.

Even if you wrote it — with AI — you inherited it.

That sentence still messes with me. I was there. Every prompt, every conversation, every accept. My name is all over the git log. But the actual decisions — why this library instead of that one, why this data model, why this particular pattern — those were the AI's calls. Made fast, made confidently, made without leaving any trace of reasoning. Just code that satisfied the prompt I gave it.

So there I was, doing archaeology on code that was three weeks old. And I realized: this is the first real job of one-to-two. Build a mental model of what you actually have.

Not what you think you have. Not what the AI told you it built. What‘s actually there — in the code, in the architecture, in the assumptions baked into every file nobody’s looked at since it was generated.

The feeling is closer to inheriting a company's software in an acquisition than iterating on your own code. You need to do due diligence on your own prototype.

I've started calling the pattern “the confident stranger.” The AI built Apex with the confidence of a senior engineer and the context of someone who showed up this morning. Any single file looked like it was written by someone who knew exactly what they were doing. But the assumptions were wrong — not because the AI was dumb, but because it was optimizing for the immediate prompt without any understanding of the broader system.

The config management system is the perfect case. Clean code. Well-named functions. Professional-looking, file by file. But the system as a whole had a fundamental flaw: two processes — the Apex platform and the OpenClaw runtime — were writing to the same config file with no ownership model. No single file revealed this. You had to read across files, understand the flow, build a mental model of who writes what and when. The AI never built that picture. It wrote each piece correctly in isolation and incorrectly as a system.

That‘s what reading the codebase actually means. Not reading individual files. Building the map the AI never had — how the pieces connect, where the assumptions contradict each other, where the confident stranger made decisions that don’t survive contact with reality.

Here‘s what the first week of reading looked like for me at Apex. A caveat: I had the luxury of a full week because Dan was focused on sales. Most builders won’t get five uninterrupted days. Day 1 is non-negotiable. Day 4 is the most valuable but the most likely to be skipped. Days 2 and 3 can be interleaved with feature work. But don't skip them.

Day 1: The critical path. I traced the main user flow end-to-end — message in, processing, response out — and documented every file it touched, every service it called, every database read and write. I drew a diagram on paper, ugly and incomplete, but it gave me a skeleton. For the first time I could see the shape of the thing I‘d built. Don’t try to understand the whole codebase — that's a trap. Find the one flow that matters most and trace it all the way through. If you can understand that single flow completely, you have the skeleton of your map.

Day 2: Infrastructure. How the system deployed. How it started. What happened on restart. What persisted and what didn't. This is where I discovered that user data vanished on every EC2 redeploy because each deploy used a new instance ID for the data directory. Invisible until a customer lost their data. I would never have found this by reading code file-by-file. It only became visible when I asked the system-level question: what happens when this restarts? This is the confident stranger at its most dangerous — the AI had set up deployment with the same professional confidence it brought to everything else, but it had no concept of what “deploy again” meant for data that lived on an instance.

Day 3: Boundaries. What goes in, what goes out. APIs, webhooks, external services, user inputs. What‘s validated and what isn’t. Where a bad input cascades into something worse. I mapped every dependency — what external services does the system call? What databases? What happens when any of them go down? At Apex, the system's health depended on a chain — SSH tunnels, container orchestration, config sync, telemetry reporting — and a failure anywhere in that chain cascaded unpredictably. I should have mapped it on day one. I also looked at secrets here — not metaphorical secrets, actual secrets. API keys, database credentials, auth tokens. Where they lived, how they were stored, whether any were hardcoded or committed to the repo. The confident stranger treats secrets the same way it treats everything else: with professional-looking code and zero threat awareness.

Day 4: Assumptions. The hardest day. I went through the code and tried to list every implicit assumption. “This assumes one user at a time.” “This assumes the database responds in under 100ms.” “This assumes no other process is writing to this config file.” Every one was fine at prototype scale. Every one was a time bomb at production scale. The confident stranger‘s assumptions are especially hard to spot because they’re buried in clean, well-structured code that looks like it was written by someone who considered these things. It wasn't.

Day 5: The model. I wrote it down. Not a comprehensive document — one page. What the system is, how it works, where it‘s fragile. The first version of my world model, externalized from my head into something I could share, challenge, update. It was wrong in places. It had gaps. It was still more understanding than I’d had after weeks of building.

Somewhere in this process — and this can happen on any of the five days — open a fresh AI session, point it at the codebase, and ask it to explain the architecture. Main components, how they communicate, key data flows. Then push it: “Why is config management structured this way? What happens when two processes write to the same config file?”

A warning: the AI will give you confident, articulate explanations. Some will be wrong. The original session that made those decisions is gone — the reasoning vanished when the conversation ended. The new session is reading the code cold, just like you, and it will invent rationales that sound authoritative for decisions that were actually arbitrary. Verify anything important by running it, tracing it, breaking it. The confident stranger explains its own work with the same unearned confidence it used to build it.

After five days I knew more about my own codebase than I did after weeks of building it. Not because I wasn‘t paying attention while building. Because the AI was doing the building, and building fast doesn’t mean building with understanding.

What if the codebase is too big? What about the prototype where the AI was prolific and you accepted fast and now there are hundreds of files across dozens of directories?

You don‘t read it all. The critical path is still your anchor. Expand outward in concentric circles: the systems that directly support the critical path, then the systems those depend on, then everything else. The parts you never reach are either dead code (more common than you’d think in AI-generated codebases) or peripheral enough to wait. The goal isn‘t to read every file. It’s to build an understanding accurate enough to make decisions.

And read the tests — or notice they don‘t exist. If there are tests, they’re documentation — they tell you what the builder (you, with AI) thought mattered enough to verify. If there are no tests, that‘s information too. It means nothing has been verified. Every behavior you’re observing is accidental until proven intentional. Let that land.

You don‘t have to finish all of this before touching anything. But do it before making architectural changes. The foundation audit in the next chapter tells you what to fix. This chapter is about making sure you understand what you’re fixing.