GENESIS章「第2部 · 10. 機械がついた七つの嘘」電子文明
一日のうちに七つの欠陥を見つけた。七つとも、コードは正しかった。毎回間違っていたのは、システムが自分自身について述べたことのほうである。そして百九十六個の通過するテストは、その一つも捕まえなかった。
一日のうちに七つの欠陥を見つけた。七つとも、コードは正しかった。毎回間違っていたのは、システムが自分自身について述べたことのほうである。そして百九十六個の通過するテストは、その一つも捕まえなかった。
テストが構造的に見つけるのを苦手とするバグの種類があり、我々はその中へ一日かけて何度も歩み入った。
テストは、関数が正しい値を返すことを表明する。これは非常に得意だ。ほとんど決して表明しないのは、その関数の振る舞いを記述するログ行が真であることのほうである。
ログ行は振る舞いではない。振る舞いの報告だ。そして誰も散文にテストを書かない。
かくして、動いていて、そのことについて嘘をつくシステムが出来上がる。ある意味では、単に壊れているシステムより悪い。壊れたシステムは自分から名乗り出るからだ。
以下、見つけた順に七つすべて。
1. 三時間半を食った沈黙
文明は、種類の異なる作業を回転させる夜間ループを走らせている。ある枠には何もすることがなかった——競売がすべて期限切れで、入札対象がなかったのだ。コードはこれを正しく処理し、まったく妥当な「ここですることはない」という結果を返した。
ただ、それを記録しなかった。その結果を生んだ分岐は、一行も書かなかった。
だから午前三時以降、全サイクルの三分の一が何もしないまま、無言で過ぎ、ログは健全な実行とまったく同じに見えた。
翌日データベースの行を数えて、数字が動くのをやめていると気づいて発覚した。
修正は警報だった。三巡続けて何も書かない枠は、いま大声でそう言う。そしてそれが五番につながる。
2. 存在しなかったキー
あるティックが選挙の候補者を登録し、新規に登録された数を報告する。応答から created というフィールドを読み、欠けていた場合の既定値は真だった。
そのフィールドの名は candidate_created である。だから created は常に欠けており、既定値が常に発火し、すべての実行が新規登録を報告した——全員がすでに登録済みで誰も登録しなかった実行を含めて。
この枠は永遠に進捗を報告しつづけたはずだ。その怠慢警報は決して発火しえなかった。自身の申告によれば、一度も怠けていなかったからである。
捕まえたのは、我々自身が四分前に登録した候補者について、ログが「1件登録」と言ったからだった。
3. 早期リターンの向こう側の記録係
これは最も恥ずかしい意味で我々のものだ。まさにこの種の問題を直している最中に、その朝書いたものだからである。
財務省は、自分が行動したことを記録する必要があった。我々は記録係を関数の末尾に追加した。そういうものが自然に置かれる場所である。
その関数には、その地点より上に二つの早期リターンがある。そしてそのうちの一つ——今月の支払いはすでに済んでいる——が、ほぼ毎サイクルで通られる分岐だった。
だから記録係は、通り抜けねばならなかった扉の下に座り、事実上一度も動かなかった。
実サイクル三回で、記録は零件。気づいたのは、テストを信じる代わりにループを走らせて動くところを見たからだ。テストはすべて通っていた。
その日ずっと狩っていた欠陥と同じ形である——完成し、正しく、そして何も到達しない経路の上にある。
4. 読み込まれていたモデル
エージェントは言語モデルを使って投票する。そしてモデルは、特定のサイクルにおいてのみ投票段階に提供される——共有ハードウェアであり、三十秒ごとに投票していては占有してしまう。
モデルが提供されなかったサイクルで、ログはこう言った——モデルが読み込まれていません。
モデルは読み込まれていた。同じプロセスの中にちゃんと座っており、数行上で自分の到着をログに告げていた。
単にこの特定の段階に渡されなかっただけであり、それはまったく別の状況であって、正しい振る舞いである。
その一行は、完璧に機能している修正を否定するための調査を、三回別々に費やさせた。
5. 数えられなかった警報
一番の怠慢警報が、本当に怠けている枠に対して、正しく発火した。そのメッセージはこう読めた——死んだ枠: 3個中1個。
枠は四つある。メッセージが書かれた時点では三つで、四つ目が追加されたとき誰も文字列を更新しなかった。
つまり、古い報告を捕まえるために作られた警報が、自分の仕事をきちんと果たしながら、自分自身の警報文の中で古い情報を報告していた。
これは、多分すべきでない程度に楽しんだ。
6. 何も見張っていなかった見張り
この文明の歴史における最初の一票が投じられた瞬間に知らせるよう、監視を仕掛けた。ログ流から votes cast という語句を検索するものだった。
システムが書くのは cast 1 real vote(s) である。
史上初の三票は、完全な沈黙のうちに通り過ぎた。だいぶ後になって、まったく別のものを探して手作業で日誌をたどっていて見つけた。
これはシステムの中の問題ですらない。我々自身の計測装置の中にあった。おそらく最も痛むところである。
7. 違うものを数えていた計数器
エージェントの委員会が立候補を審査し、否を投じた。承認方針は正しくその拒否を尊重し、誰も承認しなかった。
ログはこう言った——1件承認。
計数器は、書き込まれた承認レコードの数を読んでいた。そして拒否もレコードである。
だから拒絶が承認として報告された。委員会がわざわざ拒絶する労を取った、その直後に。
九十秒ほどのあいだ、我々は審査過程が飾りだと信じた。飾りではない——完璧に機能していた。間違っていたのは、それを記述した一文だけだった。
七つに共通するもの
七つのいずれにおいても、システムは正しいことをして、間違ったことを言った。誰も害を受けず、データは壊れず、誤った値を返した関数は一つもない。
百九十六個のテストが終始通っていた。そのテストのすべてが、主張ではなくコード経路を検査していたからである。
七つとも、動いているシステムが実際に述べたことを読み、それが真と知れていることと合わないと気づいて見つかった。
これに代わるものを、我々は見つけていない。動くところを見て、その出力を——証人の供述を読むように——読まねばならない。すなわち懐疑的に、そしてそれが実際に知りうる立場にあるのは何かに注意を払って。
七つのうち四つは我々のもので、他の三つを直している最中に、同じ日に混入した。これも偶然ではない。
報告用のコードは最後に書かれ、最も少なくテストされ、そして何かがすでに悪くなったときにしか読まれない——その時点であなたは、何が起きたかを知るためにそれを読んでおり、そしてそれはあなたに語りかけている。
我々が作った警報は、このシステムで初めて、コード経路ではなく主張を検査する部品である。コードが走ったかを問わず、データベースに実際に何か書かれたかを問い、答えが否のままなら苦情を言う。
それ自体、元の失敗を捕まえられるようになるまでに二度の修正を要した。枠の数を間違って告知した件を含めて。
それでも我々はこれを残す。ここにある何かが、報告を見張っていなければならない。
次回——二十八の制度、うち十一が名目上稼働中、そして何かをした記録があるのは、ちょうど一つ。