AI Coding Today: Steam Engines Pulling Carriages
A Real Scenario
Yesterday, I asked Cursor to refactor a Node.js project. It quickly delivered beautiful code: decoupled logic, optimized performance, and added type annotations.
Then I spent two hours:
- Manually adjusting 40+
importpaths - Re-running unit tests (because the AI didn’t know I used Jest vs. Mocha)
- Resolving three version conflicts (AI used new APIs, but my dependencies were old)
- Rewriting the README (AI-generated docs weren’t usable)
AI wrote the code in 3 minutes. I spent 2 hours cleaning up.
This reminded me of a story from history class: in the early 19th century, the British invented steam locomotives, but railways weren’t widespread yet. So what did they do? They mounted steam engines on horse carriages.
The result? Carriage wheels couldn’t handle the engine’s weight, roads got destroyed, and the turning radius was worse than horses.
That’s AI Coding today: 2025 AI pulling a 1995 carriage.
What Are Our “Carriages”?
1. File Systems: AI’s Nightmare
AI generates code fast, but it doesn’t know:
- Does your project use
src/orlib/? - Are utility functions in
utils/orhelpers/? - Is the config file named
config.jsorsettings.json?
Every time AI generates code, you have to:
- Copy code to the correct file
- Adjust
importpaths - Manually merge with existing code
This isn’t AI’s fault—it’s the file system’s.
File systems were designed for humans in the 1960s: when you see src/components/Button.tsx, your brain instantly knows it’s a button component.
But AI just sees a string. It doesn’t know if Button.tsx and button.tsx are the same file (they’re not on Linux, but are on Windows).
2. Dependency Management: Version Hell
AI gives you this code:
1 | import { useQuery } from '@tanstack/react-query' |
Looks fine. But:
- Your project uses React Query v3, this is v4 syntax
- You also have
swrinstalled, now you have two data-fetching libraries - AI doesn’t know if you use npm, yarn, or pnpm
You need to:
- Check
package.json - Upgrade dependencies (or downgrade AI’s code)
- Reinstall
- Pray there are no breaking changes
Dependency management was designed for manual coding, assuming humans carefully read changelogs and upgrade dependencies one by one. AI generates code 100× faster than humans, but dependency management is still stuck in 2010.
3. Testing: AI Doesn’t Know What You’re Testing
AI finishes the code, you ask: “Write tests for this.”
It generates:
1 | describe('Calculator', () => { |
But:
- You use Vitest, not Jest (syntax is similar, but imports differ)
- Your project convention: tests go in
__tests__/directory, not.test.jssuffix - Your CI requires >80% coverage, AI only tested the simplest case
Testing systems assume you “write tests after code”, but AI Coding’s rhythm is “generate and test simultaneously.” We need real-time validation, not post-hoc homework.
4. Git: AI Doesn’t Understand Your Commit Conventions
AI modified 10 files, now you need to commit.
But your team’s convention:
- Commit messages must start with
feat:/fix: - Each commit changes only one feature
- Must link to Jira tickets
AI doesn’t know this. It just modifies code, doesn’t care how you commit.
You either manually split commits (time-consuming) or do one big commit (get yelled at in code review).
Why Is This Happening?
Because our development toolchain was designed for manual human programming:
| Traditional Assumption | AI Coding Reality |
|---|---|
| Programmers write line by line | AI generates hundreds of lines at once |
| Read existing code before modifying | AI only sees context window (limited) |
| Understand overall project structure | AI has limited architectural understanding |
| Remember previous modifications | AI restarts with each conversation |
| Write slowly, test slowly | AI generates fast, humans clean up slowly |
We’re running a 21st-century engine on 20th-century roads.
What Would True AI-Native Development Look Like?
1. Ditch File Systems, Embrace Knowledge Graphs
Instead of src/utils/formatDate.js, use:
1 | Knowledge Graph: |
AI doesn’t need to remember paths, it just needs to know: “formatDate is a utility function, depends on dayjs, used in UserProfile.”
File systems are just serialized forms of knowledge graphs (so Git can track them), but shouldn’t be the primary interface for developers and AI.
2. Declarative Dependencies
Instead of package.json, use:
1 | I need: |
AI selects dependencies based on your intent, not you manually searching, comparing, installing, configuring.
3. Real-Time Validation Over Unit Tests
Instead of writing add.test.js, use:
1 | Real-time constraints: |
AI checks these constraints in real-time while generating code, not generate code → write tests → run tests → fail → fix code.
4. AI Manages Version Control Directly
Instead of manual commits, use:
1 | AI: |
AI auto-generates compliant commit messages, auto-splits commits, auto-links issues.
How Far Are We from AI-Native?
Technically: 3-5 years.
There are already early attempts:
- Replit’s Agent: you don’t manage file paths, the Agent finds them
- val.town: code lives in the cloud, dependencies auto-handled
- Cursor’s Composer: can edit multiple files simultaneously
But these are “better carriages,” not trains.
What does a real train need?
- New project organization (not file systems)
- New dependency management (not package.json)
- New validation mechanisms (not unit tests)
- New collaboration methods (not Git + PR)
This requires rebuilding the entire ecosystem, not something a single AI editor can solve alone.
What Can We Do Now?
Before the new ecosystem matures, we can:
1. Establish AI-Friendly Project Conventions
Bad:
1 | project/ |
Better:
1 | project/ |
2. Reduce Implicit Conventions
Bad:
“Our team convention: utils only contain pure functions” (AI doesn’t know)
Better:
Enforce in ESLint rules: utils/ directory forbids side effects
3. Use Tools to Enforce Standards
- Commit messages → commitlint
- Code formatting → prettier
- Import order → eslint-plugin-import
AI isn’t good at remembering implicit rules, but tools can enforce them.
4. Accept “Imperfection”
AI-generated code won’t be 100% in your style. Instead of spending time tweaking formatting, focus on logical correctness.
Perfection is the enemy of good code.
Conclusion
The era of steam engines pulling carriages didn’t last long. Soon, people realized: to harness the power of steam engines, they needed railways, train stations, signaling systems—an entire new infrastructure.
AI Coding is the same.
Right now we use AI to generate code, then manually adjust paths, fix dependencies, write tests, split commits. It’s inefficient, but it’s a necessary transition period.
The real revolution isn’t better AI models, but entirely new development infrastructure designed for AI.
When that happens, developers won’t “write code” anymore. They’ll “define intent, validate results, make architectural decisions.”
Code generation, testing, deployment—those are AI’s job.
We’re standing at this turning point.
The steam engine is already mounted on the carriage. Can the railway be far behind?

