There is a particular feeling you get a few hours into a productive AI-assisted coding session. The cursor is moving. Files are being created and edited. The terminal scrolls with output. Something that looks like a working feature exists where, this morning, there was nothing. You close the laptop feeling like you got a lot done.

Sometimes that feeling is accurate. Sometimes it is the feeling itself that the tool is optimised for, and the work is a much thinner thing than the experience suggested. Telling the two apart is one of the most underrated skills in working with AI today.

What progress used to feel like

For most of the last twenty years, the texture of programming was friction. You typed, the compiler complained, you fixed it. You read documentation, you tried a thing, it did not work, you tried a different thing. The slow parts were not bugs in the workflow. They were the workflow itself doing its job — surfacing the gaps in your understanding before they became gaps in the product.

Working with an AI assistant feels almost the opposite. There is much less friction. Code appears, and it usually runs. The compiler complains less. The first try is closer to working than it used to be. This is not a problem. It is mostly wonderful. But it quietly removes the signal that used to tell us how well we actually understood what we were doing.

Friction was not just a tax on progress. It was a measurement of it. Without that measurement, you can move fast in a direction that turns out, much later, not to have been forward.

The three flavours of fake progress

Once I started looking for it, I noticed three recurring shapes of "I did a lot today" that, on closer inspection, were not as substantial as they felt:

1. Volume without integration

The model generates a lot of code. The code looks plausible. Each file, taken alone, is fine. But none of it has been wired into the existing system, the tests do not actually run against real fixtures, and the new module references a service that does not exist yet. A week from now you will discover that the "almost done" feature needs another two days of glue work that nobody scoped.

Sign you are here: the diff is large and the test suite is unchanged.

2. Refactors that change shape but not behaviour

The model is good at restructuring code. Sometimes too good. A "cleanup" session can produce hundreds of lines of changes that move things around, rename things, restructure file layouts — all of it cosmetically improved, none of it changing what the software actually does or fixing what was actually broken. You feel productive because you can see what changed. The user cannot.

Sign you are here: the changelog reads "refactored X" with no corresponding "fixed Y" or "added Z."

3. Plausible code that nobody understands

The most insidious one. The model produces something that works, or at least appears to work in the few cases you tested. You ship it. Two weeks later there is a bug, you open the file, and you cannot quickly answer the basic question of why does it work this way? Not because the code is bad — it might be perfectly reasonable — but because nobody on the team ever held the design in their head. The model held it, briefly, and then forgot.

Sign you are here: a change request that should take 20 minutes takes 2 hours, because half the time goes to re-deriving the intent that was never written down.

The honest test

The thing I have started doing, at the end of an AI-assisted session, is asking a deliberately deflating question: could I, right now, explain to a teammate what this change does and why, without re-reading the diff? Not the file structure. The actual decisions: which trade-offs got made, what was considered and rejected, what the failure modes are.

If I can, the progress was real. If I cannot, I built something I will eventually have to learn from scratch, and the time I felt I saved this afternoon is debt I have not yet noticed taking on.

The fastest way to ship working software has not changed. It is still: understand the problem, hold the design in your head, write the code, and verify it does what you expected. AI changes which steps are fast. It does not let you skip any of them.

What to actually do about it

Three small habits seem to help, in roughly increasing order of discipline:

Narrate the design. Before letting the model write code, write two or three sentences in your own voice about what is being built and why. Not for the model — for yourself. Keep these alongside the commit. They become the documentation that explains the intent the code itself does not capture.

Count the failure modes. For any non-trivial change, force yourself to list at least three ways the new code could fail in production. If the list is hard to write, you do not yet understand the code well enough to ship it — regardless of whether it runs.

Take the slow read at the end. Once the work is "done," close the chat window, open the diff in a plain text editor, and read every line as if reviewing a colleague's pull request. You will notice things the model did not flag, because the model never noticed they were worth flagging.

The point is not to slow down

None of this is an argument against using AI assistants. They have made me materially more productive on real work, and I have no desire to go back. The argument is more specific: the productivity is real, but the feeling of productivity is unreliable as a measure of it. They are not the same signal. Mistaking one for the other is how you ship a quarter of half-built features instead of one finished one.

The engineers who will get the most out of these tools are not the ones who type the fastest with them. They are the ones who stay honest about what just happened — who can tell the difference between code that exists and a problem that is solved. The difference is everything.

#AI #SoftwareEngineering #AICodingAgents #DeveloperProductivity #EngineeringCulture #FutureOfWork

Learn more about NaviQure AI

We are building AI-powered chronic healthcare in India.

Visit NaviQure.ai arrow_forward