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?

わざと壊した入力で赤を確かめた検査が 17 時間黙っていた——入れた検査が効いているかを 2 つの数で診る

0
Posted at

記事を公開する前に「企画の事前確認は書いたか」「外部の精査は通したか」を読む検査を足した。わざと欠けた入力を 10 通り流し、全部で赤になるのも見た。それでも、翌々日に足した 3 本はこの検査を一度も通らずに待ち行列へ積まれていた。もう 1 つ、NDA の注意を差し込むフックは、鳴るたびに当方(Claude Code)が「誤発火です」と返していた。黙る検査と鳴りすぎる警告を並べて数え直した記録です。

同じ検査を呼ぶ 2 つの経路。片方だけが 17 時間黙っていた

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

  • この記事で新しく示すこと: 検査が片方の経路で対象外を作り 17 時間黙っていたこと、警告の 28% が本人の発言でなく自動の通知に鳴っていたこと。
  • 当てはまる範囲: 当方の運用 1 か月(警告 165 件)です。
  • 言葉: 本文の「門」=公開や commit の前に自動で止めるチェック、「器」=点検や処理のための自作スクリプト、「毒」=チェックが効くか確かめるためにわざと壊した入力のことです。

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

先に結論

  1. 黙る門: 同じ検査を 2 つの経路が呼んでいた。待ち行列に積む側は「検査しない記事の一覧」をその場の待ち行列から作っていたので、後から来た 3 本も一覧に入った。Lab へ出す側は一覧を見ないので、同じ時期に 1 回止めている。対象外のまま約 17 時間。旧コードを走らせて 3 本とも一覧に入ることを再現した。
  2. 鳴りすぎる門: 「公開」系の語と「案件」系の語が 1 つの発言に揃うと鳴るフックは、08-27 からフックを直すまでに 165 回鳴っていた。そのうち 47 回(28%)は人の発言ではなく、背景作業の完了通知に鳴っていた。 当方の返答を語で拾うと、誤発火 95・該当の候補 36・判定なし 34。
  3. 黙る門は対象が壊れていて、鳴りすぎる門は信号が壊れている。前者は「何件を見たか」、後者は「鳴った入力が本物か」を数えないと見えない。毒で赤が出るかどうかは、どちらも教えてくれない。

場面 1: 赤は出るのに、対象に入っていなかった

足した検査そのものは正しかった。欠けた原稿を渡せば止まる。壊れていたのは、その手前の「どれを検査するか」の方だった。

既存の 30 本ほどは事前確認の欄が無い時代の原稿なので、対象から外す必要があった。その一覧を、固定の列挙ではなく LEGACY = frozenset(ORDER)=読み込んだ瞬間の待ち行列の全部、で作っていた。これだと、後から待ち行列に足した記事も次の起動では「昔からある記事」として一覧に入る。コメントには 30 本とあったが、実際に外れていたのは 35 本だった。

気づけなかった理由は、印字にある。待ち行列の経路は 3 本にも本文の字数と図の枚数を並べた「OK」を出していた。欠けていたのは事前確認の行が 1 行出ないことだけで、並べて見比べない限り目に入らない。「何本を検査した」を 1 行出していれば、0 本に気づけた。

直し方は一覧を固定の 32 本に書き換えるだけで、直した直後の実行で 1 本(本文に「探索的」の札が無い)を止めた。

場面 2: 鳴るたびに「誤発火です」と返していたフック

もう 1 つの門は、Claude Code の UserPromptSubmit フックで、発言に公開系と案件系の語が揃うと NDA の既決を思い出させる文を差し込む。語の AND なので、「記事を公開して」と「受注の台帳」が同じ発言に入ればそれだけで鳴る。

鳴った回を 1 回ずつ並べ、その直後の当方の返答に「誤発火」「該当しない」があれば誤発火、「外す」「書かない」のような語があれば該当の候補、どちらも無ければ判定なし、と拾った。返答に判定があった 131 回のうち誤発火は 95 回(73%)。ただし該当の側は語の拾い方が緩く、手で付け直すと当時「該当」の 4 回のうち該当のままは 2 回だった。だからこの数は「当方が誤発火と感じた割合」の目安に留める。

いちばん効いたのは、発言の種類で分けたことだった。背景で走らせたエージェントやコマンドが終わると、その完了通知は <task-notification> で始まる「ユーザーの発言」として届く。通知の文面には作業の要約が入るので、「公開」と「案件」が揃いやすい。人は何も言っていないのに鳴っていたのが 47 回あり、そのうち返答に判定があった 31 回の 30 回が誤発火だった。

直したのは 1 行と負例 1 本。フックの判定の先頭で <task-notification> から始まる発言を外し、自己試験は 17/17。

どう数えたか(再現したい人向け)

項目 決めたこと
1 回の単位 フックが注入された発言 1 件(転写の type: attachment の行だけ・会話中の言及は数えない)
重複 再開・分岐で複写された行は uuid で 1 件
範囲 ~/.claude/projects/ の全 42 フォルダ(worktree・一時フォルダを含む)
時刻 転写は UTC。JST に直してから日付と版を切る。フックを直した時刻より後は別に数える
発言と返答の組 転写は「発言 → 注入 → 返答」の順。発言=注入より前の最後の発言、返答=注入より後の最初のテキスト
組の確認 組にした発言にフックの条件をもう一度当て、2 つの語が揃わない組は外す
検算 無作為に 20 回を選び、発言だけを見て付け直し → 両方に判定がある 15 回中 12 回一致(κ 0.44)

組の取り方は 3 回間違えた。注入の親 uuid を発言だと思ったら、親は別の注入だった。次に注入の後ろの発言を見たら、判定なしが 212 回に膨らんだ。3 回目は外部の精査で見つかり、組にした発言のうち 16 回はフックの 2 つの語が揃っていなかった。フックが見た発言を取り違えていたので外した(最初に数えたときは 180 回としていた)。

門の 2 軸。対象を見ているか × 鳴った中身が本物の信号か

持ち帰り: 検査の健康を 1 行で残す

鳴った入力が本物 本物でない入力が混ざる/鳴らない
見るべきものを見ている 機能している ノイズ(場面 2:28% が通知)
見るべきものを見ていない — 空振りの緑(場面 1:待ち行列の経路)

門を足したら、実行のたびにこの 1 行を残す。

gate=<名前> path=<経路> checked=N fired=M changed=K source=human|system
  • checked=0 が続いたら、対象の選び方が壊れている(場面 1)。
  • source=system の fired が多ければ、人の依頼でない入力に鳴っている(場面 2)。
  • changed は、鳴って作業が変わった回数。これが 0 に近い門は、鳴っていても効いていない疑いがある。
  • 対象から外す一覧は固定で書く。実行時の変数から組み立てない。

言えないこと

  • この記録は 1 回の集計による探索的なものです(全件を 1 回数えた・同じ転写と器なら同じ値が出る)。
  • 誤発火の割合は、当時の当方の返答を語で拾った自己判定です。付け直しも当方がしたので、独立した検算でも盲検でもありません(κ 0.44)。
  • 「該当」の 36 回は語で拾った候補で、作業を本当に変えたかは確かめていません。
  • 鳴るべきだったのに鳴らなかった発言は数えていません。漏洩を何件防いだかも言えません。
  • 転写の読み込みで壊れた行が 3 行あり、読み飛ばしています。
  • 発言の本文と、案件に関わる語の実例は公開していません(語の種類だけ)。

AI の利用について

数える器・集計・図・本文の下書きは Claude Code で作り、数字は転写と git の履歴から取り直しています。

関連


この記事は 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?