無人ジョブの沈黙する失敗と効果検証の自動判定
定時ジョブが1行もログを残さずスキップされる事故の検知と、恒久対策の効果検証をジョブ自身に判定させる型。Windows Interactive タスクが無人再起動で捨てられる罠、検証を壊す警告文の是正、全分岐の時間偽装テストまで。
約3.3万トークンの節約 (API料金換算で約50円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。
この巻物について
「無人ジョブの沈黙する失敗と効果検証の自動判定」は、業務自動化カテゴリのAI指示書(MDファイル)です。定時ジョブが1行もログを残さずスキップされる事故の検知と、恒久対策の効果検証をジョブ自身に判定させる型。Windows Interactive タスクが無人再起動で捨てられる罠、検証を壊す警告文の是正、全分岐の時間偽装テストまで。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約3.3万トークン(API料金換算で約50円)・79%のトークンを節約できます。
- カテゴリ
- 業務自動化
- 対応AI
- claude-code、cursor、codex-cli
- ライセンス
- 商用利用可 (再販不可)
- 価格
- 無料
- ゼロから開発時
- 約4.2万トークン
- この巻物使用時
- 約9,000トークン
- 節約量
- 約3.3万トークン (約50円)
- 更新日
- 2026-08-27
使い方 (AIに渡す3つの方法)
いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/md-833229bc/raw を読み込んで、この指示書どおりに実装して"
中身
無人ジョブの「沈黙する失敗」と、恒久対策の効果検証を自動で判定させる型
毎朝・毎晩に無人で走るジョブ(定時配信、バッチ、同期、スクレイピング)を運用すると、 失敗が通知されず、誰も気づかないまま日数が過ぎるという事故が必ず起きる。 この指示書は、その2大原因(沈黙する失敗 / 恒久対策の効果検証が人間任せ)を潰す実装の型を示す。
前提: 言語は任意(例は Node.js)。通知先はチャット webhook を想定(Slack / Discord / Teams いずれでも同型)。
原則1: 成功判定は「ログが出ていること」ではなく「今日の成果物が存在すること」で行う
最悪の失敗は ジョブが1行もログを残さずにスキップされる ケース。 ログを読む監視は「ログが無い=チェック対象が無い=異常なし」と誤読する。
やること: ジョブ本体とは別に、成果物の存在だけを見る軽量チェックを用意する。
// check-artifact.js — ジョブ本体とは別プロセス。ジョブ実行時刻の後に走らせる
const fs = require('fs');
const path = require('path');
const ARTIFACT_DIR = process.env.ARTIFACT_DIR; // 例: ./logs
const EXPECTED_HOUR = Number(process.env.EXPECTED_HOUR); // 例: 7 (この時刻までに成果物が出る想定)
const SUCCESS_MARKER = process.env.SUCCESS_MARKER; // 例: '=== 完了 ==='
const today = new Date().toISOString().slice(0, 10); // 運用タイムゾーンに合わせて調整
const file = path.join(ARTIFACT_DIR, `${today}.log`);
if (!fs.existsSync(file)) {
// ★ここが本命。「ファイルが無い」は最も見逃されやすい失敗
notify(`🚨 本日(${today})のジョブが**一度も起動していません**(ログファイル自体が存在しない)。`
+ `スケジューラのトリガ条件・端末の稼働状況を確認してください。`);
process.exit(1);
}
const body = fs.readFileSync(file, 'utf8');
if (!body.includes(SUCCESS_MARKER)) {
notify(`🚨 本日(${today})のジョブは起動したが完了マーカーが出ていません(途中で異常終了)。`);
process.exit(1);
}
console.log(`OK: ${today} 完了マーカーあり`);
設計上の要点
- 「異常なし」を無言にしてよいが、「チェック自体が走らなかった」は無言にしてはいけない。 チェッカーもまた無人ジョブなので、同じ罠に落ちる。最低限、成功時も日次ログに1行残す。
- 通知は「前回と違うこと」だけ送る。毎日同じ正常通知を送ると人が読まなくなり、 本当の異常が埋もれる。
原則2: Windows タスクスケジューラの Interactive タスクは無人再起動で丸ごとスキップされる
実際に起きた事故(原因特定まで数日かかった):
| 時刻 | 出来事 |
|---|---|
| 03:59 | ログオフ(Winlogon イベント 7002) |
| 04:01〜04:05 | OS 更新に伴う再起動が複数回 |
| 06:55 | 定時タスクのトリガ時刻。誰もログオンしていないため起動されず、ログも残らない |
| 08:43 | 人がログオン(Winlogon 7001)。もう配信時刻は過ぎている |
タスクのプリンシパルが LogonType=Interactive(=「ユーザーがログオンしているときのみ実行する」)だと、
未ログオン状態ではトリガが静かに捨てられる。StartWhenAvailable=True でも救われないことがある。
診断コマンド(PowerShell)
$t = Get-ScheduledTask -TaskName '<タスク名>'
'LogonType={0} / UserId={1} / RunLevel={2}' -f $t.Principal.LogonType, $t.Principal.UserId, $t.Principal.RunLevel
'StartWhenAvailable={0} / WakeToRun={1}' -f $t.Settings.StartWhenAvailable, $t.Settings.WakeToRun
# 該当日のログオフ/ログオンと再起動を突き合わせる(7002=ログオフ, 7001=ログオン)
Get-WinEvent -FilterHashtable @{LogName='System'; ProviderName='Microsoft-Windows-Winlogon';
StartTime=(Get-Date '<YYYY-MM-DD> 00:00'); EndTime=(Get-Date '<YYYY-MM-DD> 12:00')} |
Sort-Object TimeCreated | ForEach-Object { '{0} | id={1}' -f $_.TimeCreated, $_.Id }
対処の選び方(重要な分岐)
- GUI を必要としないジョブ(API 呼び出し、DB 同期など)→ プリンシパルを 「ユーザーがログオンしていなくても実行する」に変更する。これで根治。
- GUI・実ブラウザ・画面共有・音声を扱うジョブ → 上の変更をしてはいけない。 非対話セッションでは実ブラウザのタブ取得や音声デバイスが機能せず、 「起動はするが無音・無画面で配信される」というより悪い失敗に化ける。 この場合は (a) OS 更新の再起動を業務時間外に固定し自動再起動を抑止する (b) 原則1のチェッカーで「未起動」を検知して人に知らせる、の2段で守る。
つまり 「起動しなかった」を根治できないケースがあると認め、 検知と通知に投資するのが正解。
原則3: 恒久対策の「効果検証」を人間のカレンダーに預けない
「設定を変えた。効いているかは N 日後にログを見れば分かる」——この N 日後は、ほぼ確実に忘れられる。 判定条件をジョブ自身に持たせ、判定日を越えたら1回だけ通知して以後黙る。
例: 「セッションが既定 N 日で失効する」問題に対して無期限化の設定を入れた場合。 効いている証拠は「N 日を越えても生きていること」しか無い。
const DEFAULT_EXPIRY_DAYS = 14; // 対策前に実測した失効日数
const WARN_THRESHOLD_DAYS = 10; // 従来の事前警告の閾値
const state = loadState(); // { baselineEpochMs, verifiedForBaselineEpochMs, lastWarnedDate }
const alive = await probeLive(); // 実物を叩いて確認(推測でなく実測)
const days = Math.floor((Date.now() - state.baselineEpochMs) / 86400000);
// 判定は「いまの対象」に紐付ける。対象が更新されたら自動で判定待ちへ戻る(原則4)
const verified = state.verifiedForBaselineEpochMs === state.baselineEpochMs;
if (!alive) {
notify(`🚨 対象が失効しています。復旧手順: ...`); // 実害はここで即通知
} else if (!verified && days >= DEFAULT_EXPIRY_DAYS) {
state.verifiedForBaselineEpochMs = state.baselineEpochMs;
saveState(state);
notify(`✅ 恒久対策が効いていることを確認しました(${days}日経過 > 既定${DEFAULT_EXPIRY_DAYS}日)。`
+ `以後この経過日数警告は停止します。最終防衛は毎回の実測チェックです。`);
} else if (verified) {
log('確認済み → 経過日数警告はスキップ');
} else if (days >= WARN_THRESHOLD_DAYS && state.lastWarnedDate !== today) {
// ★原則5: 検証中は文面を変える
notify(`⚠️ ${days}日経過。**いま恒久対策の検証中です。実害が出ない限り対象を更新しないでください。**`
+ `ここで更新すると日数がリセットされ、判定(判定日 ${verdictDate})が取れなくなります。`);
state.lastWarnedDate = today;
saveState(state);
}
原則4: 判定フラグは「検証対象の同一性」に紐付ける
verified: true のような素のブール値で持つと、対象を作り直した後も「確認済み」のまま残り、
古い判定が新しい対象を保証してしまう。世代を表す値(epoch、世代ID、ハッシュ)を保存し、
保存値 === 現在値 で判定する。ズレたら自動的に判定待ちへ戻る。
この形にすると、対象を更新する側のコード(上の例では再ログイン処理)を一切改造せずに済む。
原則5: 既存の警告文が、検証そのものを壊すことがある
上の例で最も危険なのは、従来の警告文をそのまま残すことだった。 「切れる前に更新してください」という善意の警告に人が従った瞬間、日数がリセットされ、 判定は永久に取れない。恒久対策を入れたら、既存の警告文が新しい方針と矛盾していないかを必ず見直す。
安全性とのトレードオフは次のように解く:
- 実害が出た瞬間の通知(
!alive側)は残す・弱めない - 予防のための通知(日数ベース)だけ「検証中なので触らないで」に倒す
これで「本当に壊れた時は即座に人が動ける」まま、「検証は壊されない」を両立できる。
検証のやり方(この型を実装したら必ずやる)
分岐がすべて日付依存なので、時間を偽装して全分岐を実走させる。テストのために本番コードへ フラグを足すのではなく、外側から依存を差し替える。
# 依存(状態読み書き・通知)だけ stub し、実測プローブは本物のまま走らせる
node -r ./test-harness.js job.js # harness 側で loadState/saveState/notify を差し替え
// test-harness.js(検証後は削除する)
const lib = require(require('path').join(process.cwd(), 'lib.js'));
const days = Number(process.env.TEST_DAYS);
const fake = { baselineEpochMs: Date.now() - days * 86400000 };
if (process.env.TEST_VERIFIED === '1') fake.verifiedForBaselineEpochMs = fake.baselineEpochMs;
lib.loadState = () => JSON.parse(JSON.stringify(fake));
lib.saveState = (s) => console.log('[STUB SAVE]', JSON.stringify(s)); // 本物の状態を汚さない
lib.notify = async (m) => console.log('[STUB NOTIFY]', m); // 人に通知を飛ばさない
確認する分岐(最低4つ):
| 条件 | 期待 |
|---|---|
| 閾値未満 | 無言 |
| 閾値超・判定日前 | 「検証中なので触らないで」通知 |
| 判定日到達 | 成功通知1回+フラグ保存 |
| 判定済み・さらに経過 | 完全にスキップ |
必ず確認すること: テスト後に本物の状態ファイルが無変更であること、harness を削除したこと。 状態ファイルを実際に書き換えるテストは、翌朝の本番挙動を静かに変える。
チェックリスト
- 成果物の存在で成功判定している(ログの有無に依存していない)
- 「一度も起動しなかった」を検知して通知できる
- GUI 依存ジョブに「未ログオンでも実行」を設定していない
- 恒久対策の効果判定をジョブ自身が持ち、判定日に自動で1回通知する
- 判定フラグが対象の世代に紐付き、対象更新で自動リセットされる
- 検証中の通知文が「人の介入で検証が壊れる」ことを明示している
- 実害通知(即時)は弱めていない
- 全分岐を時間偽装で実走させ、本物の状態を汚していない
よくある質問
+「無人ジョブの沈黙する失敗と効果検証の自動判定」とは何ですか?
定時ジョブが1行もログを残さずスキップされる事故の検知と、恒久対策の効果検証をジョブ自身に判定させる型。Windows Interactive タスクが無人再起動で捨てられる罠、検証を壊す警告文の是正、全分岐の時間偽装テストまで。
+どれくらいトークン(費用)を節約できますか?
ゼロから開発すると約4.2万トークンかかりますが、この巻物を使えば約9,000トークンで済みます。差し引き約3.3万トークン(API料金換算で約50円)・79%の節約です。
+どうやって使いますか?
無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。
+どのAIツールに対応していますか?
claude-code、cursor、codex-cli に対応しています。
+商用利用できますか?
ライセンスは「商用利用可 (再販不可)」です。
🤝 自分でAIを動かすのは、まだ不安…という方へ
この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。
関連する巻物
Google Meet 自動参加&動画配信Bot 開発指示書
指定した時刻に Google Meet へ自動参加し、動画を再生しながら画面共有する Bot を、Claude Code に一発で作らせる開発指示 MD。朝会の定例動画配信・ウェビナーの自動放送に。
受信メール添付を案件フォルダへ自動取込するパイプライン
メールを読むアプリとドライブに書くアプリが別、という現実的な構成で顧客メールの添付を案件フォルダへ無人保存する設計。権限追加を避ける理由、実行時間制限下の予算3本立て、二重の重複防止、base64url/行数上限/変換判定などの実装罠、案件と顧客のマッチング、名寄せは候補提示+人の承認にする型まで。
Gmail 自動仕分け&返信ドラフト生成MD
受信メールを AI が分類 (要返信/情報/営業/スパム) してラベル付けし、要返信メールには返信ドラフトまで自動生成する仕組みを作らせる指示書。DWD (ドメイン全体委任) 設定手順込み。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア