Skip to content

v0.41.0

Choose a tag to compare

@Kewton Kewton released this 25 Sep 01:26
· 19 commits to main since this release
dc8cc1a

[0.41.0] - 2026-09-25

Highlight: エージェントが返答の本文でダイアログの文面を引用すると、入力待ちなのに「ダイアログが開いている」と表示され、選択リストのカードや Pick ボタンが出ていた問題を、codex・antigravity・Command Code・Claude の 4 ツールで直しました(「画面の一番下が入力欄ならダイアログは開いていない」を判定の入口に置く)。antigravity の Auto-Yes は引用されたダイアログに答えなくなり、さらに hook の問い合わせで裏付けが取れない承認ダイアログにも答えません。あわせて、画面の判定と hook の報告の食い違いをサーバーログに記録するようにし、codex のキャプチャ 55 件の判定を表で固定しました。サイドバーのセッション表示の並び替えも、選んだ順番どおりになりました。

Added

  • feat(polling): antigravity の Auto-Yes が、直前に hook の問い合わせを受けていない承認ダイアログに答えないようにする (#2849): agy は全ツール呼び出しの前に PreToolUse を CommandMate へ問い合わせ、その応答を待ってから承認ダイアログを描くため、実在のダイアログの直前には必ず POST /api/hooks/permission-request が届いている。返答本文に引用されただけのダイアログにはそれが無い。#2845 / #2851 の画面側の判定とは独立の二重の守りとして、POST /api/hooks/permission-request が antigravity の問い合わせを <worktreeId>:<cliToolId>:<instanceId> ごとに 1 件(ツール名と受信時刻)だけ短命に記録し(polling/antigravity-permission-receipts.ts。permissionHookPredictsDialog の値や応答の内容によらず記録する)、detectPromptOnCleanFrame は新しい任意引数 receiptScope(worktree と instance)を受け取ったとき、antigravity で isPrompt: true になる 2 つの出口(agy 専用リーダの直後と、末尾の共通 detectPrompt の直後)の両方で、直近 8 秒以内にそのインスタンスの問い合わせが無ければ isPrompt: false を返す。画面にツール名は出ないので照合は時刻だけ。receiptScope を渡さない呼び出し(状態 API・response poller の prompt 行・通知)は従来どおり関門なしで、hook が届かない環境でも実在のダイアログは人間に見える。

  • feat(detection): 画面が「ダイアログが開いている」と読んだのに hook はターン終了と言っているとき、サーバーログに記録する (#2843): 画面判定の誤りは、これまで利用者が誤表示に気付くまで分からなかった。承認や質問のダイアログは必ずターンの途中に出るので、画面の判定が waiting で hook の最新イベントが stop なら、画面の読み違いか、利用者がターン後に開いたメニューのどちらかである。hook がターンの開始と終了を届けるツール(claude・codex・copilot・gemini・opencode)について、これを approval-after-stop(承認。ターン終了後には起こり得ないので検出器の誤り)と menu-after-stop(選択リスト。仕分けが要る)に分け、セッション・ターン・種類ごとに 1 回、画面の末尾 40 行つきで [layer-disagreement] layerDisagreement として記録する。antigravity と Command Code は hook がターンの開始を届けず、途中のダイアログまで誤って記録してしまうため対象外。判定そのものは変えない。

  • test(detection): codex の画面キャプチャ全件の判定を 1 つの表で固定し、codex 更新時の確認手順を追加 (#2842): tests/ にある codex のキャプチャ 55 件を、撮ったままと stripAnsi 後の 2 通りで判定し、status/reason を表と照合するテスト(codex-verdict-corpus.test.ts)を追加した。表に無いキャプチャを足すとテストが落ちるので、表が実態から遅れない。CODEX_PROBE_DIR を指定すると、新しい codex で撮った 6 画面(アイドル・処理中・承認・/model・trust・承認文面を引用した返答)を同じ判定で確かめられる。手順は docs/design/codex-detection-corpus.md。

Fixed

  • fix(polling): antigravity の Auto-Yes が、直前に hook の問い合わせを受けていないダイアログに答えないようにし、答えなかったことをサーバーログに残す (#2857): #2849 の受信記録の関門は detectPromptOnCleanFrame の任意引数 receiptScope を渡した呼び出しにだけ働くが、実際に画面を読んで答える Auto-Yes(detectAndRespondToPrompt)は渡しておらず、関門は効いていなかった。Auto-Yes の呼び出しにだけ { worktreeId, instanceId } を渡すよう配線した(状態 API・response poller の prompt 行・通知は従来どおり関門なしで、実在のダイアログは人間に見え続ける)。これにより、ツール呼び出しではなく hook が届かない /feedback のカテゴリ選択のような利用者が自分で開いたメニューと、~/.gemini/config/hooks.json の向き先が別サーバ(#2622)で受信記録が付かない環境の承認ダイアログには、Auto-Yes が答えなくなる(誤って答えるより止まる側)。理由が分からないまま止まらないよう、答えなかったときは info ログ antigravity-autoyes-withheld-no-hook-receipt(worktreeId / instanceId / windowMs / hint)を、同じインスタンスにつき 60 秒に 1 回まで出す。画面に何も出ていないとき・返答本文に引用されただけのダイアログ・受信記録があって答えたときには出さない。

  • fix(polling): antigravity の Auto-Yes が、返答本文に引用された確認ダイアログに自動で答えないようにする (#2851): #2845 は状態判定(detectSessionStatus)と agy 専用のダイアログリーダを直したが、Auto-Yes の入口 detectPromptOnCleanFrame は関数末尾の共通の detectPrompt を通り、返答に引用された Do you want to proceed? と 4 択を multiple_choice の prompt と読んでいた(antigravity の Auto-Yes のダイアログ関門は legacy で、この後に判定し直す層が無い)。agy は番号つきの選択画面を入力欄の代わりか下に描き、上には描かないため、状態判定側が isStalePrompt に登録している「番号つき選択肢の最終行より下に入力欄がある候補は引用」の判定(isAntigravityQuotedNumberedList)を、この入口でも antigravity に限って適用し、isPrompt: false を返す。実機の承認ダイアログ(dialog-*.txt)と、番号つきの行が入力欄より下にある /feedback のカテゴリ選択は従来どおり prompt のまま。

  • fix(detection): 返答が選択画面のフッタ文言を引用しただけの idle 画面を、claude が選択リスト(waiting)と読む問題を修正 (#2847): tools/claude/detect.ts の afterPrompt は末尾 15 行のどこかに Enter to select … to navigate などの文言があれば claude_selection_list と判定しており、返答の本文が picker のフッタを引用した idle 画面(入力欄に下書きあり・claude 2.1.278 の実機採取)が waiting / claude_selection_list になっていた。フッタは画面の部品の側(入力欄の位置、または入力欄と入れ替わる選択画面)にあり、入力欄より上は会話の本文なので、findClaudeTranscriptTail / readIdleEvidence と同じ findClaudeInputBox で入力欄が見つかる画面では、フッタの判定を入力欄の上端以降の行(従来の末尾 15 行の内側)だけに当てる。入力欄が無い画面(/model など、選択画面が入力欄と入れ替わっている画面)は従来どおり末尾 15 行を読むので、実機の選択画面・承認画面の判定は変わらない(prompt_detected は共有の prompt 検出が先に決めるためこの変更の手前)。

  • fix(detection): Command Code の返答が画面のフッタ文言を引用すると、選択リスト・パネル・プラン確認が開いていると誤表示される問題を修正 (#2846): commandCodeStatusDetector が /model ピッカーのフッタ・/usage パネルの Press Esc to close・プラン確認の Approve ctrl+a / Cancel esc を、末尾 15 行のどこかに一致すれば「開いている」と読んでいたため、返答がそれらを引用すると(画面の一番下は入力欄で待っているのに)waiting / command_code_selection_list・command_code_dismissable_panel・command_code_plan_review と表示されていた(答えられるプロンプトではないので Auto-Yes は動かないが、チャットのカードとサイドバーが誤る)。3 つとも「フッタが画面の下端にあるときだけ」一致するようにした — ピッカーとパネルは空行を除いた最後の 1 行、プラン確認は下端の 5 行(フッタの 2 行 + ヒントバーなど 3 行。実機のプラン確認は Cancel esc の下にヒントバーを 1〜3 行描くので最後の 2 行では足りず、入力欄は最短で 4 行なので引用の下には必ずそれ以上ある)。Command Code の実機の画面 100 枚は、修正の前後で判定が変わらない。

  • fix(detection): antigravity の返答が確認ダイアログの文面を引用しただけで waiting と判定される問題を修正 (#2845): agy は確認ダイアログを開いている間は入力欄(>)を描かない(ダイアログが入力欄と入れ替わる)。ところが locateAntigravityDialogRegion は最後の ↑/↓ Navigate 行を無条件に開いているダイアログのフッタとみなし、tools/antigravity/detect.ts の分岐 0.9 も末尾 15 行に文言があるだけで通していたため、返答に Do you want to proceed?・番号つきの選択肢・フッタを引用させた画面が、入力欄で待っているのに waiting / prompt_detected になり、Auto-Yes が使う detectAntigravityNumberedDialogPrompt も 4 択の prompt を返していた。フッタより下に入力欄(promptPattern)が描かれていればそのフッタは開いているダイアログのものではないとして、フッタ位置の特定・分岐 0.9・共通パーサの番号つき選択肢(入力欄より上にあるもの)のいずれでも「ダイアログなし」に扱う(isAntigravitySurveyOpen と同じ判定)。実機のダイアログ・ピッカー・信頼確認・スラッシュポップアップの各画面の判定は変わらない。

  • fix(detection): codex の会話本文に引用されたダイアログを、開いているダイアログと誤判定しない (#2841): codex がダイアログの文面(Press enter to confirm … や › 1. Yes、ページャのフッタなど)を返答の本文で引用すると、ターンが終わって入力欄で待っているのに waiting / codex_selection_list と判定され、チャット欄に選択リストのカードと Pick のボタンが出ていた。codex はダイアログを開いている間は入力欄を描かないので、「画面の一番下が入力欄ならダイアログは開いていない」を isCodexComposerAtBottom にまとめ、状態判定(分岐 0.6 を新設し 0.7〜0.85 の前に置く)・共通のプロンプト判定(isStalePrompt)・Auto-Yes と respond の判定(detectDialog)すべての入口で使うようにした。リポジトリの codex キャプチャ 55 件の判定は変わらない。

  • fix(sidebar): セッション表示の並び替えが選んだ順番どおりにならない問題を修正 (#2838): sortSessionRows が並び順にかかわらずステータス(waiting → ready → running → generating → idle)を最優先で比べていたため、「リポジトリ名 A→Z」でも alpha が末尾に回り、ready ⇄ running の遷移のたびに行が上下へ跳んでいた。ブランチ表示の sortBranches()(#1787)と同じく先頭固定を waiting だけにし、それ以外は選んだ並び順で並べる(「ステータス」ソートは従来どおり)。あわせて行の時刻を worktree の updated_at からインスタンスごとの最終メッセージ時刻に変更(GET /api/worktrees の lastActivityByInstance、?includeStatus=0 でも返す。instance_id IS NULL の旧メッセージは主インスタンスに数える)し、同じ worktree の claude と codex も「新しい順」で実際に最近動いた方が上に来るようにした。