In the previous article, I wrote about something I started to notice while developing several applications with AI coding agents. They let me move much faster, and I find them very effective. I can take an idea, discuss the architecture, start implementing it, test different approaches, and continue developing the project without spending the same amount of time writing every piece by hand.
After doing this across several repositories in github.com/oonid, another feeling started to appear. It was not about whether the applications worked. Most of the time I knew what I had asked the agent to do, I had followed the implementation, and I could read the code afterward.
The uncomfortable part came when I tried to hold the whole project in my head.
I could recognize a module and remember the purpose of a feature, but sometimes the connections between them were less clear than I expected. Some decisions had happened several coding sessions earlier. Other parts had changed as the agent worked through a problem and found a better implementation. I had seen those changes when they happened, but seeing something is different from keeping it as part of my understanding.
This was a strange experience because these were my own projects. I was not joining an unfamiliar codebase written by another team. I had started the projects, made the main decisions, worked with the coding agent, and reviewed what it produced. Still, the software could move far enough that I needed to study my own project again.
The application could work while my understanding of it was already becoming incomplete.
That distinction has become important to how I think about AI-assisted software development.
A working application gives us many useful signals. It compiles. Tests pass. An API responds correctly. A feature behaves as expected. We may also have linting, static analysis, benchmarks, code review, and other forms of verification. All of these tell us something about the software.
They do not tell us how well the person responsible for the software understands it.
This problem existed long before coding agents. I have worked with enough software to know that nobody keeps every detail of a large system in their head. We depend on abstraction for that reason. We think about a database as a database instead of remembering every page written to disk. We think about a service through its responsibilities and interfaces instead of remembering every function.
AI changes the rate at which new abstractions, dependencies, files, and decisions can enter a project.
Before using coding agents heavily, implementing a new subsystem also forced me to spend time inside that subsystem. I wrote the code, made many small choices, encountered errors, fixed them, and slowly became familiar with the result. Some of that work was mechanical, but the time spent doing it also had an educational side effect: I was learning the system while creating it.
With an AI coding agent, part of that process is compressed. I can remain involved in the decisions while delegating much more of the implementation. This is one of the reasons the tool is productive. But it also means that an old relationship between production time and learning time starts to change.
I began to see this as an education problem as much as a software engineering problem.
Producing an answer and learning something
Education has dealt with a similar distinction for a long time.
A student can produce the correct answer without having a strong understanding of the subject. A learner may remember a procedure for solving a mathematics problem and become very good at applying it to exercises that have the same shape. The result is correct, so from the outside the learning process seems successful.
Change the problem slightly and the limitation becomes visible.
The student may know which formula to use but not why it works. Another student may be able to follow a worked example but struggle to solve a similar problem later without looking at the example again. In both cases, something has been learned, but the knowledge is not yet flexible enough to use in a different situation.
This is close to what I experience when reading AI-generated code and explanations.
While the code is in front of me, I can follow it. When an agent explains why a module is structured in a certain way, the explanation can be clear and useful. At that moment I may feel that I understand the design.
Later I discover whether that understanding stayed with me.
Can I explain the same part of the system when the original explanation is no longer open? Can I predict which other component will be affected when I change it? Can I connect a design decision from two weeks ago with a problem I am seeing today?
There is a familiar distinction in learning between recognition and recall. Recognizing something when we see it is easier than rebuilding it from memory. The same problem appears when we read source code. A function can look familiar without giving us a useful mental model of the larger system around it.
AI can make recognition very easy. It can continuously provide the missing explanation, locate the relevant code, summarize a module, and answer another question. These are useful capabilities, and I use them. But there is a risk that the tool becomes part of the memory loop. I understand the system while the assistant is present because the assistant can keep reconstructing the missing context for me.
For some tasks that may be perfectly fine. We already use documentation, search engines, IDEs, and reference books as external memory.
Software engineering, however, also requires judgment. When we design an architecture, review a risky change, investigate a production problem, or decide which trade-off is acceptable, we need enough of the system in our own mental model to reason across several pieces at once.
The amount we need to remember is not everything. The important part is knowing enough of the structure and its relationships to reason about the consequences of a decision.
Code review is also a learning activity
This way of thinking changed how I look at code review.
I used to think about review mainly in terms of software quality. I would look for incorrect behavior, design problems, missing tests, security issues, confusing names, or code that would be difficult to maintain. I still care about all of those things.
With AI-assisted development, I now see another purpose in the review process. Review is one of the places where I can update my own understanding of what the system has become.
This matters because the size of a diff does not tell us how much our mental model needs to change. A large mechanical refactoring may preserve the architecture almost completely. A very small modification may introduce a new assumption that changes how two parts of the system interact.
Git is good at showing textual change. It does not automatically tell me how much of my understanding needs to change with it.
This is also where the education perspective becomes useful. When a learner already understands a topic, we normally do not teach the entire subject again every time one new concept is introduced. We connect the new information to what the learner already knows.
Software could be approached in a similar way.
Suppose I understood a project yesterday. Today an agent changes twelve files. I probably do not need a new explanation of the entire repository. I need to know which concepts were added, which relationships changed, whether an old assumption no longer holds, and which parts of my previous understanding can remain as they were.
That is a much smaller learning problem, but it requires more than a diff.
It requires some representation of what the system meant before the change and what it means afterward.
More information does not automatically help
My first instinct was that better documentation might solve much of this. Documentation certainly helps, and I still consider it necessary, but I started to see a limitation there too.
An AI coding agent can generate documentation very quickly. It can create module descriptions, architecture summaries, diagrams, comments, and explanations of almost any part of a repository. The amount of available information is no longer the main limitation.
I can easily imagine reaching a point where the project contains more documentation than I have time to read.
Education has a useful lesson here as well. Giving a learner more material does not guarantee more learning. A textbook can contain everything required to understand a subject while a student remains confused. The order of ideas matters. Prior knowledge matters. Examples matter. Practice matters. Sometimes the learner needs a diagram, sometimes a concrete case, and sometimes they need to try explaining the idea themselves.
There is also cognitive load. Our working memory has limits, so presenting every available detail at once can make understanding harder. Good teaching manages that load by deciding what needs attention now and what can remain in the background.
Software tools rarely think this way. A repository browser gives us files. Git gives us commits and diffs. Static analysis gives us findings. A graph may give us hundreds or thousands of relationships. An AI assistant can summarize all of them.
Every one of those outputs may be correct, yet the human still has to decide what matters.
That is where my thinking about makna started to change.
The early idea was strongly connected to observing development activity. If an AI agent changes software, it seemed useful to capture what the agent did and connect that activity to the state of the repository. The history between a request and the resulting code contains information that Git alone does not preserve.
But collecting more evidence does not solve the comprehension problem by itself.
A complete recording of an agent session could include prompts, tool calls, file modifications, compiler output, test results, retries, and many intermediate actions. It could be an accurate history and still be exhausting for a human to read.
So I started separating three different problems in my head.
First, we need to know what happened. That requires evidence from the coding agent, repository, Git, compiler, tests, and other sources.
Then we need to understand what those observations mean for the software. A changed file is an observation, but the engineering meaning may be that a component gained a new responsibility, an interface changed, or a dependency moved across a boundary.
Finally, the human needs a useful way to learn from that knowledge.
These ideas eventually became the Observation, Knowledge, and Comprehension planes in makna. I did not start with those names. They appeared after trying to separate problems that initially looked like one problem.
The third plane is the one I find especially important now.
A system can collect correct evidence and build an accurate model of software while still failing to help the engineer understand it. Comprehension has its own requirements because people learn in a different way from databases storing facts.
Keeping my mental model up to date
Thinking about learning also led me to a more specific idea.
I do not need makna to teach me my entire project every morning. Most of what I understood yesterday is probably still useful today.
What I need is a way to notice when that understanding should change.
If an agent adds a helper function, my architectural understanding may stay exactly the same. If the agent moves persistence responsibility from one component to another, I need to update part of my mental model even if the code change itself is small.
If a new service appears, I need to learn what role it has and how it connects to the rest of the system. If an old abstraction disappears, I should stop carrying that abstraction in my head. And if the implementation changes while the architectural meaning remains stable, I may only need a brief note.
This eventually led us to the concept of ComprehensionDelta in makna: the difference between what a person needed to understand about the previous state and what they need to understand about the new state.
I like this idea because it connects the history of software with the process of learning it.
The repository has a history.
The engineering model has a history.
Our understanding has a history too.
AI coding agents make the first history move faster. makna is an attempt to help the third one keep up.
I still want AI to help me write more software. My experience with it has been productive enough that going back to the old way of doing everything manually would make little sense to me. The problem I want to work on is what happens after that productivity gain.
When I return to one of my own projects, I want to remain close enough to it that I can explain the important parts, follow how they changed, and make the next engineering decision with a mental model I can trust.
The application working is one result.
Understanding what I have built is another.

