AI agents now write code at over 80% success rates on standard tasks. Context engineering, better prompting, and iterative workflows have pushed them past the threshold of usefulness. The era where humans type out syntax line by line is ending.
But this does not mean software engineers are finished. It means we need to recover a distinction we lost decades ago: the difference between coding and programming.
Two Roles That Merged
In the structured design era (Yourdon, Constantine), software teams had distinct roles:
- Analyst: figures out what the customer needs
- Designer: decides how to meet those needs, balancing quality attributes
- Programmer: chooses algorithms, data structures, patterns. Specifies what code should do, then verifies it
- Coder: implements specifications in a particular language’s syntax
The programmer decides what. The coder handles how at the syntax level.
High-level languages and agile practices collapsed these roles into one. We stopped noticing the boundary. Now that agents can fill the coder seat, we need to see it again.
Most of Your Day Is Already Programming
Think about what you actually do. You debate framework choices with colleagues. You sketch class hierarchies on whiteboards. You evaluate trade-offs between libraries. You read documentation to understand constraints.
None of that requires writing a single line of code. It’s all programming.
In pair programming, only one person types. Everyone else is doing the programmer’s job: watching, correlating output with design intent, catching drift. In mob programming, the ratio is even more lopsided. The typing is the smallest part.
The Middle Loop
Steven Yegge and Gene Kim’s concept of the “Middle Loop” maps neatly onto this. The middle loop is where you construct the context that agents consume. You research requirements, read the codebase, evaluate options, then hand a specification to the agent.
Two things change in this model. First, the agent takes over the inner loop (coding). Second, a new researcher role becomes visible. Previously, when a programmer looked up documentation or scanned the codebase for patterns, that was invisible work folded into “programming.” Agents make it separable. You can delegate “go read this codebase and tell me what patterns exist” to an agent. But the decisions about what those findings mean remain yours.
The analyst, designer, and programmer roles stay human. The inner loop looks like pair programming where the agent holds the keyboard.
Why This Matters: Program Theory
Peter Naur’s 1985 essay “Programming as Theory Building” makes the strongest case for why the programmer role cannot be automated away.
Naur argues that the real output of programming is not code. It’s the theory that programmers build in their heads about how the program maps to its problem domain. This theory serves three purposes:
- Programmers can explain how the program maps to the real world
- Programmers can explain why specific design choices were made
- Programmers can judge whether a proposed modification fits the existing program
The third point is critical. When someone modifies code without understanding the theory behind it, the modification might work in isolation but degrades the program’s coherence. Do this enough times and you get a codebase that nobody can maintain. Naur calls this “program death.”
His warning is blunt: “The death of a program happens when the programming team possessing its theory is dissolved.” And theory cannot be reconstructed from artifacts alone. Documentation, comments, even Architecture Decision Records capture fragments. The full theory lives in people’s heads and in the social processes (conversations, pairing sessions, code reviews, arguments) that keep it alive.
Agents Cannot Hold Theory
This is the fundamental limitation. LLMs cannot assume the programmer role because they cannot build or maintain program theory:
- They lack context that exists outside the code: rejected pull requests, whiteboard conversations, unwritten rationale
- They cannot participate persistently in the social processes that construct and maintain theory
- Context windows prevent them from holding an entire large program’s history and evolution
- They have no continuity of identity or stake in outcomes
An agent treating each new requirement as novel, with no accumulated understanding of the program’s design philosophy, will accrete inconsistent approaches. The result is what anyone who has reviewed AI-generated code recognizes: multiple ideas lashed together, no unifying pattern, “decision archaeology” waiting to happen.
Could future agents develop persistent memory and social participation? Perhaps. But nothing about current architectures suggests this is imminent. Memory features help at the margins. They don’t structurally change the fact that theory is socially constructed and maintained through ongoing human relationships.
Senior Developers Get More From Agents
This explains the productivity gap people observe. Senior developers are more productive with coding agents because:
- They already possess the program’s theory
- With theory in hand, writing specifications for agents is straightforward
- Agents execute those specifications far faster than humans type
Junior developers lack theory. They make specification errors that produce incorrect code. Someone with theory must review their agent-generated output.
This is not new. Juniors have always needed supervision. What’s new is the temptation to skip it because “the agent wrote the code, not the junior.” The code still embodies the junior’s (possibly flawed) specification. Review remains essential.
The Speed Trap
Balint Orosz puts it well: writing code was always 20% of the time. Testing and refining was always 80%. Compressing the 20% by 10x creates pressure to compress the 80% too. That’s the mistake.
The temptation is to configure agents to handle the analyst, designer, and programmer roles as well. Go faster. Ship more. The logic is seductive and wrong.
Agents can iterate on code quality tirelessly. That’s genuinely valuable. But building software theory through discernment and judgment remains a human-in-the-loop activity. Removing it produces software that nobody can maintain.
As Gergely Orosz observes: the industry conversation is dominated by efficiency, iteration speed, PR output rates, and lines of code produced. Quality and customer obsession are barely mentioned. That gap will have consequences.
Does Your Stack Still Matter?
A naive take: if agents write the code, who cares what language or framework you use?
The problem: can you build program theory without understanding the stack? Sometimes, yes. But often the nuances of a language’s features, a framework’s constraints, or a library’s design philosophy are part of the theory. If your programmers don’t understand the stack they’re specifying for, the result is unmaintainable code. The theory has a hole in it.
Stack knowledge remains essential to theory building, especially as complexity grows.
The Programmer’s Return
The coding era, where software engineers were valued primarily for their ability to produce syntax, is ending. What remains is the older, harder, more valuable discipline: programming.
Programming means building theory about how software maps to its problem domain. It means making design decisions with judgment and taste. It means reviewing agent output not for syntax correctness but for coherence with the program’s existing theory. It means participating in the social processes that keep theory alive: pairing, code review, elaboration, argument.
Agents have taken one role off our plate. The role that remains is the one that actually matters.
Source: Ian Cooper, “Coding Is Dead, Long Live Programming” – ian-cooper.writeas.com/coding-is-dead-long-live-programming

