自分で組んだ定期タスクや自動化は、静かに壊れる。エラーも出さず、ただ動かなくなる。
なので、Claude Code に毎日1回だけ見回らせて、異常を集め、決めた条件を全部満たすものだけ自動修復し、残りは人へ回す担当を1つ置いた。定期タスクの監視と自動化の保守を、1本のスキルにまとめた形になる。
名前は CardinalSystem。スキルとして MIT ライセンスで公開した。
https://github.com/artemislog/cardinal-system
作った当日の初回診断でいちばん大きく見えたのは、「観測データの更新が80時間止まっている」という検出だった。ところが調べてみると、止まっていたのではなく、見回る側の誤検知だった。
門の1つ目(原因を特定できるまで直さない)があったので、闇雲に直さずに済んだ。その後の巡回で実際に直したのは3件。その経緯は結果の数字のところで書く。
やったこと:見回って、直して、記録する担当を1つ置いた
1回の巡回は6段階にした。
観測 → 検出 → 仕分け → 修復 → 検証 → 記録
- 観測:構文チェック、テスト、定期タスクの最終結果、ログのエラー行、出力ファイルの更新時刻などを見る
- 検出と仕分け:見つけたものに重さを付ける。S1 停止(毎回失敗する定期処理など)、S2 不全(一部が動かない、結果が古いまま)、S3 軽微(表示やログのノイズ)
- 修復:1回の巡回で直すのは最大3件。S1 から順に。直す前にその時点の状態を残す
- 検証:直す前に失敗していた確認を、直した後にもう一度走らせて通ることを見る。通らなければ元に戻して人へ回す
- 記録:巡回ごとに台帳(
.cardinal/ledger.md)へ「直したもの」「要判断」「異常なし」を追記する
呼び方は3つある。「見回って」で全項目を巡回、「<対象>がおかしいから見て」でその対象だけを深く調べる、「レポートだけ」で直さずに検出と仕分けだけ。
定期実行の入口も3つ用意した。
| 場所 | やり方 |
|---|---|
| Claude Code のセッション中 | /loop 6h /cardinal-system |
| クラウド | /schedule で毎日 /cardinal-system |
| 自分のPC | scripts/patrol.ps1(Windows タスクスケジューラ)/ scripts/patrol.sh(cron) |
PCで無人実行するときは、claude -p で1回だけ巡回させる。許可するツールは最小限(読む・編集・git の参照・構文チェック・テスト)に絞ってあり、定期タスクの状態を見るコマンドなど、プロジェクトに固有の確認が要るときだけ -AllowTools(patrol.ps1)/ CARDINAL_ALLOW(patrol.sh)で足す。
わたしのプロジェクトでは、巡回するスクリプト1本と、それを毎日回すルーティン1本の組み合わせにした。見回り項目は巡回定義のファイル(CARDINAL.md)に7項目書いてある。中身はおおむね次のとおり。
- スクリプトの構文がすべて通るか
- 直近3日の定期実行に失敗や時間切れがないか
- タスクスケジューラの最終結果コードが正常か
- 状態ファイルの更新時刻が、決めた上限以内か
- 直近24時間のログにエラー行がないか
- 時間枠を過ぎたのに未実行・失敗のままのルーティンがないか
- 同じ問題が3日以上続いていないか
なぜ:「何を直してよいか」ではなく「何を直させないか」を先に書いた
設計で時間をかけたのは、直してよい範囲より、直させない範囲の方だった。
門を先に文章で決めて、そこを通らないものにはAIを触らせない。直してよいか分からないものは直さず、報告だけする。黙って挙動を変えることはさせない。個人開発でAIに自動修復をやらせるとき、わたしはここを削らないことにしている。
門は5つある。全部満たすときだけ直す。
1. 原因を特定できた(エラーを再現した、または原因の行を指せる)
2. 変更が小さい(目安は1〜2ファイル・50行以内。設計の変更にならない)
3. 直ったことを確かめる手段がある(テスト、再実行、構文チェック、ドライラン)
4. 元に戻せる(git 管理下、またはバックアップを取った)
5. 「触らないもの」に当たらない
1つでも欠けたら直さず、「要判断」として、人が何を決めればよいかを残す。
「触らないもの」は、どのプロジェクトでも共通にしたものがこれ。
- 認証情報・トークン・鍵・
.envの中身(読まない・書かない・ログに出さない) - 本番データの削除・上書き、DB のマイグレーション、課金・決済
- 外部への公開・送信・投稿(直した結果として何かが公開されるなら、その手前で止める)
- 権限・共有設定、デプロイ設定、スケジュールそのものの登録・削除
- 他の人・他のAIの担当ファイル
git push --force・reset --hard・履歴の書き換え- テストを消す・飛ばす、エラーを握りつぶす、チェックを無効にすることで「直った」ことにする修正
最後の項目は、README にも「テストを消す・エラーを握りつぶすような『直ったことにする』修正はしない」と書いた。無人で動くときは質問できないので、迷ったら直さずに記録して終わる決まりにしてある。
わたしのプロジェクトではこれに加えて、運用の定義ファイル、方針を決めた文書、並行して動いている別のAIの担当ファイルも対象外にした。直したスクリプトを確かめるときも、投稿や公開のオプションは付けず、送信しない形の確認だけで走らせる。
もう1つ、見回り項目に「出力ファイルの更新時刻」を入れた理由がある。定期タスクは、結果コードが0でも中身が動いていないことがある。タスクスケジューラの画面で「成功」と出ていても、出すはずのファイルが古いままなら止まっているのと同じだと扱うことにした。ただ、この項目は作った当日の初回診断でいきなり誤検知を出している。その話は次で書く。
結果の数字:作った当日の検出は誤検知だった。直したのはその後の3件
- 作った当日の初回診断の検出:観測データの更新停止 80時間(のちに監視側の誤検知と判明)
- 初回診断での修復:0件(検出のみ)
- その後の巡回で直したもの:3件(どれも、直した後の確認まで通っている)
- 「要判断」として人へ回したもの:2件
直した件数と要判断の件数は、10月3日までの巡回の台帳から数えた。
作った当日の初回診断のとき、タスクスケジューラの結果コードはすべて正常だった。それでも、アクセス解析の数字を置いておく観測データのファイルは、80時間更新されていなかった。結果コードだけを見ていたら気づけない異常を見つけた、と最初は思った。
これはその場では直していない。原因をまだ調べておらず、門の1つ目(原因を特定できた)を満たしていなかったからだ。なので手を付けず、毎日の巡回に回した。
翌日、毎日の巡回の1回目で原因を調べると、止まっていたのはデータではなく、見回る側の前提だった。アクセス解析の数字は、少し前からクラウド側で取る設計に切り替えてあって、PCのそのファイルはもう更新されないのが正しい状態だった。見回り項目の表だけが、切り替える前の前提のまま残っていた。
原因を確かめないまま「止まっている」を信じて直しに行っていたら、正しく動いているものを触るところだった。門の1つ目があったので、闇雲に直さずに済んだ。作った当日のいちばんの見せ場が誤検知だったのは、正直ちょっと気まずい。でも、門が役に立ったのはむしろこの件だと思っている。
その後の巡回で実際に直したのは、次の3件。
1. 見回り項目の表(上の誤検知そのもの)。クラウドで取る設定になっているときだけ、そのファイルを更新時刻の確認から外した。もう一度巡回して、「更新が止まった状態ファイル」が1件から0件になり、ほかの項目は変わらないことを確かめた
2. 失敗の原因がログから読めない問題。ある定期処理の失敗が、ログに fetch failed としか残っておらず、原因を絞れなかった。Node の fetch は原因を cause に入れて返すのに、受け取る側がメッセージだけを出していた。cause の code を添えて出すよう、1か所・3行を直した。擬似的に名前解決を失敗させて fetch failed (ENOTFOUND) と出ること、普段の実行では出力が変わらないことを確かめた
3. 定期処理の状態が「使用中」のまま戻らない問題。前の処理が残した「使用中」の目印が消えず、次の処理が始められない扱いになっていた。目印の持ち主がもう動いていないことを確かめてから回復し、目印に持ち主の記録を足して、次からは安全に片付けられるようにした。持ち主がまだ動いている・別のPC・持ち主が分からない、のどれかなら片付けずに残す。関連するテスト25件が通ることを確かめた。この回は、別のAIに同じ台帳で巡回させた
直さなかった回もある。ある夜の失敗3件は、調べると一時的に名前解決ができなかった回線の問題で、翌日同じ処理を流し直すと正常に終わった。コードの欠陥ではないので、何も直していない。
「要判断」に回した2件は、どちらも門の5つ目(触らないもの)か、設計の変更に当たるものだった。そのうち1件(取得が全部失敗しても成功を返す件)は、翌日に別の作業で「全部失敗なら失敗を返す」形に直っている(人へ回した件を受けての変更かは記録していない)。
- 無人で動かすときに、プロジェクトのスクリプトを実行する許可が下りない。権限の設定は「触らないもの」なので、人へ回した
- ある確認処理が、外部からの取得に全部失敗しても「成功」と返す。終了コードを変えると、単発の取得失敗でも定期実行が「失敗」扱いになる。挙動の設計の話なので、人へ回した
公開までにも、審査で2か所、公開の手順で1か所、合わせて3か所直している。公開前の審査で、Windows PowerShell 5.1 で日本語が化ける点と、macOS 標準の bash 3.2 で動かない書き方の2件を指摘され、元のスクリプトで直した。公開の手順でも、PowerShell 5.1 が標準エラーの出力を例外として扱う挙動で1回止まり、そこも直した。公開後は、別の場所にクローンし直して、出してはいけない語句が入っていないことを確かめた。
次にやること
- 毎日の巡回を続けて、直した件数と「要判断」に回した件数を数え続ける。まとまったらまた書く
- 「要判断」に回したものを、人の側で決めて片付ける
同じようなことを試す場合は、リポジトリの templates/CARDINAL.md をプロジェクトにコピーして、「見回り項目」「直してよい範囲」「触らないもの」「報告先」の4つを埋めれば動く。巡回定義が無くても、自動検出で巡回はする。
名前は、とあるVRMMOの世界でバグを見つけて直し続けるシステムから借りている。非公式の命名で、原作および権利者とは関係ない。


コメント