Hey everyone,
Picture Monday morning in the merge queue. Three tickets landed overnight for the same auth service. One adds a special case for a partner that still dumps SSO claims into Excel before upload. Another wraps a null check around a token field that the caller already validated. A third introduces a second helper that almost matches the first, except the naming is different enough that search will not treat them as cousins. Every pull request is green. Every change is small. None of them makes the module quieter.
That scene is showing up across software teams in 2026, and the uncomfortable part is that the agents helping us ship are not failing at their job. They are succeeding at the job we accidentally rewarded: produce a minimal, mergeable diff that satisfies the ticket.
Hi, I’m Robert Massey, software engineer and computer science professor with twenty-plus years in the trenches. AI is a tool and an assistant. Programming is still a skill. Software engineering is still engineering solutions with software. Agents accelerate bounded work. Engineers still own cleanup.
Why additive diffs feel so responsible
Coding assistants and agents are excellent at forward motion. You hand them a ticket, they find a seam, they insert a branch, and they leave the rest of the file alone. For incident patches and bounded feature work, that habit is a virtue. Small blast radius is usually what on-call wants at 2 a.m.
The same habit becomes a quiet tax when the work is structural. Refactoring is not a minimal edit with better manners. Refactoring is deliberate subtraction: delete the dead path, collapse the duplicate helpers, route auth through one policy layer instead of three. A model trained to prefer the safest local change will often empty a value, wrap a no-op, or add a fallback rather than remove the concept. The build stays green. The ghost stays in the architecture.
Teams used to get a free warning signal when a module became unmanageable. A senior engineer would open the billing path before a change and feel lost. That sensation was unpleasant, and it was useful. It pushed people to stop and reshape the code before the next exception went in. Agents do not feel lost the same way. They can still traverse tangled callers, propose a plausible patch, and keep the queue moving. Capability without discomfort is not the same thing as system health.
What multiplies inside the merge queue
Once a deprecated pattern sits in the repo, agents treat it as teaching material. Five examples of the old auth exception style quietly coach the sixth. Parallel login flows stop looking like debt and start looking like local precedent. The next ticket asks for one more partner carve-out, and the agent does the responsible-looking thing: add another branch instead of challenging the design.
You can watch the same dynamic with defensive scaffolding. A try/catch appears around code that cannot fail in this service. A log-and-swallow block arrives so the output looks diligent. Reviewers skim because the diff is short and the tests pass. Two weeks later, the on-call person chasing a real auth outage has to peel back four layers of prudence before finding the actual decision point.
This is architecture by accumulation. Each change is locally correct. The system becomes harder for humans to own, and eventually harder for the next agent session to reason about cleanly, because the context window fills with stale forks of the same idea.
A Monday that will feel familiar
Imagine a support ticket titled Cancel order without charging the card. Product wants the flow to work for retail and for a wholesale channel that still reconciles invoices in Excel. An agent finds the order API, adds a cancellation flag, writes tests against that flag, and opens a pull request. The implementation is tidy. The architectural question never gets asked: does cancellation already live in the fulfillment service, and are we about to invent a second source of truth?
Or take the partner SSO case. The partner sends claim names that do not match your canonical schema. The minimal fix is a translation table in the controller. The better fix is to push the mapping into the existing policy layer and delete the one-off branches that have been collecting for a year. Agents will usually choose the translation table unless the ticket, the review checklist, or the workflow explicitly demands the wider cleanup.
None of that means you should stop using the tools. It means the tool is an assistant for execution, not a substitute for engineering judgment about what deserves to exist after the merge.
Make cleanup a first-class ticket, not ambient virtue
Hoping agents will tidy the campground unprompted is a strategy with a poor track record. Ambient virtue is not how these systems optimize, so teams need explicit gates instead.
A practical workplace pattern looks like this. Before implementation, require a short survey of related files and functions: extend, replace, or leave alone. After implementation, require a second pass whose only job is deletion and consolidation. Treat that pass as its own commit when the change is large enough that review would otherwise blur feature and cleanup. For renames and moves that touch import graphs, prefer language-server mechanical refactors over hopeful model guessing. Once a week, schedule a net-negative session where the only success metric is fewer lines with the same behavior.
Those practices sound managerial because they are. Software engineering is still the discipline of designing solutions with software, including the solution for how work flows through the merge queue. If your process rewards green diffs and closed tickets, you will get green diffs and closed tickets. If you also want maintainable systems, you have to put maintainability on the scoreboard.
Measure what you want to keep
Leadership dashboards love activity: agent tasks completed, lines generated, pull requests opened. Those numbers can rise while delivery quality stalls. A better pair of questions for this problem is narrower. Are validated changes reaching production with less rework? Are modules getting fewer parallel paths over time, not more?
Cycle time still matters. So does change-failure rate. For agent-heavy teams, add a hygiene signal you can actually discuss in standup: duplicate helpers found and removed, deprecated auth patterns retired, or review comments that asked for subtraction instead of another exception. You do not need a perfect metric. You need a conversation that treats cleanup as shipped work rather than unpaid virtue.
Keep the skill, keep the judgment
Programming remains a skill. Agents accelerate bounded implementation, migrations, and exploratory analysis. They do not automatically decide when a service has become a museum of special cases. That decision still belongs to the people who own the incidents, the merge queue, and the long-term cost of the next ticket.
The convenience of an assistant that can still navigate a messy module is real, and you should keep using that capability on hard tickets. Then ask the harder workplace question before you approve the next tiny branch: are we shipping a solution, or are we shipping another exception that tomorrow’s agent will treat as the correct pattern?
Loved it? Drop a comment with the last “tiny” PR that left your module louder, not quieter. Support the shenanigans on Patreon or buy me a coffee, and follow AttuneIT on YouTube, X, and Facebook. Let’s make tech less scary and more awesome.