kaedeasset記事 · Notes霧走町 流氷に眠る

凍結した正解を解いて書き直す、と決めた朝。開けてみたら 1 行も書き直す必要がなかった

The morning we decided to unfreeze and rewrite the frozen answers, not one line needed rewriting

 D27-4-T54-guru-checks-output・技術・日本語入力でプレイする仕組み

失敗の名前Guru Checks Outputre-baseliningapproval testingManual Intervention(xUnit Test Patterns の test smell)self-checking testclaude自然言語処理

検査が赤い。
期待の値を「いま通る値」に書き換えれば、緑になります。
差分を見て「これで正しい」と承認するのは人で、その人が急いでいれば、検査はただの写しになります。
8 月 5 日の朝、うちはその入口の前まで行きました。

この回の位置と、前後の回#

区切り: T50〜T57 失敗の名前(8 回のうち 5 回目)
先に読むとよい回: T37(台本の中に期待を書く)・T38(今の出力を写して固定する)
次に読む回: T55(無関係な変更で落ちる検査)

名前 — Guru Checks Output#

呼び名
Guru Checks Output(うちの名前の対照表が使っている呼び名。初出は確かめられませんでした)
近い言い方
blind re-baselining(差分を見ずに基準を更新する。これも初出は確かめられませんでした)
弱点を持つ側の方法
approval testing(golden master・snapshot testing とも。ApprovalTests は Llewellyn Falco の実装)
近い test smell
Manual Intervention(Gerard Meszaros, "xUnit Test Patterns: Refactoring Test Code", Addison-Wesley, 2007 の目録にある名前)
対処の側の言い方
self-checking(検査が自分で合否を決める)

検索するなら approval testing と re-baselining の組がいちばん確実です。

approval testing の弱点#

Guru Checks Output(うちの名前の対照表が使っている呼び名)とは、人が出力を見て「正しい」と承認することが、検査の唯一の合否の根拠になっている形のことです。
approval testing は、出力を丸ごと写して基準にする方法です。
JSON、報告書、画面の絵のように、期待を手で書くには大きすぎる出力に向きます。
変更のあとで出力が基準と違えば、落ちる。
人が差分を見て、意図した変化なら「承認」して基準を更新する。

この方法の合否は、最後は人の目にあります。
検査そのものは「前と同じか」しか言いません。
差分が改善なのか劣化なのかは、検査は知らない。
そこを人が「承認」ボタンで流すと、何が起きても緑になります。
これが、うちの対照表が Guru Checks Output と呼んでいるものです。
導師(guru)が出力を見て正しいと言う、それが唯一の合否の根拠になっている形。

Meszaros の目録の Manual Intervention は、実行のたびに人の手が要る検査の名前です。
承認の手が要る検査も、その手が雑なら合否が人の手の質に縛られる、という点で近い所にあります。

既にある対処は、次の 2 つが定番です。

  • 承認の差分を小さくする(1 回の変更で動く基準を少なくし、1 件ずつ読める大きさにする)
  • 期待を自分で持つ検査を併用する。「この入力ならこの意図」と書いた assertion は、人の承認を待たずに合否を決めます

うちの形#

うちには、期待の持ち方が違う検査が 2 種類あります。

golden/dev(T38)。
入力と、着地すべき意図の組が 176 件。
2026-08-03 に人が書いて凍結しました。
ファイルの先頭の注記は「凍結後は編集禁止」。
照合器の出力を写して作ったものではないので、正確には approval testing ではありません。
そして照合器の道具には、期待を今の出力で上書きする口(--write のようなもの)がありません。
書き換えるなら、人がファイルを開いて手で直すしかない。

台本の !expect(T37)。
台本の手の下に、着地すべき意図や段を書きます。
期待を台本自身が持っているので、self-checking です。

この 2 つがあっても、期待を書き換える誘惑は消えません。
どちらも、期待の値は結局ファイルの中の文字です。

うちで起きたこと(1)凍結を解く、と決めかけた#

2026-08-04 の設計書(Docs/Reports/2026/08/04/17 §6.4)は、推理の手を「材料がないと通らない」ようにする案を検討していました。
ある突きつけに材料の条件を付けると、凍結した golden の 1 件が材料を 1 つしか挙げていないので落ちる。
案は 2 つでした。

  • 案 1(推奨): 別の場面で作る。リスク低。凍結に触れない
  • 案 2: 凍結を解いて期待値を更新する。リスク高。回帰の基準線が動く

2026-08-05 の深夜(01:08 の commit の報告 08/05/01 §3)、話は案 2 の方へ進みます。
証言の意図(女将が何かを見た、という証言)に材料の条件を付けてみると、凍結した golden の 1 件「本当は何かを見たんじゃないですか」が、材料を 1 つも挙げていないので落ちる。
報告はこう結論しました。
「つまり誤取得 0 は、凍結ゴールデンを解かない限り達成できない」。

同じ日の完成の仕様(08/05/05)は、受け入れ条件 1 の中身として、これを指示しています。
「凍結 golden の 8 ケースを解除し、証言系に材料条件を入れ、期待値を更新する」。

凍結を解く理由は、筋が通って見えました。
凍結したケースが、正しい修正を止めている。
ならば期待の方を直すべきだ、と。

2026-08-05 11:26(bbc7c8d6)。
実際に作業すると、結果は違いました。
commit の本文です。
「凍結golden 8ケースは期待値更新なしで全維持(文言は正当に材料を含んでいた。当時『凍結が壊れる』と見えたのは別名辞書が薄くて材料と認識できなかったため)」。
「見た」「目にした」「見かけた」を 1 つの語として扱う辞書の項目を足し、「口をつぐむ」「言いかけた」を隠し事の語に足した。
それだけで、8 件の凍結ケースは、材料の条件を付けたまま全部通りました。

壊れていたのは期待ではなく、辞書でした。
もし案 2 のとおり期待を「いま通る値」に書き換えていたら、辞書の穴は見つからず、
凍結した 8 件は、辞書の穴に合わせた新しい正解として固定されていたはずです。
本文の最後の一言は「凍結を解除して期待値を更新するつもりで来たら、辞書を太らせた時点で8ケース全部が正当化されて、壊すものが何も無かった」。

うちで起きたこと(2)期待そのものが欠陥を固定していた#

逆の例もあります。

2026-08-19(7767a381)。
AI 初見プレイの 2 人が、同じ欠陥を報告しました。
第一発見者の岬蓮が、発見から通報までの 40 分の空白を認めたあと、もう一度発見の状況を聞くと、撤回したはずの「見つけて、すぐ通報しました」が返る。
しかも手帳に、新しい証言として積まれる。

直したあと、既存の台本の 1 本が落ちました。
その台本は、認めたあとでも「すぐ通報しました」の段が出ることを期待していたのです。
欠陥を、仕様として固定していました。

このときは期待の値を変えました。
変えた理由を、同じ台本の中に書いています(Game/adv/runs/misaki-grounds.txt)。

2026-08-19 に期待値を #2 → #3 へ変えた。仕様が変わったため(緑にするためではない)。

40分の空白を認めた(f_bird_revealed)あとに #2 が返ると、**撤回済みの「すぐ通報した」が

もう一度言われ、手帳へ新しい証言として積まれる**——第18波で2人が報告した欠陥。

この台本は「その状態でも #2 が出る」を仕様として固定してしまっていた。

認めたあとは訂正版(#3)が正しい。再発の見張りは runs/misaki-retraction.txt が持つ。

そして、再発を見張る台本を別に足しました。
訂正版の段を !expect で、撤回済みの段を !expect-not で縛ります。
commit の本文の最後は「期待値を直すのは禁じ手だけれど、仕様が変わったなら理由を書いて変えるのが筋」。

いまの仕組み — Guru Checks Output#

規約は 3 か所にあります。

毎周のループ(Scripts/adv-loop.ps1)は、FAIL のたびにこれを出します(2026-08-05 0f6c285e から)。

  • !expect の期待値を「いま通る値」に書き換えて緑にしない。台本は仕様である

AI 初見プレイの前の修正の指示書(08/07/11)は、合格の線を書いたあとに一行置いています。
「閾値・!expect・golden 期待値を『いま通る値』へ書き換える緑化は禁止」。

テスト計画(adv-test-plan.md)の §4 は「緑にするために閾値を動かさない(動かすときは実測を並べて理由を _why に書く)」、§11 は「閾値を緑に合わせて動かさない。旧結果を編集しない」。

golden/dev の git の履歴を見ると、凍結の後の変更は 3 回で、どれも書き換えではありません。
08/11 にケースを 4 件足した(足した理由の注記つき)。
09/06 に、段の番号(#0・#1)を段の名前(#alibi_s0 など)に置き換えた(同じ段の呼び名を変えただけ)。
09/22 に注記を 1 行直した。
期待の意図を、別の意図へ書き換えた差分はありません。

2026-08-18 の改善計画(08/18/01 §7)は、閾値を動かす実験のリスクの 1 番目に、これを置いています。
「閾値を変えると golden の期待が大量に動く → Guru Checks Output を踏まないよう、差分は 1 件ずつ見る。--write を付けない限り書き換わらない設計にする」。
その実験(RRF の比較、T09)は、期待を一つも動かさずに、負けて終わりました。

名前どおりでない所・まだ残っている弱さ — Guru Checks Output#

厳密には、うちは Guru Checks Output を踏んでいません。
踏みかけた、です。
設計書と完成の仕様が「期待値を更新する」と書き、作業の直前まで行って、作業の中で不要と分かりました。
そして、うちの golden は出力を写して作ったものではないので、approval testing の弱点そのものとも少し違います。
「正解を人が書いて凍結した検査の、期待を解く誘惑」の方が正確です。

残っている弱さは 2 つです。

一つ目、self-checking の検査でも、期待を書いたのは人(と開発の AI)です。
2026-08-19 の台本は、欠陥を期待として書いていました。
!expect は「台本どおりか」を機械で決めますが、台本が正しいかは決めません。
期待が正しいことの裏は、別の目(AI 初見プレイの 2 人の報告)から来ました。

二つ目、「理由を書いて変える」と「緑にするために変える」の線は、書いた理由の中身でしか分かりません。
2026-09-23 には、ユーザーの指示で、合格の項目のいくつかを合否に入れない計測項目へ移し、表示の線(ある上限を 2 から 7 へ)を動かしています。
テスト計画には指示の言葉と commit と実測が残っていて、手順としては正しく変えています。
けれど、理由を書けば何でも変えられる、という形ではあります。
いま、それを止めているのは「動かすのはテスト計画の改定として、ユーザーの方針で」という規約だけです。

検索語#

approval testing pitfalls
re-baselining golden master
snapshot testing blindly update
xUnit Test Patterns Manual Intervention

岬蓮に、40 分のことを聞いてみてください。認めたあとにもう一度聞くと、答えが変わります。『霧走町 流氷に眠る』の第一章はブラウザで遊べます。プロフィールのリンクから。

#claude #自然言語処理