Skip to content

Your Developer Left and the Documentation Is Gone: How to Recover Knowledge from Code

When the developer has left, or the application was built with AI and never documented, the code is the most complete record left. A practical, layer-by-layer method for reading an undocumented application back into something a team can maintain, and an honest account of what code cannot tell you.

Isometric illustration of a magnifying glass over stacked source code, with a database table, workflow diagram, user roles and scheduled jobs being recovered from the code into a new documentation folder, while torn documents drift away

The System Still Runs. Nobody Can Explain It.

It is a common situation, and it rarely announces itself. An application has been running for years. Students submit forms through it, staff approve requests in it, reports come out of it every semester. Then the developer who built it moves on, the shared drive with the specifications is cleaned up, or the laptop with the only copy of the notes is replaced. Nobody notices until something has to change.

There is now a newer version of the same story. A business owner with a clear idea and no software background builds the first version of an application with an AI coding assistant. It works well enough to use. But no analyst wrote down the requirements, no designer recorded the decisions, and the "developer" was a chat session that kept no notes. When the owner wants to grow the application, the code is all there is.

At that point the organisation discovers it owns a system it cannot describe. Nobody can say with confidence which features exist, who is allowed to do what, where the data lives, or what happens if a particular table is touched.

The good news is that the most complete record of the system is still there: the code. The code contains every route a user can visit, every table the application writes to, every rule that blocks or allows an action. It is not written for humans to read as documentation, but it can be read back into documentation with a deliberate method.

A Project That Arrived as Code Only

This article comes from practice. qadrtech was asked by a client to continue developing an application they had built themselves using AI tools. The client knew their business well, but software development was not their field, and the AI had produced exactly what it was asked for: working source code, and nothing else.

There was no analysis document, no design document, no software requirements specification, and no record of why the application was shaped the way it was. Before we could plan a single new feature, we had to work out what the existing system did. For the client's privacy we do not name the project or describe its domain here.

That work followed the method below. It also confirmed a limit we will come back to: code tells you very precisely what a system does, and almost nothing about why.

Why AI-Built Projects Need This Step

AI coding assistants make it possible for non-developers to ship a working first version, which is genuinely useful. What they do not do on their own is the surrounding engineering work: asking who the users are, writing down the rules the system must follow, or keeping a record of decisions. A person without a software background usually does not know to ask for those things, so they are never produced.

The result is an application whose behaviour lives only in the code, often written across many separate prompts. Recovering that knowledge is not a criticism of the client or of the tool. It is simply the analysis and design work that was skipped, done afterwards instead of first.

Before You Read a Single File: Secure Access

Knowledge recovery fails quickly if the system disappears halfway through. Before any analysis, make sure the organisation, not an individual, controls everything the application depends on.

  • Source code. Locate the repository. If there is none, copy the code from the production server. Put it under version control immediately, even if the history starts today.
  • Server and hosting. Confirm who holds the hosting account, the server login, and the control panel. Change shared passwords that a former developer still knows.
  • Database. Take a full backup and store it somewhere separate from the server.
  • Domain and DNS. Check who the domain is registered to and when it expires. An expired domain takes a working system offline as effectively as a crash.
  • Third-party accounts. Email delivery, payment gateways, SMS providers, cloud storage, and API keys found in configuration files all belong on this list.

Write down where each of these lives. That list is the first page of the new documentation.

Reading the Code in Layers

Opening files at random produces confusion. It works better to read the system in layers, from the outside in, and to write something down at every layer. The examples below use Laravel because it is the framework we work with most, but every mature web framework has equivalents.

Layer 1: The Stack and Its Dependencies

Start with the files that describe the project rather than the files that implement it.

  • composer.json and package.json tell you the framework, its version, and every library the system relies on.
  • .env.example, or the real .env on the server, lists the external services the application expects: database, mail, queues, storage, and third-party keys.
  • The framework version tells you how old the system is in practice and which upgrade path lies ahead.

Write down: language and framework versions, the database engine, and every external service.

Layer 2: The Route Map Is the Feature List

Users experience a web application as a set of pages and actions. Those are declared in one place. In Laravel, the routes can be listed directly:

php artisan route:list --except-vendor

The output, method, URL, controller, and middleware, is the closest thing to a complete feature inventory you will get. Group the routes by prefix or controller and give each group a plain-language name: "thesis submission", "supervisor approval", "reports".

Write down: a feature list grouped by area, with the URL that leads to each feature.

Layer 3: The Database Is the Domain Model

Tables reveal what the organisation actually tracks. If the project uses migrations, read them in order: they show not only the current schema but how it grew. If migrations are missing or out of date, read the schema from a backup of the live database instead, because production is the truth.

Pay attention to:

  • Foreign keys and naming patterns, such as student_id or supervisor_id, which show how entities relate.
  • Status columns, often named status, state, or is_approved, which point to workflows.
  • Soft deletes and timestamps, which tell you what history the system keeps.
  • Tables nobody seems to use. Do not delete them yet. Mark them as questions.

Write down: an entity relationship diagram. It does not need to be beautiful. A simple diagram of the main tables and their relationships is enough to stop people guessing.

Layer 4: Roles and Permissions

Most business applications serve several kinds of user who see different things. Find out where that rule lives. Common places include:

  • route middleware such as auth, role:admin, or custom middleware classes;
  • policies and gates (app/Policies, Gate::define);
  • a roles or permissions table, or a role column on users;
  • conditions inside views that hide buttons from some users.

The last one matters. A button hidden in a template is not a security control, and recovering the role model is often when such gaps are found.

Write down: a role matrix with roles as columns, features as rows, and a mark where access is allowed.

Layer 5: Workflows and Status Transitions

The most valuable knowledge in an administrative system is usually the workflow: a request is created, reviewed, approved or returned, and finally closed. That logic is rarely in one place.

Search the code for the places where a status changes:

grep -rn "status" app/ --include=*.php | grep -E "=|update"

Follow each result to the controller or service that sets it, and note what condition allows the change and who is allowed to trigger it. From those notes, draw the states as boxes and the transitions as arrows. That diagram will answer more support questions than any other document.

Write down: one state diagram per workflow, with the role that performs each transition.

Layer 6: What Runs When Nobody Is Watching

Some behaviour is not triggered by users at all.

  • Scheduled tasks in app/Console/Kernel.php or routes/console.php, and the server's crontab.
  • Queued jobs and listeners that send emails or process files in the background.
  • Integrations with other systems, such as an academic information system, a payment provider, or a government reporting portal.
  • Deployment details: how the code reaches the server, which commands run after an update, and where uploaded files are stored.

These are the parts most likely to break silently after a change, because nobody sees them happen.

Write down: a short operations note covering scheduled work, background jobs, integrations, and how to deploy.

Layer 7: Git History as a Clue, Not the Truth

If a repository with history exists, git log can show when areas of the system changed and which features arrived together. Commit messages such as "fix" or "update" will not explain much, but the dates and the files changed together are still useful clues.

Treat history as evidence to check, not as documentation. A commit that claims to fix something does not prove that it did.

Confirm with the People Who Use It

Code shows what the system does. It does not show whether that behaviour is intended, tolerated, or a long-standing bug that users have learned to work around.

Once the layers are written down, walk through them with the people closest to the system: the administrator who handles complaints, a few regular users, and whoever owns the process on the business side. Ask concrete questions:

  • "The code allows a coordinator to approve this directly. Do you actually do that?"
  • "This table has not received new rows in a long time. Is that feature still needed?"
  • "This report is generated every night. Does anyone read it?"

Their answers turn a description of the code into a description of the service.

What You Should Have at the End

The aim is not a thick manual. A small set of documents that people will actually open is worth more than a comprehensive one that nobody maintains.

  1. A README explaining what the system is, the stack, how to run it locally, and how to deploy.
  2. An access register listing where the code, server, database, domain, and third-party accounts live, and who holds them.
  3. A feature list grouped by area, built from the route map.
  4. An entity relationship diagram of the main tables.
  5. A role matrix showing who can do what.
  6. Workflow diagrams for each status-driven process.
  7. An operations note covering scheduled jobs, background work, and integrations.
  8. An open questions list for everything the code could not answer.

Keep these in the repository, next to the code, so they change when the code changes.

What Code Cannot Give Back

It is worth being honest about the limits. Some knowledge does not survive in code, however carefully it is read:

  • Why a decision was made. The code shows that approvals need two signatures. It does not say whether that was a regulation, a request from one manager, or a workaround for an old problem.
  • What was agreed with the client or users. Scope, promises, and exceptions negotiated in meetings leave no trace in the source.
  • What was tried and abandoned. Alternatives that were rejected are usually invisible.
  • Real-world outcomes. Code does not record whether the system saved time or what users thought of it.

With an AI-built application there is an extra twist: some of the "decisions" in the code were never decided by anyone. They are simply what the assistant produced for a particular prompt. Part of the recovery is asking the owner which behaviour they actually want and which they have only been living with.

The right standard for any recovery effort is the same: record what is known, mark what is assumed, and leave the rest as an open question for the people who own the system, instead of filling it with a guess.

Making Sure It Does Not Happen Again

Recovery is expensive. Prevention costs very little by comparison, as long as it starts early and stays small.

  • Keep documentation in the repository, not in personal drives or chat threads.
  • Record decisions as they are made, in a few sentences each: the context, the decision, and the reason.
  • Make handover a deliverable. When a project ends or a developer leaves, the organisation should receive the code, the access register, and the documents above, not just a working application.
  • Review the documents when the system changes. A README that describes last year's deployment is a trap.

Closing

An undocumented system is not a lost system. As long as the code and the data are in your hands, most of what you need can be recovered, layer by layer, and confirmed with the people who use it every day. What cannot be recovered should be named plainly rather than guessed.

If your organisation depends on an application that nobody can fully explain any more, whether its developer moved on or it was built with AI and now needs to grow, we are happy to talk it through. Get in touch and tell us what the system does today; we will start from there.