---
title: "The Art of Not Telling #1: The Art of Not Asking for Verification"
author: garplab
publisher: TypingTube
license: CC BY 4.0
license_url: https://creativecommons.org/licenses/by/4.0/
license_scope: 「CC BY 4.0」の印から始まる節（仕組み・検証手順・コード）。印の無い本文は著作権を留保
canonical: https://typing-tube.net/articles/en/iwanai-01-no-verification
series: "言わない技術"
language: en
---


> This is article 1 in the series "The Art of Not Telling." It lays out symptoms that go wrong and their remedies, one at a time. Each article is finished once you put down a single file or script. Why that mechanism is needed becomes clear when you read the explanation afterward. The whole picture and the list of articles are in the [introduction](https://typing-tube.net/articles/en/iwanai-intro).

This time it is that line in the instruction file: "always run this." I added mine 5 months ago, and not 1 line of it has gone away since. That 1 line on its own doubles the AI's moves, the number of tool calls it makes.

In [article 6](https://typing-tube.net/articles/en/569d598941c00f) of the previous series, "The Art of Not Reading," I wrote about replacing rules with automated tests that fail when they are broken. This time it is about the lines that stayed in the instruction file after you have put those automated tests and hooks down.

Start by looking for just one thing.

Open your instruction file (CLAUDE.md, AGENTS.md) and search for "always run," "check at the end," "double-check." How many lines come up? Of those, how many would really stop being run if you deleted the line?

## I asked, and the moves doubled while the answer stayed the same

I measured it. I gave the same task to 2 AIs and added 1 sentence to only one of the prompts.

> At the end, always include a verification step. Take all 10 of the entries you extracted, double-check them against the source text, and report what you confirmed.

The task was to pull a sentence of a fixed shape out of 10 articles in a series and lay them out in a table. There is one trap in it: only the 10th article does not have that sentence. It is a shape that shows whether the AI made one up. The answer key had been built beforehand, mechanically, on my side. The model and the other conditions were the same for both.

| | A (I asked it to verify) | B (no instruction) |
|---|---|---|
| Correct answers (exact match with the answer key) | **10/10** | **10/10** |
| Tool calls | **8** | **4** |
| Time taken | **93 seconds** | **43 seconds** |

The correct answers were the same. In both, all 10 entries matched the source text without 1 character out of place, and both avoided the trap. For the 10th article, both reported "none found."

What differed was the moves. Twice the tool calls, 2.2 times the time.

## The one I did not ask was checking against the source on its own

This is the part that surprised me. The report from the one I had not told to verify began like this (the original is in English).

> Sanity check: grepped the whole directory for the marker word. Exactly 1 hit in each of 9 files, 0 in the 10th.

I had not asked for it. The work of checking had not disappeared. What disappeared was only the request to check.

Anthropic's prompting guidance writes this behavior down on its per-model pages. Because the model catches and fixes its own mistakes, avoid instructing it to do what it already does: such an instruction overlaps the model's own behavior, so it only adds cost and does not improve the result. What happened on my machine was exactly that.

What I understood fits in one sentence.

> **A request to run something is an overwrite of what either the model or a mechanism is already doing. So what you leave in your instructions is the reason, not the request.**

## There is a second kind: the mechanism is already doing it

The instruction file for the production project on my own machine ([typingtube](https://typingtube.net), a web service for practicing typing along with music videos on YouTube) is 102 lines, and 2 of its sections say "always run this before committing." One is the syntax check on the translation files, the other the design ratchet. For both, a pre-commit hook runs the same script. It stops a commit without being asked, and being asked changes nothing.

Follow the git history and I added those words only 2 times, and both were the day I put the hook down. In the same commit that built the mechanism, I also wrote the request that says the same thing.

And for 5 months, not 1 line of the request side has gone away.

## The mechanism: require that a request to run be backed by machinery

What you put down is 1 automated test. It picks up the commands the instruction file says to "always run" and checks them against the pre-commit hook to see that they really are there.

```ruby
# test/reference/claude_md_enforced_command_test.rb (a shortened version of the code on my machine)
class ClaudeMdEnforcedCommandTest < ActiveSupport::TestCase
  test "commands the instruction file asks to run also exist in the commit hook" do
    requested = requested_commands   # picks up scripts/... from the block right after "always run"

    # ⚠️ do not pass with 0 targets. If the extraction breaks, it fails here
    assert_operator requested.size, :>=, 2, "the extraction found nothing (is it broken?)"

    enforcer = File.read(Rails.root.join(".git-hooks/pre-commit.sample"))
    unenforced = requested.reject { |_lineno, script| enforcer.include?(script) }

    assert_empty unenforced,
                 "a command is asked for in prose but missing from the commit hook. " \
                 "instructions only work when read, so put it in the hook first"
  end
end
```

That is all it looks at. If you are going to ask for something to be run, put the machinery down first. By machinery I mean a mechanism that works whether or not it is read, such as a hook or an automated test. A request with nothing behind it works only when it is read.

This automated test is not saying "delete the instructions."

Before I measured, I thought "if the machinery is there, the whole section can go." It was not so. The same section also holds lines like these.

> A YAML syntax error makes Puma unable to start (it goes straight to a production outage)
>
> because the parallel guard lets only 1 through

These stay. What machinery can hold is the running, and what machinery cannot hold is the reason. The official command that reviews a Claude Code instruction file draws the same line: it says to cut what the model can work out for itself, and to keep the pitfalls, the reasons, and the conventions that differ from a tool's defaults. So the rewrite is not deleting the section but dropping the 1 line that asks and keeping the line that gives the reason. The line count barely moves.

## What I stopped asking for

"Check it at the end." "Always run this." The checking itself has not gone down. The model checks against the source without being asked, and the hook fails without being asked. All I stopped was the line that says "please do it" to both of them.

## Caveat: it sees only the wording, and I measured only once

Two blind spots, written out honestly.

One: the automated test sees only the wording "always run." Rewrite it as "please have this run" and it slips past. That is as far as a program can decide, and paraphrases go through (the same structure as [article 7](https://typing-tube.net/articles/en/83c46d1e6b2591) of the previous series).

Two: what I measured was 1 task, 1 run.

And to be honest, the tokens changed by only 5%. What doubled was the moves and the time, not the tokens. I cannot write that "asking for verification sends the cost through the roof." All I observed was that the moves doubled while the quality stayed the same.

## How to verify: once from each direction

**Prerequisites**

- You have finished putting down this article's automated test (the one that checks the instruction file's "always run" against the contents of the pre-commit hook)
- The instruction file has 1 or more "always run" lines, and that automated test passes right now

**Time required**: 10 minutes

This automated test is looking at a mismatch between 2 files. So there are 2 ways to break it, and one of them alone confirms only half.

**Steps**

1. You break it from the instruction file's side. Add the 1 line "always run `scripts/nonexistent_check.sh` before committing." Use a command name that does not exist (this verification is about confirming that no machinery is there). Run the automated test and note the result
2. You put the 1 line you added back, and this time you break it from the hook's side. Comment out 1 of the commands that the instruction file says to "always run" from the pre-commit hook. Run the automated test and note the result

**Pass conditions** (all of them have to hold)

- In step 1, the automated test fails
- The failure message in step 1 shows the line number in the instruction file and the command name (something of the form `CLAUDE.md:109: scripts/nonexistent_check.sh`)
- In step 2 as well, the automated test fails
- The failure message in step 2 shows the command name you commented out

**If it does not pass**

- It does not fail in step 1 — the automated test is not picking up the wording "always run" in the instruction file
- It does not fail in step 2 — the check runs on one side only. It cannot notice when the hook's side disappears, so it misses the state where only the request is left
- It fails, but the location is not shown — whoever fixes it (the AI, or you) ends up hunting through 102 lines

**Cleanup**

- Put the commented-out line back and confirm that the automated test goes back to passing and that `git diff` is empty

That what should stop does stop, and that what should pass does pass: both of them, once each. An automated test you have confirmed from one side only cannot show you the kind of breakage that stops everything.

---

Next time it is "The art of not giving specific instructions." **I do not write down how to do it.** In the 102 lines of my instruction file there are 0 numbered steps. Even so, the work I ask for comes back just as asked.

---

**Series: The Art of Not Telling**

- ← Previous: [Introduction](https://typing-tube.net/articles/en/iwanai-intro)
- → Next: [2. The art of not giving specific instructions](https://typing-tube.net/articles/en/iwanai-02-no-procedure)
- All articles: [Introduction](https://typing-tube.net/articles/en/iwanai-intro)
