(Spine Ch. 40.)
“Declarations of high confidence mainly tell you that an individual has constructed a coherent story in his mind, not necessarily that the story is true.” Daniel Kahneman, Thinking, Fast and Slow, Ch. 20 “The illusion of validity” (2011)
An operator types air:block --remove, watches the flag
clear, and gets on with their day. The command worked. The screen said
so. Somewhere behind it a seven-day cached NXDOMAIN verdict still has
its own opinion, and on the next pass the system quietly puts the block
back and never mentions it. Six frontier models had reviewed that design
and all six said ship it. The override survived exactly as long as
nobody looked: a shelf life of one job cycle.
Six frontier models sat down on 15 August 2026 to review a one-day-old CLI. They got a brief saying the system “polls every 20s, hard cap 180s, then returns whatever it has.” Five accepted it. One, kimi-k3, opened the source: the 180-second cap only existed on the pending branch, and the 429 rate-limit branch had no elapsed-time check at all. A server in sustained overload could pin the CLI forever. I wrote a one-line summary of my own 24-hour-old code, got it wrong, then rented six frontier models to agree with me about it. Five did. The n00b in that room was me, and I was also paying for the room.
Bottom line: Human-in-the-loop is not a checkbox. It is a testable property: at the moment of approval, the human must be able to say no with information, and that no must stop something. Miss either half and you have a signature block, not HITL. A signature block is worse than nothing because it launders the decision. Everybody downstream now believes a human looked.
EU AI Act Article 14 requires that high-risk systems be designed so they “can be effectively overseen by natural persons during the period in which they are in use”: the human has to understand the system’s limitations, detect automation bias, and override or reverse the output. That is an engineering spec, not a disclaimer, and it enters into force 2 December 2027. An Effective Altruism Forum analysis from 31 August 2026 put it bluntly: Article 14 “neither acknowledges nor seriously addresses” how you implement it.
A 2024 Harvard Business School study gave 228 evaluators AI recommendations with clear explanations of the reasoning. Reviewers were 19 percentage points more likely to align with the AI than the control group; add narrative rationales and deference climbed another 5 points. MIT Sloan Management Review said it out loud on 12 June 2025: understanding the reasoning can turn reviewers into people who “rubber stamp rather than acting as a critical check.”
That is automation bias: the tendency to favor AI suggestions and overweight them. Complexity and workload “increase reliance by placing stress on cognitive capacity.” Your agent produces complexity and workload as its primary output: a bias machine with a tired person stapled to the end of it.
Software got its own version on 26 December 2025, when Leena Malhotra published three months of replacing human code review with AI review. Nothing paged anyone, because nothing broke: six weeks in, the juniors had stopped learning, the code went “homogenous but soulless,” and a change traveled from author to production with exactly one human understanding it. Mitchell, Ghosh, and Passi made it structural on 24 August 2026: as agents gain autonomy they push humans out of the loop, and oversight, the fix everybody names first, “is not a simple solution.”
Three conditions make a review real, and every one is a build task, not a policy sentence:
The human must have independent information. Not the agent’s summary of what it did, a number they can check that the agent did not produce. What broke the false consensus above was one model reading the source file instead of the brief.
Saying no must cost less than saying yes. If rejecting means writing a paragraph and yes means one keystroke, you have priced the outcome you will get. Make the reject path as cheap as approve: a two-click reason field, not an essay.
The no must be enforceable and durable. If the override can be silently reverted by cache, default, or the next run, it was never an override.
Two of those three are dials your tooling already ships. Claude Code
has four permission modes: Default asks before any edit, shell command,
or network call; acceptEdits waves edits through; Plan mode
touches no source until you say go; Auto mode runs the lot behind a
classifier, and since v2.1.228 is the starting default on Pro, Max, and
Team. Shift+Tab cycles all four, a dial labeled how much trouble do
you want to get in today.
Set the dial by the door, not by mood. Two-way doors, act then
report: edit a file, create a branch, run the suite. One-way doors, ask
every time: git push --force to a shared branch, any DDL
against production, a DELETE without a WHERE
you have counted first, anything landing in a real customer’s inbox. The
split is not size, it is recovery: a flag defaulted off is a two-way
door, the same flag at 100% is a one-way door. Every prompt you spend on
a two-way door is attention you will not have at 1am when a one-way door
shows up.
airank, 15 August 2026. Two councils, same week, same repo, two shapes of the same failure.
The sharper one: a gate to stop the system from processing domains that do not exist. The cost of not having it was already measured, 495 false domains at $0.03 a lookup, roughly $16 of confident summaries about nothing. The council of six converged fast: verify via DNS, bundle an offline IANA TLD list for speed. Every reviewer green.
Then the adversarial review stage ran, which this workflow refuses to skip, and found the design ate its own override in both directions.
Unblocking was a lie. The air:block --remove command
cleared the flag but not the cached seven-day NXDOMAIN verdict, so the
next lookup re-condemned the domain and re-blocked it. The human’s no
was decorative.
Worth admitting what airank does and does not have. It does have a
pre-flight ask: three artisan commands count the work and refuse to
start until a human answers. The sharpest is
AirTracerQuery.php line 90, which prints the exact number
of real, billed API calls before a dollar moves. All three also take
--yes, which is how a scheduler runs them, so the gate
exists exactly as long as a person is the one typing. Then the durable
half: one line inside unblock() now drops the DNS verdict
so a person’s no outlives the cache.
The bundled TLD file could blacklist the future too: when ICANN adds a TLD, the snapshot goes stale and every domain on it is permanently condemned by a file nobody remembers is there. I shipped a list of what the internet looked like on one Tuesday and treated it as permanent, roughly the shelf life of an AOL 5.0 CD: correct on the day it was pressed, a coaster by the time you needed it.
Six models agreed, and the agreement was real and worthless as evidence: coherent, not correct.
The first council, about the 180-second cap, shows the other half. After the brief got retracted on the record, the chair measured the actual distribution instead of arguing about it. Of 8,853 domain rows, zero resolved between 60 and 180 seconds, and 8,736 took longer than 180. A switch, not a curve.
The third variant is the one that will happen to
you. The commander-in-chief project, a deterministic Godot sim,
documents 51 measured design decisions in DECISIONS.md.
Entry D1 is the tank bail mechanic. The HUD prints
BAIL OUT! %ds, but on default difficulty no player ever
sees it work, because vestless riders get one-shot on the same tick the
shell lands. The file says: “16 of 22 occupied-tank ignitions per the
pre-flight are artillery, so this is the common case.” The
recommendation was a 30 to 45 tick grace window. The recorded resolution
was “do nothing.”
Four of the top five decisions got no sign-off at all. I wrote D1, wrote “do nothing” under it, and shipped the lying HUD anyway. Fifty-one measured decisions, and the review process for the top four was me not typing anything. Silence approved it, which is the hardest version to catch in an audit, because the artifact looks complete.
The loud failure is the human who was not there. Easy to find, easy to fix.
Your approval rate is 98% and you read that as the agent being good. It is at least as likely to mean your reviewer stopped reading in week three. Those two states produce identical dashboards. If you are not measuring reject rate and time-on-review, you cannot tell them apart.
The human reviews the agent’s summary of the agent’s work. That killed round one of the CLI council. Reviewing a summary is proofreading, not oversight.
The override that does not survive the next run. If the human’s no expires and the machine’s yes does not, the human is not in the loop, they are in the transcript.
Do
GROUP BY, a file read directly.--remove bug before shipping.Don’t
Ch. 42 (Your Agent Just Hit Your NAS) is what the agent is allowed to touch. This chapter is who stops it and whether that stop is real. Ch. 41 is how a refusal gets recorded so the next run inherits it. Ch. 60 is the counterweight. Ch. 15 is the upstream version, where a well-formatted plan gets read as work already done.
Thesis is Jeremy’s (“if they can rubber-stamp it, you don’t have HITL”), argument, not citation.
Verified:
EU AI Act Article 14: high-risk systems must be designed so they “can be effectively overseen by natural persons during the period in which they are in use,” including understanding limitations, detecting automation bias, and overriding output. In force 2 December 2027. https://artificialintelligenceact.eu/article/14/
Harvard Business School (2024), 228 evaluators: explanations made reviewers 19 points more likely to align; narrative rationales added 5; automation bias definition. Via TianPan.co, 15 April 2026. https://tianpan.co/blog/2026/04/15/human-in-the-loop-rubber-stamp
Automation bias and workload. NIH/PMC systematic review, 2012. https://pmc.ncbi.nlm.nih.gov/articles/PMC3240751/
Explainability can produce rubber-stamping rather than critical checking. MIT Sloan Management Review, 12 June 2025. https://sloanreview.mit.edu/article/ai-explainability-how-to-avoid-rubber-stamping-recommendations/
Mitchell, Ghosh, Passi, “AI Agents Push Humans Out of the Loop.” arXiv, 24 August 2026. https://arxiv.org/abs/2608.23642
Article 14 “neither acknowledges nor seriously addresses” implementation. Effective Altruism Forum, 31 August 2026. https://forum.effectivealtruism.org/posts/MHAaDyBDpSp2hKfSM/the-eu-s-ai-act-looks-to-implement-human-oversight-the-only
Three months of AI code review replacing human review: cracks at six weeks, juniors stopped learning, code “homogenous but soulless,” “everything appeared to work.” Leena Malhotra, DEV Community, 26 December 2025. https://dev.to/leena_malhotra/i-tried-replacing-human-review-with-ai-heres-where-it-quietly-failed-4jh3
Claude Code permission modes: default, acceptEdits,
plan, auto; auto is the starting default on Pro, Max, and Team from
v2.1.228. Claude Code documentation, retrieved 9 September 2026.
https://code.claude.com/docs/en/permission-modes
Two-way / one-way door lists, quoted to match Ch. 60 so both
chapters use one definition.
~/Projects/aibook/manuscript/60-Dont_Ask_on_Reversible_Work.md
Worked example 1: air CLI council, airank, 15 August 2026. False
180s-cap brief, retracted on record; 8,853 rows, zero between 60 and 180
seconds, 8,736 over 180.
~/Projects/airank/blog/2026-08-15-air-cli-council.md
Worked example 2: domain guard council, airank, 15 August 2026.
495 false domains, ~$16 at $0.03 each; air:block --remove
left the cached NXDOMAIN verdict; stale IANA TLD snapshot.
~/Projects/airank/blog/2026-08-15-domain-guard-council.md
unblock() (line 51) now also forgets the cached DNS
verdict, so a manual unblock is not re-blocked on the next run;
block() at line 39. Read 9 September 2026.
~/Projects/airank/app/Services/Api/DomainBlocklist.php
Worked example 3: commander-in-chief DECISIONS.md,
2026. 51 measured decisions; D1 tank bail; “16 of 22 occupied-tank
ignitions per the pre-flight are artillery”; resolved “do nothing”; four
of the top five got no sign-off.
~/Projects/commander-in-chief/DECISIONS.md
Pre-flight approval gates in airank, read 9 September 2026:
AirTracerQuery.php line 90
(confirm("Proceed with {$totalCalls} real, billed API call(s)?")),
AirChatgptCollect.php line 174 (live browser sessions),
AirCollect.php line 113 (dispatch). All three are bypassed
by --yes.
~/Projects/airank/app/Console/Commands/
What I could not verify:
CliAuthPageController.php approve() line 88 is
CLI token pairing, not that.