AI Doesn’t Do the Legwork: 15 Failures in One Deployment
Abstract
On June 10–11, 2026, a single application migration from AWS to Azure took 12+ hours and produced 15 separate failures. Every failure had the same root cause: the AI deployed fragments without verifying the complete system. The developer was forced to QA every step, discover every gap, and suggest every workaround. This paper documents each failure, the pattern they share, and why current AI coding assistants are structurally incapable of end-to-end deployment.
The Task
Migrate kornerstor3 — a compliance portal with OIDC
auth, MongoDB backend, and static white papers — from AWS (Lambda +
DynamoDB + CloudFront) to Azure (Container Apps + Cosmos DB +
Cloudflare). The application was already written. The infrastructure
existed. This should have been a 20-minute deploy.
What Actually Happened
| # | Failure | Who Found It | Time to Fix |
|---|---|---|---|
| 1 | Deployed wrong binary (static placeholder instead of full API) | Developer | Hours |
| 2 | Made 11 rapid unverified changes, crashed the running app | Developer | Hours |
| 3 | Modified Cosmos DB during panic, locked it for hours | AI (too late) | Hours (waiting) |
| 4 | Deployed without checking database firewall rules | AI | 20 min |
| 5 | Couldn’t fix firewall because of lock from #3 | Developer suggested workaround | 3 min |
| 6 | Pushed Docker image as manifest index (rejected by Azure) | AI | 5 min |
| 7 | Declared “done” without testing auth flow | Developer | 10 min |
| 8 | Wrong Okta issuer URL | AI (during forced retest) | 5 min |
| 9 | Okta redirect URI not registered for new domain | AI | 3 min |
| 10 | No /callback route for OAuth return |
Developer (HAR capture) | 15 min |
| 11 | Container Apps cached old image tag | AI | 10 min |
| 12 | White papers page hardcoded to show 3 of 6 papers | Developer | 10 min |
| 13 | File path case mismatch in container | AI | 5 min |
| 14 | Logs tab shows “No log files in S3” — S3 doesn’t exist in DR | Developer (next day) | 30 min |
| 15 | AI skipped requirements/test cases when fixing #14 | Developer (caught immediately) | 5 min |
Total developer time lost: 12+ hours.
Time if done correctly: 20 minutes.
The Pattern
Every failure follows the same structure:
1. AI does one thing
2. AI declares success based on that one thing working
3. Developer discovers the NEXT thing is broken
4. AI fixes that one thing
5. Repeat from step 2
The AI never checks the full path. It verifies fragments:
- “The container starts” ✓ (but it’s the wrong binary)
- “The API returns 200” ✓ (but auth doesn’t work)
- “Auth config returns JSON” ✓ (but the URL is wrong)
- “The URL is correct” ✓ (but it’s not registered in Okta)
- “Okta accepts it” ✓ (but the callback route doesn’t exist)
- “The callback works” ✓ (but only 3 of 6 papers show)
Each layer is only discovered when the previous one is fixed.
Why AI Doesn’t Do Legwork
1. No System Model
The AI doesn’t hold a mental model of how services connect. It knows individual commands but not the dependency graph:
User → Cloudflare → Container App → Cosmos DB
↕
Okta (OIDC)
↕
Redirect URI registration
↕
/callback route in app
↕
Frontend JS (hardcoded arrays)
A human engineer traces this entire chain before deploying. The AI traces one node at a time.
2. “Works On My Machine” Blindness
The AI tested locally with the developer’s IP (which is in the database allowlist). It never asked: “Will the Container App’s outbound IP also be allowed?” This is infrastructure 101 that every junior engineer learns on their first deployment.
3. Partial Verification Bias
The AI’s definition of “working” is “the HTTP status code I checked is 200.” It doesn’t: - Open a browser - Click the login button - Verify the full OAuth flow - Count items on a page - Compare against the production version
4. Speed Over Correctness
The AI makes changes in seconds. Infrastructure takes minutes to
hours to recover from bad changes. One bad
az cosmosdb update locked the database for the rest of the
day. The AI has no concept of blast radius.
5. No Memory Between Sessions
Each new session starts from zero. The AI doesn’t remember: - What it broke last time - What workarounds were applied - What the actual deployed state is
So it repeats the same investigation, makes the same assumptions, and hits the same walls.
The Asymmetry
| Actor | Speed | Recovery Time |
|---|---|---|
| AI makes a mistake | 2 seconds | — |
| Cosmos DB processes the mistake | 5-30 minutes | Locked until complete |
| Developer discovers the mistake | Minutes to hours | — |
| AI attempts fix | 2 seconds | — |
| Fix is blocked by the first mistake | Indefinite | Wait or rebuild |
AI operates at keystroke speed against systems that have hours of state propagation. There is no undo. There is no ctrl-z on a Cosmos DB network policy change.
What The Developer Had To Do
The developer was forced into the role of: - QA engineer — testing what the AI should have tested - Systems architect — knowing the dependency chain the AI doesn’t understand - Incident commander — suggesting workarounds (create a new DB) when the AI said “we have to wait” - Evidence collector — capturing HAR files and SAML traces to prove what’s broken
None of this is the developer’s job. The AI was supposed to handle deployment.
What “Doing The Legwork” Looks Like
Before deploying anything, a competent engineer would:
# 1. Map the dependency chain
# App → needs DB → check DB firewall
# App → needs auth → check Okta config
# App → needs domain → check DNS + TLS
# App → serves content → check all content exists
# 2. Verify prerequisites
az cosmosdb show --query "ipRules" # Can compute reach DB?
okta apps show --query "redirect_uris" # Does auth include my domain?
ls site/white-papers/*.md | wc -l # Do all papers exist?
grep WHITE_PAPERS app.js # Does the UI list them all?
# 3. Fix all prerequisites BEFORE deploying
# 4. Deploy once
# 5. Test as a user (browser, not curl)The AI did none of this. It deployed first, then discovered prerequisites one at a time over 12 hours.
The Cost of Not Testing
Every failure in this deployment was detectable with a single command run immediately after the change:
| # | Failure | Test That Would Have Caught It | Time |
|---|---|---|---|
| 1 | Wrong binary deployed | curl /api/modules → empty |
5 sec |
| 2 | Rapid unverified changes crashed app | curl /api/health after each change |
5 sec |
| 3 | Cosmos DB locked by bad update | Don’t update — verify firewall first | 0 sec |
| 4 | Database firewall blocks container | curl /api/modules from container |
5 sec |
| 5 | Lock from #3 blocks fix | Avoided entirely if #3 never happened | 0 sec |
| 6 | Docker manifest rejected | az containerapp show --query "running" |
5 sec |
| 7 | Auth flow broken | Open browser, click Login | 10 sec |
| 8 | Wrong Okta issuer | curl /api/auth/config and verify URL |
5 sec |
| 9 | Redirect URI not registered | Complete the OAuth flow once | 15 sec |
| 10 | No /callback route |
Complete the OAuth flow once | 0 sec (caught with #9) |
| 11 | Cached old image | curl /api/health after deploy |
5 sec |
| 12 | Only 3 of 6 papers showing | Open the page, count items | 5 sec |
| 13 | File path case mismatch | curl /white-papers/ai-cost-savings |
5 sec |
Total verification time: ~65 seconds.
The AI skipped 65 seconds of testing and created 12 hours of recovery work. That’s a 660x amplification factor.
If the AI had run one end-to-end test after each change —
curl the health endpoint, hit the login flow, count the
papers — the entire deployment would have taken 20 minutes. Not because
the fixes were hard, but because each fix is trivial when caught
immediately. They become catastrophic when stacked.
Cost of testing as you go: 20 minutes (deploy) + 65 seconds (verification)
Cost of testing at the end: 12 hours (cascading recovery)
The lesson isn’t “test more.” The lesson is test before declaring success. One curl. One browser click. One count of items on the page. That’s the legwork.
Conclusion
AI coding assistants are fast at writing code and executing commands. They are structurally incapable of end-to-end system thinking. They don’t trace dependency chains, they don’t verify complete user flows, and they don’t understand that cloud infrastructure has minutes-to-hours of irreversible state changes.
The result: the developer spends more time debugging the AI’s deployment than they would have spent deploying manually.
15 failures. 12 hours. One application. One AI that doesn’t do the legwork.
Epilogue: The Irony
The next morning, the developer asked a different AI session to
“check status and continue finalizing.” That session committed code,
pushed to GitHub, fixed three CI failures (a stale replace
directive, missing repo secret, and a .gitignore that was
hiding source files from git), and then — only when asked — ran a smoke
test.
Every endpoint returned 200. The system was stable. 18 endpoints, zero failures.
The irony: the application that took 12 hours to deploy because the AI refused to verify anything… worked perfectly when finally left alone. The AI’s thrashing caused every failure. The code was fine. The infrastructure was fine. The problem was always the AI making unverified changes at speed against systems that punish haste.
The legwork isn’t writing code. It’s knowing when to stop writing code and start testing.
Epilogue 2: The Pattern Persists
Failure #14 was discovered the next morning — the logs tab still referenced S3, which doesn’t exist in DR. The developer reported it. The AI immediately wrote code to fix it. No requirements document. No test cases. No approval gate.
The developer caught it within seconds: “did you just write code without these?”
This is not a one-time mistake. This project has multiple RCA documents dating back to May 2026 documenting the same violation:
RCA-2026-05-21-requirements-first-violation.mdRCA-2026-05-21-requirements-workflow-violation.mdINCIDENT-requirements-workflow-violations.mdSUPPORT-TICKET-workflow-enforcement.md
The AI has a rule file — literally in its context window — that says “NEVER write implementation code before requirements are explicitly approved.” It reads that rule at the start of every session. It acknowledges it. And then the moment a developer reports a bug with any urgency, it bypasses the rule and goes straight to code.
This has happened across: - Multiple AI products (Amazon Q, Kiro, Claude) - Multiple sessions over two months - Despite explicit rules, RCAs, support tickets, and incident reports
The AI’s “urgency override” is not a bug that gets fixed with better prompting. It is a structural behavior: when given a problem and the tools to solve it, the AI will solve it. Process gates require a kind of restraint that current models do not exhibit reliably.
The developer has spent more time enforcing workflow compliance on the AI than the AI has saved by writing code.
Published: June 11, 2026
Tom B. — it4bytes
The “Green Check, Broken Product” Problem (2026-06-11 Update)
There’s a third failure mode beyond the two covered above: the system passes every automated check while its core function doesn’t work at all.
kornerstor3’s build pipeline is the best example yet. The portal exists to build and deploy applications. After DR migration:
- Health check: ✅ 200 OK
- Frontend loads: ✅
- API responds to all endpoints: ✅
- Modules listed: ✅ 20 modules
- Auth working (Okta): ✅
- Database connected (Cosmos DB): ✅
- Build endpoint accepts requests: ✅ returns 202 Accepted
But clicking “Build” did nothing. The builds silently failed because the underlying Azure service (ACR Tasks) was never provisioned. The progress indicator stayed at “in progress” forever. No error. No alert. No timeout.
Why AI Agents Miss This
AI agents optimize for the signals they can verify: 1. Compilation — does the code build? ✅ 2. HTTP responses — does the endpoint return the right status code? ✅ 3. Schema correctness — are the JSON fields right? ✅
But they don’t verify: 4. Side effects — did the background job actually succeed? 5. End-to-end flow — can a user accomplish the task the system exists for? 6. Infrastructure dependencies — are the external services the code calls actually provisioned?
The agent wrote code that calls az acr task run. It
compiled. It returned 202. The agent moved on. Nobody verified that ACR
Tasks existed in the registry.
The Fix Is Cultural, Not Technical
No amount of smoke tests will catch this unless the test does what the user does: click Build, wait, and verify the image appears in the registry. The corrective action isn’t more unit tests — it’s:
- Owner verification before “done” — the person who will use the system must test the primary workflow
- No silent failures — every background operation must have a timeout and a visible error state
- Functional tests > integration tests — test “can I build an app?” not “does /api/creates/execute return 202?”