The Codebase Needs an Autograd Graph for Its Decisions
Hatched by Nan Wang
Aug 17, 2026
10 min read
0 views
90%
A strange thing happens when we ask an intelligent system to help with a complicated project: giving it more information can make it less useful.
The problem is not usually a lack of facts. It is a failure to preserve the relationships among facts. A model may know what a function does, what a tensor is, and what an architectural pattern means, yet still make a disastrous recommendation because it cannot tell which assumptions belong together, which decisions are reversible, or which pieces of state are secretly shared.
This is the same family of problem that appears in numerical computing. A tensor is not merely a convenient array. Its location, history, relationship to other arrays, and role in a computation all matter. An in place operation may save memory while destroying the history needed to compute a derivative. A CPU tensor and a NumPy array may appear to be separate objects while quietly modifying the same underlying memory.
These are not only programming details. They reveal a general law of intelligent work:
Reliability depends less on how much information a system contains than on whether it preserves the boundaries, history, and language that give information meaning.
That law explains why thin, well chosen documentation can outperform a giant knowledge base, why architectural decisions should be recorded selectively, and why the safest collaboration with an AI system is less like asking for an answer and more like supplying a map of dependencies.
The hidden cost of information without context
Imagine handing a new engineer ten thousand pages of internal documents on their first day. They now possess more information than an experienced colleague could remember. Yet they may still ask the wrong questions, confuse two meanings of the word “account,” or propose a redesign that violates a constraint nobody bothered to write down.
The issue is not ignorance in the ordinary sense. It is context collision. In one part of a business, “customer” might mean the person who pays. In another, it might mean the end user. In a third, it might mean a legal entity with several accounts. A shared vocabulary is not cosmetic. It determines which objects can be safely connected.
This is why bounded contexts are so powerful. A context is a region in which words have stable meanings and rules can be applied without constantly translating between neighboring worlds. The boundary does not claim that the rest of the organization is irrelevant. It says that reasoning becomes more accurate when the active problem has a defined linguistic and operational home.
The same principle applies to asking an AI system to inspect a codebase. A general request such as “grill me on this project” invites broad questions about productivity, style, and software development. A request grounded in the repository, its documentation, its domain vocabulary, and its decisions can ask a much sharper question: “Which assumption in this payment flow would make this refactor unsafe?”
The second request is not better because it contains more words. It is better because it establishes a bounded field of relevance.
A useful way to think about this is to distinguish three layers of knowledge:
- Facts: what exists, such as functions, tables, APIs, and tensor shapes.
- Language: what those things are called and how the team distinguishes them.
- History: why the system has its current shape and what consequences were accepted.
Most documentation captures facts. The highest value documentation preserves language and history. Without those layers, a technically plausible suggestion can be semantically wrong.
Documentation is a memory system, not a filing cabinet
The phrase “documentation” often suggests a large reference manual. In practice, the most valuable documentation is frequently the thinnest layer that prevents a future mistake.
Consider three notes:
- “The service uses a queue.”
- “The service uses a queue because payment providers occasionally retry requests, and synchronous retries previously created duplicate charges.”
- “Do not make payment confirmation synchronous unless idempotency is enforced at the provider boundary. The queue was introduced after duplicate charges appeared during provider timeouts.”
The first note records a fact. The second records rationale. The third records a constraint that can actively guide future decisions. It tells a reader what not to erase, the failure mode to fear, and the condition under which the architecture might safely change.
Architectural Decision Records are useful precisely because they preserve this kind of history. They deserve a place when a decision is difficult to reverse, surprising without explanation, or shaped by a meaningful tradeoff. They function like externalized computational history. The current system is the output, but the record stores enough of the path that produced it to help someone evaluate a proposed transformation.
This has a striking parallel with automatic differentiation. A machine learning system does not only need the current value of an operation. To calculate a derivative later, it may need the history of how that value was produced. An in place modification can be efficient because it reuses memory, but it can also erase information required by the backward pass.
In both cases, optimization by deletion creates a delayed failure:
- In software architecture, deleting the rationale makes a sensible looking refactor dangerous.
- In numerical computation, deleting the operation history makes a sensible looking mutation incompatible with gradient calculation.
The immediate result looks fine. The problem appears only when a later process needs the lost context.
A system becomes fragile when it optimizes the present representation by destroying the history required for future reasoning.
This is why concise documentation can be more valuable than exhaustive documentation. It does not attempt to preserve every event. It preserves the events that future transformations will need in order to remain safe.
Mutation, shared memory, and the illusion of independence
There is another connection between computational systems and organizational knowledge: the danger of hidden sharing.
Two data structures may look independent while pointing to the same underlying memory. Change one, and the other changes too. The visible interface suggests separation, but the implementation contains an unannounced coupling.
Organizations have the same problem. A team may believe it owns a local concept called “status,” while another team uses the same database field for a different workflow. A developer may copy a configuration object, believing it is now private, while both components still share a mutable reference. A language model may receive documentation from several domains and merge identical terms into a single mental object, even though the terms carry different rules.
The common failure is false independence.
Bounded contexts reduce this risk by making semantic ownership explicit. A payment status and a shipment status may both be represented as strings, but they should not automatically be treated as interchangeable. Their shared surface syntax does not imply shared meaning. In the same way, two arrays having the same shape does not mean they participate in the same computation.
This suggests a practical design rule:
Whenever two things appear separate, ask what they share underneath: memory, vocabulary, authority, or history.
If the answer is “more than we intended,” the system needs a boundary, a copy, a translation, or an explicit contract.
This does not mean mutation or sharing is always wrong. In place operations can save memory. Shared storage can avoid expensive copying. A common vocabulary can reduce translation costs. The issue is not whether sharing exists, but whether its consequences are visible to the people and tools that must reason about the system.
A safe shared resource has a clear ownership model. A safe mutation has a clear lifecycle. A safe cross domain term has a translation rule. A safe architectural shortcut has a written rationale. Efficiency becomes dangerous when it hides dependency.
The right unit of AI assistance is the decision, not the conversation
This framework changes how we should use AI in technical work. The natural interface is conversational, so people tend to ask for broad interaction: critique this, quiz me, review the code, find problems. But a broad conversation often produces broad intelligence. It may be articulate, energetic, and insufficiently constrained.
A better unit of assistance is the decision under consideration.
Suppose a team wants to remove a queue from a notification system. A generic code review might point out style issues, test gaps, and possible simplifications. A decision centered review would reconstruct the relevant context:
- What failure originally required the queue?
- Which domain owns delivery status?
- Is retry responsibility moving somewhere else?
- Which consumers depend on eventual consistency?
- Is the change reversible once messages are no longer persisted?
- What evidence would show that the tradeoff is acceptable?
The AI does not need every document in the company to help with this question. It needs the code involved, the vocabulary of the relevant context, and the few decisions that explain the current architecture. This is the documentation equivalent of loading only the tensors required for a computation rather than treating all memory as equally relevant.
The workflow can be made explicit:
- Define the boundary. Name the subsystem, business capability, or decision being examined.
- Load the local language. List terms that have specialized meanings in that area.
- Surface preserved history. Attach the relevant decision records, incidents, constraints, and rejected alternatives.
- Identify shared state. Look for databases, mutable objects, queues, caches, and terms that cross boundaries.
- Ask for adversarial reasoning. Request questions about hidden coupling, irreversible consequences, and assumptions rather than generic criticism.
- Record the result. If the investigation changes a durable architectural assumption, update the decision record.
This creates a feedback loop. Documentation improves the quality of AI assistance. AI assisted questioning reveals missing documentation. The resulting records then improve the next round of reasoning.
The important shift is from treating documentation as an archive to treating it as an interface between human intention and machine action. A good interface does not expose everything. It exposes the right concepts, with stable names, at the moment they matter.
A practical test for durable knowledge
Before writing a document, teams often ask, “Will anyone read this?” A more useful question is, “What future operation would become unsafe if this knowledge disappeared?”
That question filters noise. A note about a minor implementation detail may not survive. A note explaining why a seemingly redundant validation exists probably should. The difference is not length. It is the relationship between the note and future change.
You can evaluate a piece of documentation with four tests:
The surprise test
Would a competent engineer make the wrong choice if they saw only the current code? If yes, record the missing rationale.
The reversal test
Would changing this decision be expensive, politically difficult, or operationally risky? If yes, preserve the alternatives and tradeoffs.
The boundary test
Does this concept mean something different in a neighboring subsystem? If yes, state its local meaning and identify the translation point.
The sharing test
Could two apparently separate components change each other through shared state or shared authority? If yes, document ownership and mutation rules.
Together, these tests produce a compact map of the system’s semantic hazards. They also give an AI system something far more useful than a pile of prose: a model of where naive reasoning is likely to fail.
Key Takeaways
- Document lost context, not every fact. Prioritize surprising constraints, irreversible choices, and tradeoffs that are invisible in the current code.
- Treat bounded contexts as cognitive boundaries. Define what key terms mean locally before asking people or AI systems to reason across domains.
- Make hidden sharing visible. Audit shared memory, mutable state, database ownership, vocabulary, and authority whenever components appear independent.
- Ask AI about decisions, not just code. Give it the relevant repository area, domain language, and architectural history, then request adversarial questions about consequences.
- Preserve history before optimizing it away. A concise decision record can play the same role as retained computation history: it enables safe future transformations.
The deepest lesson is that context is not decorative information surrounding a system. It is part of the system’s operating state. Remove it, and the code may continue to run while the ability to change it safely disappears.
A tensor without its computational history can be numerically valid but impossible to differentiate correctly. A codebase without its decision history can be executable but impossible to reason about reliably. In both cases, the most dangerous errors come from mistaking a current snapshot for the whole object.
The next time you improve a system, do not ask only what can be simplified, compressed, or made faster. Ask what invisible relationships your optimization will erase. The best engineered systems are not those with no memory, no boundaries, or no sharing. They are those that make memory, boundaries, and sharing legible enough that both humans and machines can act without guessing.
Sources
Hatch New Ideas with Glasp AI 🐣
Glasp AI allows you to hatch new ideas based on your curated content. Let's curate and create with Glasp AI :)
Start Hatching 🐣