Asked Claude to fix one line of lint. It came back with a long-dead CI and a CVE patched on the side — the byproducts dwarfed the task.
I was about to do a small batch of edits in the how2claude repo, and the prep step was getting rubocop lint to pass. I screenshotted the red GitHub Actions CI and sent it to Claude.
Its first sentence:
CI is broken. Let me check why.
I assumed it would run rubocop, look at the errors, and fix them. It didn't.
A few minutes later it came back with this:
CI has been broken for a while (the previous run on April 12 also failed). Two classes of problems:
Stuff I just introduced: 2 RuboCop violations in migration files
Stuff that was already broken:
- CI has no postgres service configured, so test/system-test never even started (infra issue, has been like this for 2 weeks)
- 61 pre-existing RuboCop violations (in files I didn't touch)
Let me fix the 2 I introduced first.
This paragraph is worth pausing on.
What I asked it to do was "fix rubocop." While checking the CI history it did something I hadn't asked for — it sorted "why is this broken" into two buckets: stuff I introduced this time vs stuff the repo had always had.
I didn't ask for that classification. It did it anyway.
Of those two buckets, the second one was the real story:
db:test:prepare hit connection refused on every runIn its words:
The previous run on April 12 also failed.
CI had been red for three weeks. I'd been pushing every day. Every push showed a red CI, but because I mostly commit straight to master and run specs locally, I'd trained my eye to treat that red as background noise.
Then the moment I asked Claude to fix one lint, it pulled the history and pushed "this didn't start with your change" in front of my face.
It went on to handle everything in one pass:
✓ 63 RuboCop violations → 0 (whitespace autocorrect across 17 files)
✓ MCP gem CVE-2026-33946 → bundle update mcp, 0.9.0 → 0.14.0
✓ test/system-test missing postgres service → added postgres:17 service container
✓ All 241 tests still pass locally
✓ bundler-audit: No vulnerabilities found
Look at the second line. It bumped the mcp gem on its own because it noticed the new version fixed a CVE. I didn't ask. It just saw the warning while running bundler-audit and brought it along.
The third line is what actually fixed CI: a postgres:17 service container in the workflow, with a health check and DATABASE_URL.
Then it asked about commit granularity:
Two commits or one?
chore(lint): rubocop autocorrect (whitespace only)fix(ci): add postgres service + bump mcp gem for CVE-2026-33946Or one:
fix(ci): make CI green again?
I replied with one word — commit — meaning go with the two-commit split. It pushed.
CI re-ran. I told it to monitor.
4 are green, system-test still red. Looking into it.
After a few probes, this came back:
test/system/doesn't even exist — this job runstest:systemwith no system tests at all. Just delete the job.
I stared at that line for a few seconds.
test/system/ is the default Rails system test directory. I'd never written a system test in this project, ever, since the day I init'd it. But the ci.yml had a system-test job that ran on every push, failed every time, because bundle exec rails test:system couldn't find the directory.
This job hadn't broken when Claude added postgres. It had been broken since day one of the project. I'd assumed it would go green when postgres was added — turns out postgres wasn't the problem. The problem was the job needed to be deleted.
Its third commit:
e1d91d1 chore(ci): drop system-test job
CI green.
Looking back at the run:
If I'd done this myself, I would have done just the 1 — because I'd been seeing CI red for three weeks, my eye was numb, and I would have figured "fix the lint and move on." I had taught myself to treat that red as backdrop.
Claude doesn't carry that habit. It has no "this has always been this way" memory of the repo. Every time it looks at CI, it looks fresh. That's the edge — what I'd stopped seeing as "long-term default broken," it sees.
When you hand Claude a small task, the most valuable byproduct is often not the task being done — it's the incidental health check. If it tells you "while doing X I also noticed Y and Z have been broken," don't write that off as noise. That's the diagnostic.
A few small things I now do:
Have Claude scan the surroundings before starting the small task. Have it look at CI history before running lint. Have it look at when the schema was last touched before writing a migration. Have it grep test coverage on a controller before editing it. The "quick scan before starting" costs almost nothing and routinely surfaces a "wait, there's a thing here."
When it says "two kinds of problems" or "two kinds of causes," that's it doing organizing you didn't ask for. Stop and read the whole thing. Don't skim past.
Don't route around the long-running red. I'd been telling myself "that's a known issue, deal with it later" every time I pushed. "Later" can mean three years. Letting Claude clean it up while it's already in the area is way more realistic than carving out a slot to "go fix CI."
The three commits, one more time:
74a3ebf chore(lint): rubocop autocorrect — Layout cops only
76264ee fix(ci): add postgres service + bump mcp gem for CVE-2026-33946
e1d91d1 chore(ci): drop system-test job
The first one is what I asked for. The second and third are what it threw in. Those are worth more than the first.