一覧に戻る
    「絶対条件」が詰みを生む — testing フェーズに「検証不能の出口」を作った話
    AI開発
    PRこの記事には広告が含まれています

    「絶対条件」が詰みを生む — testing フェーズに「検証不能の出口」を作った話

    14 分で読める

    起きていたこと

    DevLoop Runner の運用で、ある違和感が積もっていました。

    testing フェーズで「3回トライして失敗、停止」というケースが、どうにも構造的に発生している気がする。しかも詰まり方が決まっていて、「物理的に検証できない受け入れ要件」が混じっているときに、必ずと言っていいほど起きる。

    たとえば、

    • 実機がないと最終確認できないハードウェア連携
    • 本番環境にしか繋がらない外部システムとの結合
    • ライセンスの都合で CI 環境からは叩けない API

    こういう項目が受け入れ基準に入っていると、テスト実行エージェントは正直に「実機がないので検証不能」と書きます。すると review が品質ゲートで FAIL を出し、revise が走り、また FAIL を出し……を3回繰り返して停止する。

    正直に書いたほうが詰む、というのはおかしい。これは仕様バグなんじゃないか、と思いました。

    まずはコードを読む

    「仕様バグかも」という直感は、思い込みである可能性も高いので、まずコードを読みました。execute を走らせる前に何度か通った道ですが、今回は特に testing フェーズの判定ロジックを丁寧に追いました。

    読んでわかった構造はこうです。

    3回リトライの場所

    src/phases/core/review-cycle-manager.tsMAX_RETRIES = 3 がハードコードされていて、testing フェーズの review が FAIL するたびに revise → review → … を最大3回繰り返し、超えたら例外で停止します。

    testing フェーズの「FAIL ロジック」

    src/prompts/testing/ja/review.txt に書かれていたのは、品質ゲート3項目(テスト実行されている / 主要なテストケースが成功している / 失敗が分析されている)のうち1つでも FAIL なら自動的に最終判定 FAIL、というルールでした。「80点で十分」という緩和条項もあったのですが、それは品質ゲートをクリアした後にしか適用されない。つまり、品質ゲートは絶対条件になっていました。

    既存の逃げ道は「実行不要なケース」だけ

    src/prompts/testing/ja/execute.txt には、「テスト実装がスキップされた」「ドキュメント修正のみ」など、テスト自体が不要な場合のスキップ手順しか書かれていません。「テストは必要だが、物理的制約で実行できない」ケースのガイダンスが、丸ごと抜け落ちていました。

    revise の選択肢が二択しかない

    revise.txt には「Phase 4(実装)に戻る / 環境を直す」の二択しか提示されていない。物理制約は実装修正でも環境修正でも解決しないので、何度リトライしても無意味です。

    ここまで読んで、ようやく構造が見えました。

    物理制約のケースは、図の左下のループから抜ける道がない。正直に書くほどここに突っ込む構造でした。

    3つの案を並べる

    仕様の穴の場所はわかったので、ここから直し方を考えます。「とりあえず直す」だけだと別の歪みが出るので、案を3つ並べました。

    変更範囲効果リスク
    A: 上流で検証性タグ付与requirements / test_scenario / testing 全プロンプト + 成果物構造根本対策。物理制約は上流で隔離できる既存 issue のメタデータ互換性、影響範囲が大きい
    B: testing に正規の「検証不能出口」testing の3プロンプト(execute/review/revise)のみ直近の3回失敗を即解消エージェントが「物理制約」と称してスキップ乱発する恐れ
    C: B + 判定ロジック実装B + testing.ts のコード追加乱用抑止が効く誤判定リスク、実装コストが上がる

    A は構造的にきれいです。受け入れ基準に「自動検証可能/物理制約あり」みたいなフラグを上流で付与しておけば、testing 側は迷わない。ただし、requirements / test_scenario の出力構造、既存 issue のメタデータ、すべての下流フェーズで一貫した扱いを設計し直す必要がある。痛みが大きすぎる

    C は B にコードでガードを足す案ですが、「物理制約かどうか」を機械的に判定するロジックは、本質的に難しい。誤判定して逆に乱用を生む可能性があります。

    B は最小侵襲で、プロンプト改修だけで済む。乱用リスクは残るけれど、まずは効果を見てから A に段階拡張するのが現実的だと判断しました。

    「迷ったら、より構造的に正しい方を選ぼう」という私の癖からすると A を選びがちなのですが、今回は「痛みを止めること」を優先しました。全体の整合性を犠牲にせず、当面の詰みを解消できる範囲で動く。これは、過去に 検証サイクルの設計 を考えていたときに学んだ「やりすぎないことの効用」とも繋がります。

    プロンプトだけで仕様バグを直す

    実装はプロンプト6本(ja/en × execute/review/revise)と report プロンプト2本、それと回帰テスト1本だけで終わりました。testing.ts の TypeScript には一切手を入れていません。

    具体的には、こういう変更を入れました。

    testing/ja/execute.txt への追加

    「## 検証不能項目(物理制約)」セクションのフォーマットを定義し、項目ごとに以下を必須記入にしました。

    • 検証できない理由
    • 検証に必要な環境(実機 / 本番接続 / ライセンス等)
    • 代替検証手段(コードレビュー / 設計レビュー / ドライラン等)

    「物理制約だから検証不能」とだけ書いて逃げられないように、代替の検証手段まで考えさせるのが肝です。これがないと、ただのスキップ乱用への扉になります。

    testing/ja/review.txt の品質ゲート判定の緩和

    「検証不能項目が正当な理由付きで記録されている場合、『主要なテストケースが成功している』は検証可能だった範囲で評価する」というルールを追加しました。これで、物理制約に阻まれた項目があっても、PASSWITHSUGGESTIONS で抜けられるようになりました。

    testing/ja/revise.txt に第3の選択肢

    これが今回の本丸です。「Phase 4 に戻す / 環境を直す / 検証不能項目として記録する」の3択にしました。物理制約のケースは、3つ目を選ぶことで無限ループから抜けられます。

    report プロンプトに「未検証項目」セクション

    未検証項目は PR 本文に集約されて、最終的に人間レビューで担保する形にしました。AI 側で完結させずに、人の判断を挟む経路を残すのは、こういう曖昧な領域では大事だと思っています。

    なぜプロンプトだけで済んだか

    これは振り返ると、ちょっと面白いポイントです。

    ワークフロー系の挙動の多くは、「プロンプトに書いてあるルール」に支配されています。testing.ts の中で見ているのは「python3 が入っているか」程度で、合否判定の本体はプロンプトの中の自然言語ルールにある。だから、「品質ゲートで何を絶対条件にするか」「revise で何を選択肢として提示するか」をプロンプト側で書き換えれば、構造的なバグも直る

    これは LLM 駆動の開発 で何度か感じてきたことですが、「コード変更前に、プロンプト改修で済むかを最初に検討する」というチェックは、毎回意識的にやる価値があります。今回もそれで実装コストが大幅に縮みました。

    学んだこと

    実装が終わってから、改めて整理してみると、いくつかの学びが浮かび上がってきました。

    「絶対条件」は逃げ道とセットで設計する

    品質ゲートに「すべて PASS が絶対条件」を置くなら、同時に「何が PASSWITHSUGGESTIONS で抜けられるか」を設計しておく必要があります。今回詰まっていたのは、絶対条件は明文化されているのに、抜け道の条件が定義されていないという非対称性でした。

    絶対条件を作るとき、「これだけは譲れない」を決めるのは比較的簡単です。難しいのは、「譲れないけど、構造的に満たせない場合の扱い」を一緒に決めること。今回はここを忘れていたのが原因でした。

    「スキップ」の意味を分けて設計する

    既存のプロンプトには「テスト自体が不要なケース」のスキップ手順しかなく、「テストは必要だが物理的に実行できないケース」が抜けていました。

    今後新しいスキップ判定を追加するときは、

    • 不要: そもそもテストする対象がない
    • 実行不能: 必要だが物理制約で実行できない
    • 失敗のまま記録: 実行したが意図的に通過させない

    この3分類を意識しないと、また同じ穴を作りそうです。

    revise の選択肢は「修正先」を網羅的に並べる

    revise を「直す or 戻す」の二択で書くと、そのどちらでも解決しない問題が現れたときに詰みます。今回学んだのは、revise の選択肢は「上流に戻す / 自フェーズで直す / 正当に記録する」の3軸で考えるべきだということ。

    特に「正当に記録する」を最初から選択肢に入れておくのは大事だと思いました。AI に判断させる場面では、「直す」「戻す」だけでなく「人間レビューに委ねる出口」を必ず用意しておく。

    プロセスの学び:探索的な問いでも、根拠付きの提案を返す

    今回、最初に「なんとかしたい」という曖昧な相談から始めたのですが、コードの該当箇所(ファイル名・行番号)を根拠にした提案にしてもらったことで、意思決定がぐっと早くなりました。

    抽象的な選択肢提示だけだと、どれが現実的かわからない。コードに根拠が紐付いている提案は、選びやすいし、後で実装に入ったときの迷いも減る。これは AI とのやり取りに限らず、人間同士の議論でも同じだと思います。

    案を階層化して提示する型

    今回の3案(A: 根本対策 / B: 最小侵襲 / C: 中間)の出し方は、こういう問題のときに使い回せそうです。「B から始めて効果を見て A に段階拡張」という着地は、リスクと効果のバランスが取れていて、合意も早かった。

    「迷ったら難しい方」が私の判断軸なんですが、最近は「段階的に難しい方に行く」という方が、現実的にうまくいくことが多い気がしています。

    次の課題

    今回の B 案で痛みは止まりましたが、根本対策の A 案は残っています。2〜3週間運用してみて、

    • 「検証不能項目」セクションが実際に使われているか
    • 乱用されていないか(本来テスト可能なものまでスキップされていないか)

    を観察してから、A 案への移行可否を判断する予定です。乱用が見えたら C 案でガードを足す方向もあり得ます。

    絶対条件と逃げ道、その間のバランスは、運用しながら少しずつチューニングしていくものだと思っています。最初から完璧な線引きは多分できなくて、「詰みを止める」「乱用を見つけたら締める」を繰り返すことでしか、ちょうどいい場所は見つからない気がしています。


    関連書籍

    今回のような AI ワークフロー設計・品質ゲート設計・テスト戦略について、さらに学びたい方におすすめの書籍です。

    この記事は役に立ちましたか?

    Coffee cup

    この記事が、何かの整理につながったら

    コーヒー1杯分の応援をもらえると嬉しいです。

    ※ これは応援とは別の話ですが、

    同じようなテーマを自分の文脈で整理したい場合は、 (文章だけだと詰まりやすい人向けに) 思考整理の壁打ちという形で対話の時間も取っています。

    対話の時間について