A Plan Fails

A hand-written AI agent run, line by line. The lesson: recovery means distrusting your plan.

task
/api/orders is returning 500s — fix it.
Watch this run on the timeline →
plan
The API is failing. I write a plan — but a plan is only my theory of the fix, written down.
  1. Check the server logs
  2. Diagnose the failure
  3. Apply the fix
  4. Verify 200s
bashtail -n 50 logs/api.log
cheapest evidence first — no code touched yet
ERROR /api/orders — upstream DB timeout after 5000ms (x14)
Fourteen database timeouts. That's a lead, not proof.
Fourteen DB timeouts. The pool is probably starved under load.
editdb.config.ts — raise pool max 10 → 50
I bet the plan on it — raise the limit.
pool size raised
The change is made. I haven't seen it work yet.
bashcurl -s -o /dev/null -w '%{http_code}' localhost:3000/api/orders
a fix only counts if the check passes
500
Still broken. A failed check doesn't just kill the fix — it puts my whole plan under suspicion.
your call
I was wrong. You call the next move.
Still 500. Where do I look next?
“reproduce the failure directly” or “dig deeper into the logs”
The script writes both paths. Beats tagged with a pick happen only on that path.
if you picked “dig deeper into the logs
bashtail -n 200 logs/api.log
Back into the logs. Maybe I missed something.
if you picked “dig deeper into the logs
the same DB timeout, 41 more times — nothing new
Two hundred more lines, nothing new.
if you picked “reproduce the failure directly
Reading about the error hasn't helped. Trigger it myself and watch what actually breaks.
if you picked “reproduce the failure directly
The pool-size theory dies here. The plan built on it dies with it.
if you picked “dig deeper into the logs
More lines describe the same symptom. Logs won't surface the cause — reproducing it will.
plan dead — built on a misread symptom
I kill the whole plan. Every step inherited the bad guess, so patching one step can't save it.
plan
New plan, built differently — this time every step starts from evidence I watched happen, not a theory.
  1. Reproduce the failure directly
  2. Trace the request path
  3. Fix the real cause
  4. Verify 200s
bashcurl -s localhost:3000/api/orders | head
watch it break live instead of reading about it
TypeError: Cannot read properties of null (reading 'email') — order.user.email, orders.ts:41
The real bug — a crash, not a timeout. The logs never lied; I read them wrong.
Orders with deleted users. The timeouts were downstream noise — retries piling up behind the crash.
readorders.ts:30-50
never edit a line I haven't read
user joined without a null check — guests and deleted accounts arrive as null
It assumes a user that isn't always there.
editorders.ts — guard null user, fall back to order.contactEmail
fix the crash, not the noise around it
1 file changed
bashcurl -s -o /dev/null -w '%{http_code}' localhost:3000/api/orders
the same check that failed under plan A
200
It passes — because I let plan A die.
done
recovery means distrusting your plan
  • ·Plan A was a bet on one theory — the check exposed it.
  • ·When the fix failed, the plan was the suspect, not just the fix.
  • ·Killing plan A is what surfaced the real bug.

Every line above is a hand-written script; no model.

The same lesson with no code in sight: A Plan Fails — “I plan eight hours of work and get four. Figure out why.

the other runs:
  • A Clean Run — “Tests are failing in utils.test.ts — find out why and fix it.
  • Memory Fills Up — “Rename getUser → fetchUser across the codebase — 14 files.
  • A Clean Run — “What can I make with what's in my fridge?
  • Memory Fills Up — “I saved 14 apartment listings. Which ones should I actually tour?