AI運用の障害が起きたとき、原因切り分けを誤ると同じ現象が何日も再発します。本記事は、更新時刻を犯人だと決めつけて誤診した社内の実際の事故を追い、症状・誤診・真因・恒久対策の4段で切り分ける手順と、証跡から追える記録設計への直し方を共有します。読み終えたら、次に同じ症状が出たときの確認順序が手元に残ります。

01AI運用で起きた障害|原因切り分け前に見えていた症状

WEBMARKSは2026-07-08、Codex(別のAIエンジン)に「成果物が納品先へ正しく格上げされたか」を末尾で確認する仕組みを入れました。導入直後から、業務と無関係な確認メッセージがセッションの最後に毎回出るようになりました。

TASK-048というブラッシュアップ監査を45分かけて実行した回では、完了報告のはずの末尾が「【格上げ確認ゲート】直近で成果物が作られました」という表示に乗っ取られました。列挙されたのは、その回のセッションが一切触っていない別案件のファイルでした。

導入からの3日間で、この確認メッセージは233回発火しました(出典: 社内タスク台帳、2026-07-10記録)。記録に残っているのは次の範囲です。

項目記録されている内容
発火回数3日間で233回
症状完了報告の末尾が、そのセッションが触っていない別案件のファイル列挙に置き換わる
判定材料ファイルの更新時刻(mtime)から担当セッションを推定していた
解消thread・case・ハッシュを明示記録する方式へ全面刷新して収束

日別の内訳は残していません。ここは正直に書いておきます。合計値だけを記録し、日ごとの推移を取らなかったため、「初日に何回で、修正パッチ後に何回に減ったか」を後から言えません。再発の傾向を見るには日別が要ります。 障害の記録設計としては、この時点で1つ足りていませんでした。

「毎回最後に変なメッセージが出る」「Codexが動いていない気がする」という体感は、あとから振り返ると正確な障害報告でした。ただし、この体感だけでは原因切り分けは進みません。

AI運用の障害がやっかいなのは、業務の完了報告そのものが上書きされる点です。次に何を確認すればいいかが分からないまま、無関係な情報だけが目の前に残ります。

障害切り分け4段フロー。検証で画面と照合したかどうかが、誤診の再発と真因到達を分ける分岐図 障害切り分けの4段フロー図。①症状の発見→②最初の仮説(更新時刻を疑う)→③検証(画面と照合するか)の3段の後、③の分岐点で二手に分かれる。画面と照合せず結論を急ぐと「誤診のまま停止(233回の再発が続く)」へ進み、そこから同じ症状が再発して①症状の発見へ戻る(モグラ叩き、破線のループ矢印)。画面と照合すると④真因の特定(旧フックの誤爆)→⑤恒久対策(記録方式へ全面刷新)という正常経路へ進む。下部の注記は、結論を出す前に画面と照合したかどうかが分かれ目になることを示す。 DIAGNOSIS 障害切り分けの4段フロー:検証が誤診と真因を分ける 画面と照合する ①症状の発見違和感に気づく ②最初の仮説(更新時刻を疑う) ③検証画面と照合するか ④真因の特定旧フックの誤爆 ⑤恒久対策記録方式へ刷新 画面と照合せず結論を急ぐ 誤診のまま停止 (233回の再発が続く) 同じ症状が再発(モグラ叩き) 「壊れていない」と結論する前に、画面と照合したかどうかが分かれ目になる
障害切り分けの4段フロー図

02最初の原因切り分けは、なぜ更新時刻を疑ったのか

最初にこの症状を調べた担当は、セッションログの最後の1行だけを読み、「既存の運用ルールどおりに動いている、壊れていない」と結論づけました。これが誤診でした。

判断の根拠は、確認メッセージの文面が既存ルールの体裁に沿っていたことだけです。ユーザーが実際に画面で見ていたもの、つまり無関係な別案件のファイル一覧とは突き合わせていませんでした。

障害切り分けでもっとも危険なのは、この「文面は正しそうに見える」段階で止まることです。ポストモーテムの実務書は、対応者を個人として断罪しない姿勢を説きます。同時に、システムの脆弱性そのものを特定することへ焦点を当てるべきだとも述べています(出典: Google SRE Book「Postmortem Culture」)。

今回のケースでいえば、脆弱性は担当者の注意力ではありません。検証手順に「実物の画面と照合する」工程が、そもそも入っていなかったことが脆弱性でした。

論点誤診(最初の結論)真因(実際の原因)
何が起きているかルールどおりの正常な確認表示旧フックの誤爆バグ
判断の根拠セッションログの最終メッセージのみ更新時刻で別セッションの成果物を誤って自分の成果物とみなす設計
突き合わせた対象ログの文面だけユーザーが見た画面(無関係ファイル一覧)とは未照合
結果「壊れていない」と回答3日で233回の誤爆が継続

体感が正しく、調査の結論が誤っている。この食い違いは、原因切り分けの現場でくり返し起こります。

03障害切り分けの盲点だった、更新時刻が招いた本当の原因

真因は、旧フック(承認ゲート用の確認スクリプトの旧版)の設計そのものにありました。Codexにはセッションを一意に識別するIDがありませんでした。その代替として「前回の確認以降に更新時刻が動いたVault内ファイルは、このセッションの成果物」とみなす作りにしていました。

このMac上では、画像生成バッチやClaude Codeの並行セッションが常時動いています。更新時刻はファイルシステム全体で共有される値なので、複数の処理が同時に走る環境では「誰が触ったか」の手がかりになりません。2026-07-09に中間ファイルを除外するパッチを当てても再発したのは、更新時刻という方式そのものに欠陥があったためです。この時点で、パッチは症状ごとに後追いする「モグラ叩き」になっていました。

同じ問題は分散システムの世界でも古くから知られています。W3C Trace Context仕様は、高スループット環境では同時刻に複数のリクエストが発生し、タイムスタンプ単独では識別できないと明記しています。だからこそ、ランダム生成した明示的なtrace-idを識別の起点に据えます(出典: W3C Trace Context仕様)。更新時刻に頼った旧フックは、この教科書的な落とし穴をそのまま踏んでいたことになります。

ログだけでは原因追跡に足りない、という指摘も一致します。分散トレーシングの解説では、ログだけでは実行経路を追うのに文脈情報が不足しがちだと指摘されています。根本原因分析には、リクエスト単位の明示的なつながりが要るとも説明されています(出典: OpenTelemetry Observability Primer)。

旧フックが持っていたのは更新時刻という間接的な手がかりだけでした。どのセッションが何を書いたかという明示的なつながりは、どこにもありませんでした。

更新時刻推測と書き込み記録を4軸で比較し、旧フックの限界を示す図 更新時刻(mtime)による間接推測と、書き込みイベントの明示記録を4つの軸で比較するマトリクス図。①判定の根拠、②並行処理の環境での精度、③第三者による事後検証の可否の3軸は、いずれもmtime側が低く明示記録側が高い。本文にない追加軸の④導入・運用コストだけはmtime側が低く(既存の仕組みを流用するだけ)、明示記録側は中〜高い(フック新設とID設計が必要)。このコストの低さがmtimeを選ばせ、旧フックが再発を止められなかった理由を4軸で示す。 MATRIX 更新時刻推測と書き込み記録を4軸で比較し、旧フックの限界を示す図 ①判定の根拠(推測か記録か) ②並行処理の環境での精度 ③第三者による事後検証の可否 ④導入運用コスト(本文にない軸) 更新時刻(mtime)による間接推測 書き込みイベントの明示記録 推測特定不可 低い共有値のため 低い再現できない 低い既存流用で軽量 記録ID・ハッシュ 高い主体を記録 高いハッシュで検証 中〜高新設が必要 ④のコストの低さが旧方式(mtime)を選ばせ、2026-07-10に記録方式へ全面刷新された
更新時刻(mtime)による間接推測と、明示的な書き込みイベント記録を比較軸マトリクスで対比する図

04AIの運用障害を止めた、原因切り分け後の対処

2026-07-10、WEBMARKSはこの仕組みを全面的に作り直しました。柱は、更新時刻による推測をやめ、書き込みイベントを明示的に記録する方式へ切り替えたことです。

  1. 更新時刻の走査・時間窓・クールダウンといった間接推測の仕組みをすべて廃止する
  2. ツール実行の直後に発火するフック(record-output.py)が、そのスレッドが実際にWrite・Edit・ApplyPatchしたファイルだけを、スレッドID・案件ID・SHA-256ハッシュ付きで記録する
  3. セッション終了時のゲート(promotion-gate.py)は、この記録だけを見て判断する。他セッションの成果物が混ざる経路自体が無くなる
  4. 検証に失敗したとき(書き込み記録そのものが見当たらない場合を含む)は、ブロックではなく通過を選ぶ設計にした。止める方向に倒すと、正常な成果物まで巻き込んで業務が止まってしまうためだ。その代わり、通した記録は必ず残す

記録先のディレクトリ名は、スレッドIDと案件IDを連結した文字列のSHA-256ハッシュです。案件をまたいだ記録の混線も、構造的に防いでいます。

フックが判断をJSON形式で返し、必要な処理だけを止めるという設計自体は珍しくありません。WEBMARKSはClaude Code側でも同じ仕組みを採用しています(出典: Claude Code公式フックドキュメント)。エンジンが変わっても、この骨格は使い回せます。

この判断は、その場しのぎの妥協ではありません。意図した設計だと、記録に明文で残してあります。原因切り分けでは、判断の根拠が個人の記憶に留まると、あとから検証も再現もできなくなります。設計判断そのものを記録に残す姿勢は、更新時刻のような間接的な手がかりに頼らない運用と、根っこは同じです。

通常のWIP(作業途中の成果物)では、確認メッセージ自体を出さなくなりました。ブロックするのは、承認証跡の無いファイルが納品フォルダへ混入したという構造違反1種類だけです。加えて、フック(機械層)の刷新と同じ日に、指示書側の「毎回質問する」という古い文言も「作業途中は黙って進める」へ書き換えました。片方だけを直すと、直さなかった側から同じ症状が再発するためです。

05原因切り分けの記録を、証跡として残るように変えた

この事故から持ち帰れる教訓は、Codex固有の実装詳細より一段抽象度の高い、原因切り分けの手順そのものにあります。

  • 「壊れていない・仕様どおり」と結論する前に、ユーザーが実際に見た画面や出力と照合する
  • 並行セッション環境では、更新時刻だけを根拠に成果物の所有者を推定しない。所有の証跡は、書き込みイベントの明示記録でしか成立しない
  • フック(機械層)と指示書(文章のルール)は、同じ日にセットで直す。片方だけでは再発を止められない
  • 別のAIエンジンへ同じ機能を移植するときは、前提条件(セッションIDの有無など)が崩れていないかを先に確認する

残っている運用上の論点も1つあります。フックの設定ファイルを更新すると、次回Codex起動時に「このフックを信頼するか」という確認が1回だけ出ます。承認するまで新しい仕組みは有効になりませんが、無効な間も更新時刻による誤爆はしない設計にしてあります。

WEBMARKSは2026-06-24に7部署・30体のAI社員体制を統合し、AI社員同士・AIエンジン同士が同じVaultを並行して触る運用に切り替えました。並行稼働が増えるほど、更新時刻のような間接的な手がかりに頼った設計は壊れやすくなります。この事故も、その構造から起きた1件です。

更新時刻を疑う前に、まず証跡の有無を疑う。この順序を守るだけで、同じ種類の誤診はかなり減らせます。

明示記録の仕組みは、送信や公開を人が最終判断する承認ゲートの土台にもなります。ゲート設計全体は『AIエージェントの承認ゲート|送信・公開・削除で止める仕組み』で扱っています。

06同じ失敗を避けるためのチェックリスト

  • 「壊れていない」と結論する前に、ユーザーが実際に見た画面と照合したか
  • 並行セッション環境で、更新時刻(mtime)だけを根拠に成果物の所有者を推定していないか
  • フック(機械層)を直すとき、指示書(指示層)の文章ルールも同じ日にセットで直したか
  • 「誰が書いたか」を、推測ではなく明示的な記録(スレッドID・案件ID・ハッシュ値など)で追跡できるか
  • 障害の発火回数と発生日を数値で記録し、パッチ後に再発していないかを実測で確認したか
  • 新しい検知の仕組みを入れるとき、誤検知は「止める」方向ではなく「黙って通す」方向に倒したか
  • エンジンを乗り換えて同じ機能を移植するとき、前提条件(セッションIDの有無など)が変わっていないか確認したか