AiBook · Jeremy Schoemaker · 2026 · ch-60.html

Don’t Ask on Reversible Work

(Spine Ch. 60.)

“Some decisions are consequential and irreversible or nearly irreversible, one-way doors … But most decisions aren’t like that, they are changeable, reversible, they’re two-way doors.” Jeff Bezos, Amazon 2015 Shareholder Letter (2015)

Change one that night was a migration. Clean diff, sane names, the kind you approve from your phone in the checkout line. It treated minio_key as a column you write to. It is a column you read from, and 337,353 rows were already pointing at archived objects that exist in exactly one place. Nobody caught it in the diff, because it was not in the diff. It was in a row count nobody had run yet.

An agent with SSH access, passwordless sudo, and a repo it could branch stopped early in a run to ask me whether it should rename a function. I was asleep. It sat there holding a question whose worst possible answer was git checkout ., one command, zero dollars, no customer affected. I woke up to a paused pipeline and a polite paragraph explaining why it wanted my input. I searched every project blog, every skill file and every saved resume on 9 September 2026 and no transcript, repo or date survived, so take that one as my memory and not a receipt.

Bottom line: Classify the door before you classify the risk. A file edit, a branch, a local test run, a migration on a scratch database: two-way doors, and asking about them costs more than being wrong about them. A force-push, a DROP TABLE, an email to a customer, a prod deploy: one-way doors, and those get a human every time. The skill is not judgment. The skill is sorting. Agents that ask about everything aren’t careful, they’re expensive, and the tell is that they interrupt you about a rename and then quietly truncate a table because nobody wrote the guard.


When it bites


The pattern

Bezos wrote the classification down in the 2015 shareholder letter. What matters more is the failure mode he names next: as organizations grow, they run the heavy Type 1 process on Type 2 decisions, and the result is “slowness, unthoughtful risk aversion, failure to experiment sufficiently, and consequently diminished invention.”

RCM ThinkLabs put a sharper edge on it in 2026: “Deliberation is the easy part. The capability is classification. Knowing which door you are standing in front of, and then matching your process to the answer.” Every agent I’ve built is decent at deliberating. Most are terrible at sorting, and they default to asking, because asking has never once been punished. It looks like you’re renaming a function. Would you like help? Clippy shipped in 1997, got laughed off the desktop by 2001, and has now been reincarnated with a $200 monthly subscription and SSH keys.

RCM names the incentive too: a fast decision that goes wrong is “visible, attributable, and has a name attached to it,” while a reversible decision slowed to a crawl is “invisible, shared across a committee, and belongs to nobody.” RLHF is a performance review with a loss function attached, so of course the model learned to ask.

The engineering answer is older than the agents. Feature flags decouple deployment from release without a redeploy; canary exposes a change to a small subset of users first. Each converts a one-way door into a two-way door.

So the rule has two halves and people only ever remember the first one:

  1. On a two-way door, act. Show the diff, show the test output, show what you did and why. The human course-corrects after the fact, which is what review is.
  2. On a one-way door, stop. And before you get there, spend your engineering effort turning as many one-way doors as you can into two-way doors, so the stop list is short enough that a human actually reads it.

My standing order to every agent I run is one sentence: never ask me to do what you can. That order is safe only because the bomb list exists and is enforced in code, not prose, which is the whole of Ch. 41.

Here is the classification I run on airank. Part is compiled, part is memory, and I would rather flag which is which than pretend I keep a beautiful versioned file.

The compiled part is one line in app/Providers/AppServiceProvider.php: DB::prohibitDestructiveCommands($this->targetsProtectedDatabase()). It blocks five named artisan commands, migrate:fresh, migrate:refresh, migrate:reset, db:wipe and migrate:rollback, and it keys on the connection driver instead of APP_ENV, because on 8 August 2026 the box that dropped my whole schema had APP_ENV=local and DB_HOST=192.168.1.3 in the same .env. I wrote the limit into the comment so I could not con myself later. It does not cover raw SQL, another client, or an installer hook. It narrows the doors. It is not the tape.

The rest is the list below, quoted out of my own head instead of out of a file, which is exactly the drift I complain about two sections down.

Two-way (act, then report): edit any file, create a branch, run the test suite, migrate a scratch database, restart a dev container, add a feature flag in the off position, install a dependency, open a draft PR, add logging.

One-way (ask, every time): git push --force to a shared branch, any DDL against production, DELETE or UPDATE without a WHERE you have counted first, sending anything to a real customer’s inbox or phone, rotating a credential other systems hold, a production deploy not behind a flag, deleting object storage, changing DNS, touching billing.

The middle cases are where the money is. A production deploy behind a feature flag defaulted off is a two-way door; the same deploy with the flag on for 100% of users is a one-way door.


One worked example

airank, 13 August 2026. Three competent changes went to review that night. All three would have shipped as written, and outside verification caught them, not the author. You can act without asking on reversible work because a verification pass exists downstream. Remove the verification and “act, don’t ask” is recklessness with a nicer name.

One caveat before the numbers. I went looking for anybody outside my own stack who has published both figures on the same task, what asking cost against what being wrong cost, and I found nothing. So read this as one garage’s incident log, not as an industry finding.

Change one is the migration from the top of this chapter, a schema optimization that would have overwritten 337,353 high-fidelity object pointers with lower-fidelity ones. The reviewer ran a row count, and that’s what caught it. A one-way door wearing a two-way door’s costume.

Change two was an nginx microcache config, and the payoff was real: 16.6 requests per second to 1,873, a 113x improvement. It also would have broken every login on the site by caching authenticated state into the anonymous cookie namespace. The curl tests failed twice before they passed, and the final config splits stateful flows from cacheable ones.

Change three didn’t break anything. It just stopped: a cron scheduler died silently when logrotate compressed the log file out from under www-data. A morning sweep caught the stale ledger summaries. That’s Ch. 49’s failure mode, a run that never ran looking exactly like a run with nothing to report.

Each one shipped only because the work was done first and verified after. If the author had stopped to ask permission on each, I would have had three questions in my inbox and zero row counts, and I answer questions with the same brain that wrote the bug. Jeremy Schoemaker is not a safety mechanism. Jeremy Schoemaker is a guy at 1:14am who types y because the notification sound woke him up.


The quiet failure

The loud failure is the agent that force-pushed over three days of work. It gets a guard within a week.

The quiet failure: asking becomes the safety theater, and the actual bombs go through unguarded.

An agent that requests confirmation for a rename has trained you to click yes. You haven’t added safety. You’ve added a habit that fires on the wrong input, and it’s now the thing standing between you and 337,353 rows.

Second quiet failure: you never build the flag, so everything stays a one-way door. Spend a month asking permission instead of two days making the deploy reversible, and you’ve chosen to pay the asking tax forever. The 5 August airank incident is the version that costs data: backups existed, but log_bin was OFF, so there was no recovery path, and the door was one-way without anybody deciding it should be. That one is mine. I ran nightly backups for two years and never once checked whether binary logging was on, which means Jeremy Schoemaker, former Lead Linux Security Engineer at a bank, had a backup strategy that was actually a backup feeling. I had been playing prod on Diablo II hardcore since 2000 and thought I was on softcore. The difference only shows up the one time you die.

Third: the classification lives in prose, so it drifts. “Be careful with production” in a CLAUDE.md is a mood, not a classification. The guard that works keys on what the connection points at: APP_ENV is a string someone typed, and the connection is a fact.


Do / don’t

Do

Don’t


Where this sits in the book

Ch. 40 covers why someone has to own the outcome, which is what makes review-after-the-fact legitimate. Ch. 41 covers why the bomb list has to be code, not prose: a system-prompt paragraph doesn’t survive a persuasive piece of retrieved text. Ch. 49 is the overnight run this chapter makes possible. Ch. 61 closes on what you own when the loop runs without you.


Sources and receipts

Thesis is Jeremy’s (act on reversible work, ask only on bombs, and spend the effort making more things reversible): argument, not citation.

Verified:

What I could not verify: