版のずれによる空振りは、なぜエラーにならないのか
無人実行の監視は、エラー率や終了コードで組むことが多いと思います。版のずれによる空振りは、そのどちらにも引っかかりません。
処理系そのものは正しく動いているからです。子エージェントは起動していますし、トリガーも時刻どおりに走っています。実行されているのは「仕様どおりの新しい挙動」か「古いが正常なコード」なので、例外は投げられません。
見るべきなのは「エラーが起きたか」ではなく「意図した処理が最後まで進んだか」です。relmeaでは、この違いに気づくまでに2種類の版のずれをそれぞれ見逃しました。
型A 勝手に上がる版:実行環境の自動更新で、後続工程に進まなくなった
構成
relmeaの無人パイプラインは、AIエージェントの実行環境(CLI)を、Macの定時実行(launchd)から対話なしのモードで起動しています。司令塔役のAIが子エージェントを起動し、その結果を受け取って次の工程へ進む構成です。
起きたこと
2026年9月18日、この実行環境が自動更新され、子エージェントの起動が既定で「バックグラウンド起動」に変わりました。司令塔は子の結果を待たずに「完了通知を待ちます」と言って自分の手番を終えるようになり、後続の工程に進まなくなりました。
毎日回している改善ループは、9月18日から21日までの8回すべてが同じ工程(2番目の工程=診断役の子エージェントの起動)で止まっていました。日報は0件、仮説の判定も0件です。
気づけなかった理由
途中の書き出し処理は毎回走っていたため、ログには「〇件書き出し」という行が出続けていました。エラーも出ていません。この行だけを見ると健全に動いているように見えますが、実際には健全性の証拠になっていませんでした。
対処と確かめ方
全パイプラインが共有している起動部品の1か所で、子エージェントを同期実行に戻す環境変数を渡すようにしました(2026年9月21日)。直ったかどうかは、小さいモデルで次の2つの状態を実測して確かめています。
- 設定なし:バックグラウンド起動が1件発生する
- 設定あり:バックグラウンド起動は0件で、子の結果が同じ手番のうちに返ってくる
無人実行が「起動しました。完了を待ちます」で終わり、そこから成果物が増えていないときは、まず実行環境そのものの版と更新日を疑います。自動更新は便利ですが、既定の挙動が変わることまで含めて受け取っている、という前提で見ておく必要があります。
型B 上がらない版:GASのトリガーが古いバージョンに固定されていた
起きたこと
型Aと向きが逆の空振りが、GAS(Google Apps Script)で起きました。GASの時間トリガーは、どの版のコードで動かすかが「導入」の時点で決まります。relmeaの集計用トリガーは、2026年8月23日の版(v64)に固定されていました。
コードを更新(push)しても、更新されるのは最新版(Head)だけです。トリガーは古い版のまま動き続けたため、8月30日と9月4日に加えた変更が2週間ぶん反映されていませんでした。発覚したのは9月6日です。
気づけなかった理由
見つけにくかった理由は3つ重なっていました。
- 実行は毎回「完了」で、エラー率は0%だった
- 実行ログに新しいコードのログが1行も出ない。古いコードにはそのログが無いので、出ないことが当然に見えた
- 本番と手元のコードを比べても差分はゼロ。比べている相手のHeadは正しく更新されているため
3つとも「異常なし」に見える指標で、版が固定されているという事実だけがどこにも出てきませんでした。
1本だけ直した結果
同じ固定は、他の複数のトリガーにも入っていました。9月6日には見つけた1本だけを直し、残りは据え置きました。その結果、配信の対象から外したはずのアカウントに、9月10日まで毎朝2枠の配信が割り当てられ続けました。すべてのトリガーをHeadへ張り直したのは9月10日です。
対処
- 複数のトリガーをまとめて張り替える関数を用意した。既存トリガーの版は管理画面から変えられないため、コードで作り直す
- 「外したはずのアカウントが配信計画に出てきたら鳴る」監視項目を足した
2つ目は版そのものを見る手段ではありません。版のずれが引き起こす結果を見る手段です。現状、版の固定を機械で検出できているのはこの項目だけです。
2つの型に共通すること:正常終了の顔をした空振り
型Aは、実行環境が意図せず新しくなりました。型Bは、デプロイした処理が意図どおりに新しくなりませんでした。版が動く向きは逆です。
それでも、どちらも「エラーなく正常終了した」という顔で終わっています。型Aでは子エージェントの起動自体は成功していて、完了を待つ手番のまま進行が止まっているだけです。型Bではコードの実行は完全に正常で、動いているコードが古いだけです。
「失敗したら知らせる」監視は、失敗していない空振りを検知できません。版のずれを捕まえるには、別の置き場所に検査を置く必要があります。
終了コードでは捕まらない:結果の側で検査する
版のずれは、実行の途中ではなく結果の側で捕まえます。relmeaの毎日のコラム公開ジョブには、次の検査を入れています。
- 終了コードではなく「公開済みの記事ファイルが実行前より増えたか」で成否を判定する
- 増えていなければ公開の工程へ進まず、その理由を記録する
型Bで足した「外したはずのアカウントが出てきたら鳴る」監視も、同じ考え方です。トリガーが何版で動いているかを直接見るのではなく、出るはずのない結果が出ていないかを見ています。
検査は2種類に分けて置く
- 増えるはずのものが増えたか:進行が止まる空振り(型A)向け。成果物の件数やファイル数を、実行の前後で比べます。
- 出てはいけないものが出ていないか:古い版が動き続ける空振り(型B)向け。変更で消したはずの挙動が、結果に残っていないかを見ます。
どちらも、ログの「成功」「完了」という表示だけを見ていては作れない検査です。自動化を1本足すときに、「この処理が正しく動いたら、何がいくつ増えるか」「何が出てこなくなるか」を先に書いておくと、検査の中身がそのまま決まります。
見つけたら、同じ日に全部直す
型Bで学んだもう一つのことは、同じ構造の不具合が他の場所にもある前提で探すことです。
9月6日に見つけたトリガーの版固定は、他のトリガーにも同じ形で入っていました。最初の1本だけを直して残りを据え置いたため、9月10日まで別の空振りが続きました。1本直した時点で安心すると、「直したはず」という記憶だけが残り、残りの箇所は手つかずのまま忘れられます。
見つけた不具合と同じ構造の箇所を、その日のうちに全部洗い出して直す。そして、直したことを結果の側の検査で確かめる。無人実行を長く回すうえで、版のずれに限らず効く手順だと考えています。
