Agentic Software Engineering · AI-Native Engineering · Software Architecture
Staying attached to code you didn't write
Plan, teachback, ADR - three deliberate moves that stop an agentic workflow from quietly detaching you from your own architecture.
About six months into working with coding agents full time, I noticed something I didn’t like.
The features shipped. Tickets closed at a rate I couldn’t have matched by hand. But when a colleague asked me why a module was structured the way it was, I couldn’t answer without opening the file. On code I had approved. Sometimes on code I had approved that week.
That is a different failure from “the AI wrote bad code.” The code was fine. What was missing was me.
Why it happens
When you write code yourself, you learn it through recall. You hold the problem in your head, construct a solution, hit the constraints, back out, try again. The dead ends are the part that sticks. By the time it works you know the shape of the thing and every place you almost went wrong.
When an agent writes it, you learn it through recognition. A diff appears, you read it, it looks right, you approve. Recognition feels like understanding in the moment and encodes almost nothing.
None of this is my observation. Learning research splits it into fluency strength - can you retrieve it right now, and storage strength - will it still be there in six weeks. Reading a good diff produces fluency in abundance, and fluency is the one that feels like mastery. The name for deliberately trading comfort for retention is desirable difficulty, and it long predates any of this tooling.
You can recognise correct code without being able to reproduce the reasoning behind it, and reasoning is exactly what you need six weeks later when it breaks in production, or when someone asks you to defend the design in review.
So the problem isn’t speed and it isn’t code quality. It’s that the effort which used to produce architectural knowledge as a side effect has been removed, and nothing replaced it.
What I didn’t do
I didn’t go back to writing everything by hand. The productivity is real and I’m not giving it up out of nostalgia.
The fix is narrower: put deliberate cognitive effort back in, but only at the moments that are architecturally significant. Most code isn’t. Commodity CRUD, a form, another list endpoint - the agent handles those and I don’t think about them again. That’s the point of the tool.
For everything else, three moves. Two of them lean on skills I did not write - Matt Pocock’s wayfinder, grill-me and grill-with-docs, from his skills repo - and one I had to put together myself, because I could not find anything that did it.
/plan - decide before you build
The command forces the agent to stop before writing code. It has to produce:
- A short restatement of the problem and the constraints in the existing architecture.
- At least three approaches, each with what you gain and what you pay.
- A recommendation with an explicit “why this one”.
- Implementation broken into increments of roughly 150 lines or less.
Then it stops and waits.
The last line of the prompt is the whole trick: do not write code until I tell you which option I’m choosing.
That choice is where the memory forms. Reading one plan teaches you nothing, because there’s nothing to weigh. Reading three and rejecting two means you had to hold the trade-offs in your head and commit. Two months later I don’t remember the code, but I remember that I picked the option costing more memory to avoid a network round trip. That’s the thing I actually need to recall.
For work too big to hold in one session, wayfinder is the layer above this: it charts the whole effort as a map of decision tickets and resolves one per session, under a rule identical to the last line of my prompt - plan, don’t do. grill-me and grill-with-docs are the other half, interrogating a design before any code exists. That timing is worth being precise about, because the next move is the exact opposite.
/teachback - find the holes before you merge
This is the one I had to build. Grilling skills exist and they are good, but they all run before the code does. I wanted the mirror image: the feature is written, it is about to merge, and the only open question is how much of it stayed in my head. teach names the mechanism I was reaching for - retrieval practice, recall from memory rather than review - and warns about the failure mode below by name.
After a feature is implemented, this one turns the agent around. It doesn’t explain the code to me. It quizzes me on it, four to six questions, one at a time, waiting for my answer before moving on:
- the main data flow, from input to database and back
- why we made the key decisions, not just what they were
- where the module boundaries are and what’s coupled to what
- the most likely edge case, or where this will break first
After each answer it tells me whether I was right and corrects me tightly if I wasn’t.
One honest caveat, because this is the part people get wrong.
It only works if you answer out loud first and then check. If you let the agent recite the answers while you nod along, you are back to recognition and you’ve gained nothing but a pleasant feeling. The entire value is in the moment where you reach for something, find nothing, and now know exactly where your gap is.
It’s uncomfortable. That’s the signal.
/adr - leave a sentence for the next person
The last one generates an Architecture Decision Record stub from the session’s changes. Status, context, decision, alternatives considered, consequences.
Whether a decision earns one at all runs through the same gate as the rest of the loop: it changed the architecture, it is expensive to reverse, or a future reader will look at the code and wonder why on earth we did it this way. That is the diamond in the diagram further down, and it governs the whole loop, not just the ADR.
Rules:
- One screen, maximum. Nobody reads more.
- The alternatives section must always list at least two rejected options. If we never discussed any, the agent has to state the logical alternatives and why they’d lose. Undocumented rejections come back as “why didn’t you just…” a year later.
- The decision has to be phrased as a sentence I can say to a colleague who asks how this works.
That last rule does more for me than the file itself. If a decision can’t be compressed into one speakable sentence, I usually don’t understand it well enough yet.
All three come straight out of my own ADR template, which makes a Rejected section mandatory and asks for the decision in one sentence. They stay mandatory for a reason specific to agent work: when I didn’t write the code, the rejected options are the only part of the session that survives nowhere else. The diff records what we built. Nothing records what we ruled out and that is the question I actually get asked.
The loop
Per ticket: /plan, choose an option, let the agent implement in increments, /teachback before merging, /adr if the decision was architecturally significant.
And, just as important: skip all three for commodity code. If you run this on every commit it becomes ritual, you’ll resent it, and you’ll drop it within two weeks. Reserve it for the risky parts and the parts people ask you about.
What it actually buys
I built AttestBIM, a browser-based IFC compliance checker, across roughly ten agent sessions. Monorepo, a core package and a web app, fifteen compliance checks, ninety-odd tests. I did not type most of it.
I can still tell you how the check pipeline is wired, which decisions I’d revisit, and where it will strain first on larger models. That’s the outcome I’m optimising for. Not fewer AI-written lines - fewer lines I can’t defend.
Because the part that hasn’t changed at all is who gets called when it breaks. The agent isn’t on that rotation. You are, and the review, and the incident, and the conversation with the client are all still yours. Speed is worth very little if you can’t stand behind the result.
This workflow is my answer to that. It costs maybe twenty minutes per significant feature. It’s the cheapest thing I do.