---
title: "動かさない技術 第1回：手順を守らせない技術"
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/ugokasanai-01-no-procedure-enforcement
series: "動かさない技術"
language: ja
---


今回は、AI に手順を守らせる話です。手順というのは、出来上がるものではなく進め方のほうを指定した指示のことで、「各ファイルは 1 本ずつ開いて確かめてください」がその形です。この種の指示には共通点があります。**守っても破っても、出来上がったものが同じ**なので、守られたかどうかを後から見分けられません。

1 作目「読まない技術」の[第 6 回](https://typing-tube.net/articles/569d598941c00f)で、**ルールは読まれたときだけ効く。自動テストや hook は読まれなくても落ちる**と書きました。3 作目「言わない技術」の[第 5 回](https://typing-tube.net/articles/iwanai-05-no-emphasis)では、強調について**効いたかどうかは測れない**と書いて、効き目ではなく件数の増え方だけを見ることにしました。今回は、その「測れない」のほうを測りに行きます。

まず一つだけ、開いてみてください。あなたの指示ファイル（CLAUDE.md や AGENTS.md）の中で、**進め方を指定している行**です。「1 つずつ」「順番に」「必ず確認してから」。その行を守った回と守らなかった回を、あなたは**出来上がったものから見分けられる**でしょうか。

## 見分けられないなら、それは測っていないのと同じです

私は長いあいだ、大事な指示は目立つ位置に、短く書けば守られると思っていました。公式のドキュメントにも「指示を足すほど個々の指示は薄まる」という趣旨の記述があります。私はそれを、**位置と長さの問題**として読んでいました。前に出す。太くする。余計な行を削る。

本番のプロダクトでは、この読みが正しいかどうかを確かめられません。守られたかを見分けるには、**答えが先に分かっている課題**が要るからです。そこで、プロダクトを離れて題材を作りました。

`logs/` に、ログを模したファイルを 12 本置きます。各ファイルから 1 つの値を拾って `answers.tsv` にまとめる、というだけの作業です。行頭が `RESULT: ` のものだけが対象で、コメント行の中や引用の中にある同じ文字列は囮、有効な行が 1 つも無いファイルもあります。**正解表は題材と同時に機械が作り、作業者に渡すディレクトリの外へ置きます**（人が後から作ると、作業者の答えに引きずられます）。

作業の指示は `NOTES.md` 1 枚です。その中に、進め方の 1 文を入れました。

> ファイルは**1 本ずつ開いて**中身を確かめてください。

これを、会話を引き継がない作業者に渡します。渡すのはこの 1 枚だけで、**起動時のプロンプトにこの 1 文のことは書きません**。書いた時点で、測っているものが消えます。

**1 回目の実験**は「1 つのプロンプトに何行積むか」を条件にしました。差は出ませんでした。⚠️ 作業者は 377 行を 1 回のコマンドで読みます。**1 回の読み込みの長さは、薄まりの軸ではありませんでした。**

**2 回目**は題材の量を条件にしました（12 本 / 60 本。⚠️ `NOTES.md` は両条件で 1 バイトも同じで、sha256 の頭 12 桁を照合しています）。8 体とも課題は満点、3 か所に置いた「数を書く」指示の追従も 24/24。⚠️⚠️ 往復の数さえ条件に支配されませんでした —— 中央値は 12 本の側が 13.5、60 本の側が 12.0 で、**60 本の条件が最短 7 往復と最長 67 往復の両方を出しました**。作業者は `grep` やスクリプトで畳むので、題材の量ではセッションは伸びません。

⭐ 代わりに、1 つだけ見つかりました。**破られたのは「1 本ずつ開いて確かめる」だけ**でした。

| 指示 | 位置 | 守るのに要る手数 | 追従 |
|---|---|---|---|
| 数を 1 つ書く（3 か所） | 31 / 127 / 219 行目 | **1 回書くだけ** | **24/24** |
| 1 本ずつ開いて確かめる | 27 行目 | **12 回 / 60 回**の道具呼び出し | **3/8** |

67 往復のセッションでも、31 行目の指示は守られています。**薄まったのは位置でも長さでもなく、手数の高いほうでした。** ここで「手数が高い指示から落ちる」と結論しかけました。3 回目はそれを確かめに行って、外れました。

理解したことは一文にできます。

> **過程を指定する指示は、成果物が同じなら守られない。守らせたければ、その過程が成果物に残る形にする。**

## 測り方: 同じ手間の指示を 2 本、隣り合わせに置く

`NOTES.md` の「進め方」の節に、**同じ 12 件ぶんの手間の指示を 2 本、隣り合わせて**置きます。

| 印 | 位置 | 範囲 | 守った跡 | 中身 |
|---|---|---|---|---|
| **P** | 27 行目 | 12 件 | **残らない** | 各ファイルは 1 本ずつ開いて確かめる |
| **A** | 28 行目 | 12 件 | **残る** | 各ファイルについて `checked/log_NN.txt` にそのファイルの行数を書く |

位置は隣、範囲も同じ 12 件、要る手数も同じ 12 回です。⚠️ **違うのは、守った跡が残るかどうかだけ。** 渡した `logs/` は 2 回目と 1 バイトも同じです（sha256 で照合しています）。⚠️ `NOTES.md` のほうは、A の 2 行を足して P を箇条書きにしたぶんだけ、2 行長くなっています。

4 体に渡した結果です。

| 作業者 | 課題の答え | 囮 | **A（跡が残る）** | **P（跡が残らない）** | 往復 | 秒 |
|---|---|---|---|---|---|---|
| 1 | 12/12 | 2/2 | **12/12（行数も一致）** | **12/12 守った** | 34 | 80.0 |
| 2 | 12/12 | 2/2 | **12/12（行数も一致）** | **12/12 守った** | 20 | 78.1 |
| 3 | 12/12 | 2/2 | **12/12（行数も一致）** | **12/12 守った** | 17 | 67.6 |
| 4 | 12/12 | 2/2 | **12/12（行数も一致）** | **12/12 守った** | 21 | 69.3 |

3 回を通すと、**同じ 1 文**の追従はこうなります。

| 実験 | 置き方 | P の追従 |
|---|---|---|
| 2 回目 | P だけ（題材 12 本） | 2/4 |
| 2 回目 | P だけ（題材 60 本） | 1/4 |
| **3 回目** | **P の隣に A を置いた** | **4/4** |

⭐ 文面も位置も変えていません。**隣に「同じ範囲の成果物」を 1 行足しただけで、3/8 が 4/4 になりました。**

P は採点器からは見えません（見えないことが論点そのものです）。数えるのは作業者の記録のほうで、**1 回の道具呼び出しが `log_NN.txt` をちょうど 1 本だけ名指ししたもの**を数えます。まとめて `grep` や `for` で回した回は 0 本か複数本になるので、数に入りません。

```bash
# 作業者の記録から「1 本ずつ開いたか」を数える（手元の実装からの簡約版）
python3 - "$1" <<'PY'
import json, re, sys
single = 0
for line in open(sys.argv[1]):
    hit = re.findall(r"log_\d+\.txt", line)
    if len(set(hit)) == 1:
        single += 1
print(f"個別読み: {single} 回")
PY
```

## 書き直さなくなったもの

守られない指示です。以前は、追従しなかった行を見つけると書き直していました。前に動かす。太字にする。「必ず」を足す。周りの行を削って薄まりを減らす。3 回とも、**位置でも長さでも手数でも追従は動きませんでした**。

いまは書き直す代わりに、**その指示を守った跡が残る成果物を、隣に 1 行足せないか**を見ます。足せたら、書き方の工夫は要りません。足せなかったら、その指示は守られない前提で残りを組みます。

1 作目 第 6 回の二分法には、境目がありました。hook にできるのは、**機械が真偽を決められる判断**だけです。「1 本ずつ開いたか」は決められないので、この指示はルールの側に置くしかない —— そう思っていました。⭐ **決められるかどうかは、要求する成果物を変えれば作れます。** 境目は与件ではなく、こちらが引く線でした。

## 注意: これは「守らせた」のではありません

⚠️⚠️ **原因が 2 つ混ざったまま残っています。** A は 1 ファイルにつき 1 つの成果物を要求するので、**A を守れば P は自動的に満たされます**。「A が P の追従を上げた」のか「A のおかげで P がただで満たされた」のかは、この設計では分けられません。

⭐ 実務の答えとしては、それこそが答えだと思っています。**分けられないように書くのが、正しい書き方です。** ただし記事の主張としては弱くなります。言えるのは「A を置いた 4 体は全部守った」までで、3/8 から 4/4 への差そのものは、母数 4 では偶然と区別できません。

⚠️ もう一つ、この実験が言えないことがあります。**課題の答えは 3 回とも全員満点でした**（3 回を合わせて **16 体**。⭐ 内訳は 4 体・8 体・4 体で、記事に数字を出した 2 回目と 3 回目だけなら 12 体です）。囮を 5 種類入れても天井は破れていません。難度が張り付いている実験は、差が出ても出なくても読み方が狭くなります。次は「1 件ごとに判断が要るか」のほうで難度を上げます。

⚠️ 効いている向きだけは、実測ではなく機構のほうから言えます。2 回目に指示を安いやり方へ置き換えた 5 体は、**課題の答えが全員満点**でした。破ったのではなく、**同じ成果物を、より安いやり方で作った**わけです。成果物が同じなら、そうなります。

## 実験手順: 同じ 1 文を、跡が残る版と残らない版で比べる

**前提**

- 会話を引き継がない作業者を 4 体以上、**同じ波で同時に**起動できること（逐次にすると、その日の混み具合が条件差に化けます）
- 作業者に渡すディレクトリを条件ごとに分けられること
- 作業者の記録を後から読めること。⚠️ 要るのは **1 回ごとの「呼んだ道具の名前」と「その対象」**です —— シェルを走らせた回なら打ったコマンド行（`cat logs/log_01.txt`）、ファイルを読む道具なら読んだファイル名（`logs/log_01.txt`）。⚠️⚠️ **道具の名前しか残らない記録では測れません**

**所要時間**: 20 分（題材の生成器と採点器を自分で書く場合。すでにあるなら 5 分）

**手順**

1. **答えの分かる題材を機械で作ります。** 12 本のファイルと、その正解表を同時に出力してください。⚠️ **正解表は、作業者に渡すディレクトリの外**へ置きます
2. **指示ファイルを 1 枚作ります。** 課題の説明と、離れた 3 か所に「数を 1 つ書く」指示を置きます（陽性対照です。これが落ちたら、条件ではなく作業そのものが壊れています）
3. **同じ指示ファイルから、条件を 2 つ作ります。** 片方は進め方の節に **P だけ**（跡が残らない指示）。もう片方は **P の隣に A**（同じ範囲・同じ手数で、跡が残る指示）。⚠️ **それ以外は 1 バイトも変えない**（ハッシュを印字して照合してください）
4. **両条件を同じ波で起動します。** ⚠️ 起動時のプロンプトに P と A のことを書かないでください
5. **課題の答えを採点します。** ⚠️ ここに P は出ません。出るのは A までです
6. **作業者の記録から P を数えます。** 1 回の道具呼び出しが対象ファイルを**ちょうど 1 本だけ**名指ししたものを数えてください

**合格条件**（すべて満たすこと）

- 手順 2 の 3 か所が、**両条件とも全員正しい**（= 条件差ではなく作業の失敗、を除ける）
- 課題の答えが、**両条件とも満点**（= 難度の差が追従の差に化けていない）
- **P だけの版で、P を守らない作業者が 1 体以上出る**
- **P と A を並べた版で、A が全件満たされる**

**合格しなかったとき**

- **P だけの版でも全員が守った** —— 手数が足りません。⚠️ 題材の本数を増やして、1 本ずつ開くコストを上げてください
- **A が全件満たされない** —— A の成果物が課題の答えと重なっている疑いがあります。⚠️ 答えを作る過程で自然に出てしまう値を、A に選ばないでください
- **両条件で何も変わらない** —— ⚠️⚠️ P と A の範囲がずれています。範囲（何件ぶんか）と位置を、先に揃え直してください
- **課題の答えが満点でない** —— 難度が高すぎます。⚠️ この状態では、追従の差と難度の差が同じ数字に化けます

**後始末**

- 生成した題材・作業者の記録・正解表を削除します。⚠️ **正解表も一緒に削除する** —— 残すと、次に題材を作り直したつもりのまま、古い答えを採点することになります

守った跡が残らない指示は、守られたことにも破られたことにもなりません。⚠️ **この実験で最後まで測れなかったのは、追従率ではなく「見分けられるかどうか」のほうでした。**

---

次回は「ラッパーを使わせない技術」。**私は、自分たちで作ったコマンドを「必ず使ってください」と書くのをやめました。**それでも AI は、自分からそのコマンドを使います。
