opinion
We Don't Apply Changes For You — On Purpose
Every other tool is racing toward "full autonomy." We built the brakes in, and I'd make the same call again.
Here’s a feature request we get, in some form, almost every time we demo Swordfish: “This is great, but can it just apply the fixes? Why am I still reviewing diffs in 2026?”
It’s a fair question and the answer is a flat no, and I want to explain why that no is a design decision I’m proud of rather than a roadmap item we haven’t gotten to. Swordfish never modifies your source tree. Every rewrite it produces (from the direct LLM, from a permission-gated agent, from a subprocess copilot) lands in a .new sibling file or a configured mirror directory. You diff it. You decide what merges. The original code sits there untouched the whole time.
That’s not timidity. It’s the conclusion I reached after watching what happens when you remove the human from this specific loop.
The thing autonomy advocates wave away
Go back to the inferred-knowledge problem. A migration is full of code whose meaning lives in someone’s head: the status = 3 that means cancelled, the magic region IDs, the isolation level someone bumped in 2015 for a reason nobody documented. And it’s full of behavioral traps that look correct and aren’t. An autonomous agent rewriting that code has no way to know which WHERE clause encodes a load-bearing business rule and which is incidental. It can’t ask. It just rewrites, fluently, and moves on.
So when someone says “just apply the fixes automatically,” what they’re really asking for is: let a system that cannot know what your code means change all of it at once, unsupervised. The best case is it’s right most of the time. The worst case is the one that actually happens — an agent rewrote 200 files overnight, 190 are fine, 10 silently changed behavior, and now you’re spelunking through a diff the size of a phone book trying to find the 10, except git blame just points at a robot. That’s not faster than doing it yourself. That’s a debugging project wearing a productivity costume.
The human stays in the loop because the human is the only thing in the pipeline that knows what status = 3 means. Remove them and you haven’t automated the hard part — you’ve just deferred it to production.
What “keeping the human in the loop” looks like in code
This philosophy isn’t a disclaimer in the docs. It’s enforced in the architecture, and the enforcement is the part I actually want to brag about:
Output never overwrites input. Rewrites go to .new siblings or a mirror dir. The blast radius of a bad suggestion is “you read a diff and said no,” full stop. There is no code path where Swordfish edits your file in place, because we didn’t write one.
The copilot subprocess is locked down. When you hand a rewrite to a CLI copilot, we invoke it with create_subprocess_exec — an explicit argument list, never a shell, so there’s no string-interpolation injection surface. The argument list is fixed, and we deliberately strip the “yolo” / auto-approve flags that those tools offer. The whole selling point of those flags is “don’t ask me, just do it.” That is precisely the behavior we refuse to enable. On purpose. Always.
The in-process agent is permission-gated. Run the Claude Agent SDK mode and every single tool call the agent wants to make is routed through our permission UI first. The agent proposes; you approve or deny, per action. It cannot touch a file you didn’t sign off on, because the permission callback sits between the agent’s intent and the filesystem.
Three layers, one idea: the machine drafts, the human commits. The tool is a power tool with the safety on, not a robot with the keys to your codebase.
”But it’s slower”
Sometimes, marginally, yes. Reviewing a diff takes longer than not reviewing it. I’ll own that.
But run the actual math, not the demo math. Auto-apply feels faster because the expensive part — finding and fixing the 10 wrong files — gets pushed past the moment you’re measuring. You “finished” in an hour and then spent three weeks hunting behavioral drift. Review-first feels slower because the cost is paid upfront and in plain sight, where you can see it. Same total work, mostly; wildly different risk profile, and a far better chance you catch the data-corrupting change before it corrupts data.
And here’s the part that flips it: a good assessment plus a human reviewing scoped, contextual diffs is genuinely fast — three-times-faster-than-by-hand fast — and you stay in control of the dangerous parts. You get most of the speed of automation without betting your data on a system that can’t know what your code means. That’s not a compromise. That’s the right point on the curve.
So no, Swordfish won’t just apply the fixes. It’ll find them, explain them, draft them, hand them to whatever tool you trust, and then get out of your way so you can do the one thing it can’t: decide. If a vendor’s pitch is “our AI does the whole migration, hands-off,” ask them what happens to the ten files it got quietly wrong, and who finds them, and when. The silence is the answer.
Next up: how we keep a list of 20,000 findings from being as useless as a wall of red.
Swordfish is an open-source (Apache-2.0) assessment harness for migrating Oracle, MySQL, SQL Server, Sybase, and DB2 to PostgreSQL — it shows you what’s in your codebase, what needs to change, and hands scoped tasks to the copilot you already use. Source: github.com/EnterpriseDB/swordfish-migrations