Justin Bartak · AI Org · · 6 min read
Your Linter Was the Prototype.
TL;DR
Every engineer has run a linter with the fix flag. That is self-healing code in its smallest form: a program that finds a defect and writes the correction. Scale the idea to the whole repository and the build stops only reporting drift. It repairs what it can and opens a pull request for the rest.
Most engineers have already written self-healing code and did not call it that. If you have ever run a linter with the fix flag, you have shipped the smallest version of the pattern: a program that detects a defect and writes the correction.
Everything past that is the same idea with a bigger blast radius and more discipline.
A checker tells you the truth. A fixer tells you the truth and hands you the diff.
What does it look like at repository scale?
One convention, repeated per defect class: a detector and a separate fixer.
On Orbyt every guard has a name like check-seo-infra and its optional partner is heal-seo-infra. The guard is 1 of 103 mechanical checks and it fails the build. The healer repairs the subset that is deterministic and prints what it refused to touch.
The healer defaults to a dry run. It prints the plan and exits. Applying requires an explicit flag, because a repair tool whose default action is to write is a foot gun with a schedule.
That is the whole shape. ESLint's fix flag does it for syntax. This does it for anything you can specify: derived files that drifted from their source, a config line that should not exist, a structural attribute a page is missing.
Why must the checker and the fixer be separate programs?
Because a program that grades its own repair always passes.
Separation forces the fixer to satisfy an independent detector, which is the same reason the model that writes the code should not be the one that audits it. It also lets you ship the detector alone, watch what it catches for a week, and automate only the part that turned out to be genuinely mechanical.
It has a practical benefit too. The detector runs in CI, where nothing is allowed to write. My CI runs the check flag, never the heal flag, because a build that edits your repository is not a build.
What can a machine fix unattended?
Draw the line at judgment, not at difficulty.
Mechanical, so it heals itself: regenerating a derived file so the generated map cannot drift from its source. Removing a stray sitemap directive from robots that shadows the real index. Adding a structural attribute that is either present or absent with nothing in between.
Judgment, so it reports: anything touching source logic, any public claim, any prose. My healer prints those as a worklist. When the same audit found 31 FAQ answers running over 80 words, not one was auto-shortened, because shortening a sentence in somebody's voice is writing, not repair. A separate proposal layer drafts the copy into a markdown file for approval and never edits source. An apply layer runs only after a human approves it.
And some things are exempt forever. A set of my series posts is excluded from both layers permanently, because that voice is mine and no codemod gets a vote on it.
Automate the repair whose correct answer is already written down. Propose the rest.
What is the failure mode?
A fix that satisfies the detector without solving the problem. This is the one that bites teams, and it is worth a real example.
A guard counted 42 pages emitting Article or FAQPage structured data with no speakable block, which is the marker that tells an answer engine which passage to quote. The detector was a substring test. A codemod could have pasted the same three-line selector into all 42 files and taken the number to zero in a single commit.
It would have earned nothing. A selector is worth something only if it matches an element that actually exists on that page. Worse than nothing, in fact: the guard would now be green, so the alarm retires and the real gap becomes invisible and unfunded.
So the healer validates every candidate selector against the actual file, applies only the ones a page can satisfy, and skips and reports the rest. A page that can satisfy none stays red on purpose.
That is the rule I would tattoo on anyone building this. A green guard is not the goal. A green guard is a claim, and a fixer that makes claims it cannot support is worse than the defect it hid.
How should a repair reach the codebase?
As a pull request, never as a push.
My weekly healing workflow runs Sundays at 08:00 UTC, repairs what it can, and opens a PR. It never pushes to main and it never merges. Before it opens anything, it re-runs the detector, the type check, and the test suite itself, because a bot-authored PR does not trigger the normal CI workflow. Skipping that means the automation is the one path into your repository with no checks on it.
Anything it could not heal becomes an issue instead. The unhealable case is the valuable output, because it is the one that needs a person.
What to do Next
Pick the review comment you have written more than 5 times. That is your first defect class.
Write the detector first, and only the detector. Run it across the repository and read what it catches for a week. You will find that some of what you were correcting by hand is not mechanical at all, and that is the most useful thing this exercise produces.
Then write the fixer for the deterministic subset only. Dry run by default. Separate program. Opens a PR. Everything else it prints as a list, which is now a worklist instead of a habit.
The harness that grades this took me 84 dimensions and 49 recorded failures to build, but the first one was an afternoon, and it started exactly here: one check I was tired of performing by hand.
The fix that runs while you sleep is not the impressive part. Knowing which fixes are allowed to is.
Related reading:
-
Self-Healing Is a Euphemism. the runtime half, and why you count every repair
-
84 Ways to Tell Me I'm Wrong. where the detectors live and how each one was earned
-
Your Tests Are the Spec Now. writing intent as checks a machine can act on
-
Codex Accuses. Claude Convicts. why the thing that finds the problem should not be the thing that fixes it
Originally published on orbytlabs.ai on Sep 8, 2026.
Frequently asked questions
What does self-healing code actually look like in a real codebase?
At repository scale, each defect class gets a guard and a separate healer: a guard named check-seo-infra fails the build, and its optional healer, heal-seo-infra, repairs the deterministic subset. The healer defaults to a dry run, printing its plan before exiting, and applying changes requires an explicit flag rather than writing automatically.
Why can't the same tool both detect and fix code issues?
A program that grades its own repair always passes, so the fixer must satisfy an independent detector instead of approving its own work. Separation also lets a team ship the detector alone, watch what it catches for a week, and automate only the part that turns out to be genuinely mechanical. The detector runs in CI, where nothing is allowed to write.
What happens when an automated fixer can't safely repair something?
Anything touching source logic, a public claim, or prose gets printed as a worklist rather than automatically fixed, since rewriting someone's sentence is writing, not repair. A proposal layer drafts suggested copy into a markdown file for approval, and an apply layer runs only after a human approves it. Anything the weekly workflow cannot heal becomes an issue for a person instead.




