0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AI に任せるときの見張りは 2 つ要る——沈黙は経過時間で表面化し、前面は奪わず・奪われたら戻し・人の操作は奪い返さない

0
Posted at

エージェントに 20 分の作業を投げて、別の作業をしていた。完了通知は来ない。出力ファイルを覗くと 0 B のまま。止まっているのか、まだ走っているのか、どちらも分からない。

もう 1 つ。AI に自分の PC のアプリを操作させていて、様子を見ようとウィンドウをクリックした瞬間、0.1 秒で画面が奪い返された。奪い返したのは、当方が「前面を奪われたら戻す」ために置いた見張りでした。

この 2 つは別の見張りの話で、どちらも「気をつける」では立ちませんでした。見張り 25 本の記録と、実機 3 セッションで数えた記録から、どこに何を立てるかを書きます。

止まったときの見張り

この記事の位置づけ(2026-09-26 追記)

  • この記事で新しく示すこと: 見張り 25 本の記録と、前面を奪い返す条件を 3 つにした状態機械(入力の直後に奪い返した 9/9)。
  • 当てはまる範囲: Windows・当方の PC・実機 3 セッションです。
  • 言葉: 本文の「器」=点検や処理のための自作スクリプト、「番人」=見張りのスクリプトのことです。

数字の元データと再現の手順は、検証の記録(Lab)にまとめています。

止まったとき: 完了は届くが、沈黙は届かない

Claude Code のエージェントは完了すると通知が来ます。来ないときに「まだ走っている」と「止まった」を区別する合図は、こちらには何も届きません。出力ファイルのサイズも更新時刻も試しましたが、この運用では 10 本とも 0 B のままで、mtime は作業中も動かなかった。中身を覗いて進捗を測る案は捨てました。

追加実装なしで使えた最低コストの合図は経過時間です。エージェントを起動したのと同じターンで、背景に 1 本立てる。

sleep 1200; echo "[見張り] watchdog:<agent>-<日時>: 起動から 20 分たっても完了通知が無い"

猶予を過ぎると、この echo が「完了通知」として届き、沈黙が破れます。完了通知が先に来たら TaskStop で見張りを止める。自分でエージェントを止めたときも、見張りを止める。対にするのが要点で、対にしなかった 1 回が誤報になりました。

見張り 25 本で何が起きたか

09-09〜10 の 3 セッションの転写から、見張りの起動・TaskStop・鳴った通知を機械で拾いました。

面 何を数えたか 数
沈黙 見張りの起動 26 本=試験 1(60 秒・鳴った)+エージェント向け 25
沈黙 エージェント向け 25 本の結果 完了が先で猶予内に止めた 16/転写から直接確認できた鳴動 0(記憶には誤報 1 の記帳)/特定できない 9
沈黙 止めたときの猶予までの残り秒(16 本) 最小 8・中央値 525・最大 994

止めた 16 本のうち 1 本は残り 8 秒。あと 8 秒遅ければ、完了しているのに「止まった」と鳴っていた。猶予 20 分は所要の最長実測 19:15 の 45 秒上で、運用上の暫定値です。

9 本は転写から結果を特定できませんでした。通知の形が一定でなく、見張りに ID が無かったので、どの通知がどの見張りか対応づけられない。⟹ 見張りに watchdog:<agent>-<日時> の ID を付ける、が改善点で、率(16/25)で語ることはしません。

動いているとき: 前面は奪われる

実機の操作は PostMessage の背景経路で送っていて、その経路自体は前面化しません。それでも作業中に相手のアプリが前面に出る遷移が起きた(引き金は未特定)。「奪わない」だけでは足りず、「奪われたら戻す」番人を器を呼んだ時点で自動で立てるようにしました(札で 1 本・寿命 90 秒)。戻す条件は 2 つ、「印(機械が操作中)が 5 秒以内」AND「相手が前面」。

動いているときの番人

見張りが、人のクリックを 0.1 秒で奪い返す

外部の精査で「機械操作 → 2 秒後に人がクリック → 番人が奪い返す」逆転を指摘されました。印は新しい、相手は前面、2 条件とも真。番人から見れば「戻す」場面です。

本当に起きるかを実機 3 セッション(各約 330 秒)で数えました。(a) 機械が 90 秒操作する(3 秒ごとに背景送出・印を打つ・当方は触らない)→ (b) 「人の入力」の代用として、印の直後に SendInput で Alt を 1 打してから相手を前面にする(3 回)→ (c) 印を 20 秒古くして同じ前面化(2 回・陰性対照)。観測器は前面を動かさず、0.1 秒ごとに前面プロセス・印の鮮度・最後の入力イベントを記録。番人は現行の 2 条件のまま。

面 何を数えたか 数
前面 実機 3 セッション(現行の 2 条件の番人) A 奪われた(印が新しい)9/B 2 秒以内に戻った 9/C 入力の直後なのに戻した 9(0.1〜0.2 秒)/D 戻らず 0/E 印が古いのに前面 3 → 戻した 0
前面 番人自身のログ「戻した回数」 3・3・3=観測器の B と一致
前面 機械操作中(270 秒)に相手が自分から前面を奪った回数 0
前面 3 条件の判定(純関数) 自己テスト 6/6

入力イベントの直後の前面化を 9 回すべて奪い返した。印が古いときは 3 回とも戻さなかった(番人は正しく動いている=条件が足りないだけ)。機械操作中に相手が自発的に前面を奪うことは 270 秒で 0 回でした。

3 つ目の条件と、それでも見分けられないもの

戻す条件に「機械操作の後に新しい入力イベントが観測されていない」(GetLastInputInfo の時刻が印より前)を足すと、上の 9 回は全部「戻さない」になります。判定は純関数にして、逆転事故の型を含む 6 例で自己テストしました(3 つ目を外すとその例が「戻す」に転ぶ)。本物の番人への実装はまだで、この記事で言えるのは「2 条件では逆転する」を数で確かめたところまでです。

限界も 2 つ。GetLastInputInfo は SendInput 由来のイベントも数えるので、代用が成り立つ代わりに「人の入力」を厳密に見分ける手はこの合図には無い。印(ファイルの mtime)と dwTime(tick)は別の時計なので、同じ軸に揃えるか、曖昧なら「戻さない」側へ倒す。

もう 1 つ、器を回す側の「前面化 OK/NG」の印字は当てにならなかった。SetForegroundWindow の直後に番人が 0.1 秒で戻すので GetForegroundWindow が相手でなく「NG」と出る。数えたのは観測器の CSV で、番人自身のログと突き合わせて 3・3・3 が一致したことを根拠にしています。

見張りの設計表(5 行 × 2 列)

止まったとき 動いているとき
合図 経過時間 印(鮮度 5 秒)+相手が前面+機械操作の後に入力イベントが無い
立て方 起動と同じターン・1 体 1 本・ID 付きの背景 sleep N 器を呼んだ時点で自動(札で 1 本)
止め方 完了が先なら TaskStop/自分で止めたら見張りも止める 寿命 90 秒(器を呼ぶたびに延びる)
誤報の型 止め忘れ 人が自分で見にきた(印が古い/入力が後)
検出しないもの 本体・端末・PC ごとの停止/猶予の中の停止 引き金の特定/同じ PC の外

経過時間が示すのは「N 分以内に完了しなかった」だけで、生存確認ではありません。端末や PC ごと止まった場合は見張り自体が鳴らない。

AI の利用について

見張りの集計は AI(Claude Code)が自分の転写を機械で数えたもので、実機 3 セッションも AI が器を回して観測しています。観測器・純関数・図・この下書きも AI 製。相手のアプリ名・案件名・機種は伏せています。

関連


Sumitsuke は、AI や外注で作ったものの点検と修理、業務自動化、検証を受託しています。AI に任せた作業が「止まった」「奪った」を数で検収する設計は → https://sumitsuke.jp/works/verification/


この記事は Zenn にも同じ内容を掲載しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?