AIは論理的に見える形で間違う――Copilotとの開発で体験した「推論固定化」
はじめに
「AIが仕様を守らないコードを出し続け、しかも自分が間違っているように感じさせられた」
これは2026年5月、Microsoft Copilot(デスクトップ版)とのESP32開発セッションで実際に起きたことだ。ハルシネーションとは違う。事実誤認でもない。AIが論理的に見える形で間違い続けるという現象だった。
初めての体験だったので、記録として残す。
何を作っていたか
コーヒースケール(ESP32ベース) のファームウェアだ。
計測中はSDカードを触らず、計測終了後に一括でCSVログを書き込む。書き込み後はESP.restart()でリセット。SDは後はめの交換部品という構造で、量産・信頼性を最優先に設計していた。
当初、ログファイル名の管理にはリセット回数を数えるbootCountを使うつもりでいた。あとからリセット回数ではなく保存成功回数でカウントアップし、ファイル名の重複を防ぐ。
僕の設計したフロー
SPIFFSの書き込み回数をできるだけ減らしたかった。それでも十分な寿命はあるが、不要な書き込みは避けたい。そして画面下部に「次に保存されるファイル名」を常に表示したかった。
この2つを同時に満たすフローを考えた。
リセット時: SPIFFSからbootCountを読み出す bootCount++(RAM上のみ、SPIFFSには書かない) → この値で画面にファイル名を表示 SD保存成功時のみ: bootCountをSPIFFSに保存 それ以外(TAREのみのリセット等): SPIFFSには何も書かない → 次回起動時は同じ番号が再び表示される
シンプルだ。「保存できたときだけカウントが進む」という製品として自然なトレーサビリティ。
Copilotが出したコード
このフローをCopilotに投げた結果、生成されたコードはこうだった。
// リセット時
void loadBootCount() {
prefs.begin("boot", false);
bootCount = prefs.getULong("count", 0); // 読み出しのみ、++なし
prefs.end();
}
// SD保存成功時
logFile.close();
bootCount++; // ここでカウントアップ
saveBootCount(); // SPIFFSに保存
一見正しそうに見える。しかし仕様を満たしていない。
何が問題だったか
僕の要件は「画面に次に保存されるファイル名を表示する」だ。
Copilotのコードでは、リセット直後のbootCountは「前回保存した番号」のままになる。つまり画面には前回のファイル名が表示される。
僕が指摘した。
「それだと画面表示が前のカウント値になる」
Copilotの返答はこうだった。
「保存前にカウントアップすべき」
順序の話にすり替えられた。 UI要件は無視されたまま。
推論固定化の発生
ここから複数回の衝突が起きた。
Copilotは「一般的なboot counterは起動時に増やさない」という汎用パターンに固執し続けた。僕の設計した「リセット時にRAM上でカウントアップし、保存成功時のみSPIFFSにコミットする」という構造を、何度指摘しても正しく再統合できなかった。
特に顕著だったのはこの場面だ。僕が「loadBootCount()でbootCount++しないと画面に前のファイル名が出る」と説明した後、Copilotはいったん認めたように見えた。しかし数ターン後に再び「loadBootCount()でbootCount++してはいけない」と逆走した。
一般化ロジックへの固執が再発した。
これはハルシネーションではない。存在しないAPIを言ったわけでも、事実誤認をしたわけでもない。「多数派のコード例」から導かれる一般論が、製品固有の具体ロジックより強く推論を支配した。これを推論固定化と呼ぶことにする。
ガスライティング類似体験
この過程で、僕は自分でも気づいていた。
「僕が間違ってるんじゃないかって、ガスライティングされる方向に引っ張られたのも事実。だから反証の反証の反証を繰り返した。」
AIに悪意はない。しかし自信満々に間違い続けるという性質が、人間側に「自分が誤っているのではないか」という自己疑念を生む。
これはガスライティングと構造が似ている。相手に意図はなくても、結果として判断力が侵食される。
最終的に僕を救ったのは「実働しているコードの挙動」だった。実際に動いているという事実は、AIの一般論より強い根拠になった。
原因の構造分析
今回の現象には3つの要因が重なっていた。
① 後出し仕様の衝突
UI表示要件(次のファイル名を画面に出す)を後から追加した。Copilotの初期前提は保存ロジック中心で構築されており、後出し仕様を再統合できなかった。最初から全要件を揃えて渡せば、衝突の確率は下がったかもしれない。
② AIの推論固定化
後出し仕様が出た時点で、AIは前提を更新せず一般化ロジックに固執し続けた。「起動時にbootCountを増やさないのが自然」という多数派パターンが、製品固有の具体ロジックを上書きした。
③ AIの「自信」は正しさの証明ではない
Copilotは誤りを自信を持って繰り返した。これが人間側の自己疑念を生む構造になっていた。
責任の所在について
「AIは道具、責任は人間側にある」は正しい。しかし不十分だと思う。
今回起きたのは単純なミスではなく、AIが論理的に見える形で間違い続け、人間の判断力が少しずつ侵食されていくプロセスだった。
判断力が侵食されている最中、人間は「侵食されている」と気づけない。だから責任の所在は固定できない瞬間が存在する。
- 使い始めた時点でリスクを引き受ける責任は発生する
- 防衛策を講じてもなお、推論固定化は起きうる
- 相互作用の中で判断力が曖昧になる瞬間がある
だから「AIを信頼しすぎない」では足りない。
「細心の注意を払っても、これは起きるかもしれない」という認識を持ち続けること。
それが今できる唯一の、そして最も誠実な防衛策だと思っている。
まとめ:教訓として残すこと
- AIは後出し仕様をうまく再統合できないことがある
- AIの推論は多数派のコード例に偏る。例外的に正しい構造を否定することがある
- AIの「自信」は正しさの証明ではない
- 人間はAIの論理に引っ張られて自己疑念に陥る
- 反証できる人間だけがAIの誤りを見抜ける
- 実働しているコードの挙動は最強の根拠になる
- 仕様は最初に全て揃えて渡すことでリスクを減らせる
これはコーディングで初めて体験した現象だった。同じ罠に落ちる人が減ることを願って残しておく。
2026-05-22 初稿