Skip to content

fix(computer-use): #823 Windows の V1 の UI Automation で、値を返した遅い成功を時間切れにしない - #824

Merged
yusei531642 merged 1 commit into
mainfrom
fix/823-slow-success-timeout
Oct 17, 2026
Merged

yusei531642 merged 1 commit into
mainfrom
fix/823-slow-success-timeout

Conversation

@yusei531642

Copy link
Copy Markdown
Collaborator

何を変えたか

  • WindowsV1UiaTimed(computer_use_windows_host.cc)で、遅い成功(読み取りは 270 ms 以上、最初の接触は 470 ms 以上)を時間切れとして扱うのは、呼び出しの出力が空のときだけにしました。値を返した遅い成功は成功です。
  • 空かどうかの判定は WindowsV1UiaEmpty で、型ごとに 1 つです。
    • 要素、pattern、walker の移動の結果、SAFEARRAY: null
    • BSTR: null または長さ 0
    • RECT: すべて 0
    • 値の型(BOOL / int / enum): 0。値の型には「空」が無いので、0 を空として扱います。0 が正しい答えでもありうるもの(空の名前、子なし、最後の兄弟、IsPassword の FALSE、ToggleState_Off、ExpandCollapseState_Collapsed)は、遅ければ従来どおり時間切れです(fail closed)。特に、IsPassword の遅い FALSE を「password ではない」とは読みません。
    • toggle と expand の状態は、呼び出し前の初期値が Indeterminate / LeafNode です。何も書かずに切れた呼び出しは初期値を残しますが、呼び出し元がこの値を semantic_state_unavailable で拒否します。
  • 最初の接触(ElementFromHandle / ElementFromPoint / GetFocusedElement)は例外で、遅ければ要素を返しても時間切れのままです([bug] Computer Use Windows: V1 のレーンの UI Automation にタイムアウトが無く、応答しない対象でレーンが止まりうる (#500 S5-c-2 R8) #820 の規則のまま)。ローカルの live seam で、答えなくなった provider の窓への ElementFromHandle が 1026 ms かかったうえで S_OK と要素を返しました(UI Automation が HWND から要素を作るためです)。これを成功として扱うと、その後の呼び出しが続き、observe が 2.5 s かかりました。
  • すべてのラッパー呼び出しは、その呼び出しが書く出力を名指しで渡します。source 契約で次の 2 点を数えます: ラップされた UIA 呼び出しが全数と一致すること(38 == 38)、渡す出力がその呼び出しの書く変数であること。
  • live seam の 1 ケースあたりの上限を 950 ms にしました。内訳は Connection 500 + Transaction 300 + 余裕 150 で、host の定数から求めます。1 s の Cancel 確認未満であることは、static_assert と契約で固定しました。PR feat(computer-use): #785 T15-4w Windows の native で対象ノードの値を読む(能力は false のまま)、J12、アーカイブ済み Task の開始拒否 #822 の CI(2026-10-17)で、Connection と Transaction の連鎖が 844 ms で実際に起き、旧上限(Connection + 200 = 700 ms)で失敗したためです。
  • host のコメントと、ADR の [bug] Computer Use Windows: V1 のレーンの UI Automation にタイムアウトが無く、応答しない対象でレーンが止まりうる (#500 S5-c-2 R8) #820 の段落を更新しました。連鎖は CI で観測済みで、そのときの 1 s 確認までの余裕は約 156 ms でした。

なぜ

応答している app でも、負荷が高いと 1 回の呼び出しが閾値を超えることがあります。#821 の規則ではその時点で経路全体が打ち切られ、target_unclassified で拒否されていました(PR #821 の CI の deep tree ケース)。時間切れの読み取りが残すのは空の値なので、空の値の遅い成功だけを時間切れとします。

どう確かめたか(ローカル Windows、MSVC 2022)

  • npx tsc --noEmit -p . は成功、npx prettier --check も成功
  • node build-computer-use-native.mjs(vcvars64)は成功
  • computer-use-windows-v1-uia-timeout-live-seam.test.ts: 契約 6 件はすべて PASS。新しく足した決定的な SeamCheck もすべて PASS(遅い値あり → 成功で経路が続く/遅い空 → 時間切れで経路が終わる/遅い FALSE → 時間切れ/遅い TRUE → 成功/要素を返した遅い接触 → 時間切れ)
    • live の 1 ケースは、このマシンでは FAIL のままです: the_first_call_of_a_new_process_reads_an_ordinary_window と ReadUiaObservation@provider-answers-0(1027 ms)。ただし、変更前の main(cc59e6a0)でも同じ 2 件が同じように失敗することを確かめました。環境に依存する既存の失敗で、CI の結果で確かめます。
  • RED 確認 1: 中心の規則を戻して、遅い成功を常に時間切れにしました。この状態では、新しいケースのうち 4 件(a_slow_read_with_a_value_is_a_success_and_the_path_lives、a_slow_value_type_read_with_a_value_is_a_success、a_slow_move_with_an_element_is_a_success、a_slow_true_is_an_answer)と契約が FAIL しました。その後、元に戻しました。
  • RED 確認 2: 接触の例外を外すと、a_slow_contact_with_an_element_is_still_a_timeout が FAIL し、provider-answers-0 の observe は 2537 ms になりました。その後、元に戻しました。
  • host.cc を読むほかの test 21 ファイルを実行しました: 20 passed、1 skipped(input-seam は既定で skip)、297 tests passed。

Refs #823

🤖 Generated with Claude Code

…にしない

#820(PR #821)の規則 4 は、270 ms(最初の接触は 470 ms)以上かかって成功した呼び出しを一律に
時間切れとしていた。応答している app でも負荷が高いと 1 回の呼び出しがこの値を超えることがあり、
経路全体が打ち切られて target_unclassified で拒否されていた(PR #821 の CI の deep tree)。

- WindowsV1UiaTimed は、呼び出しが書く出力そのものを受け取り、遅い成功を時間切れとするのは
  出力が空のとき(WindowsV1UiaEmpty)だけにする。空の形は型ごとに 1 つ: 要素・pattern・
  SAFEARRAY は null、BSTR は null か長さ 0、RECT はすべて 0、値の型(BOOL / int / enum)は 0。
  0 が正しい答えでもありうるもの(空の名前、子なし、FALSE、ToggleState_Off など)は、遅ければ
  従来どおり時間切れ(fail closed。IsPassword の遅い FALSE を「password ではない」と読まない)。
- 最初の接触(ElementFromHandle / ElementFromPoint / GetFocusedElement)は例外で、遅ければ
  要素を返しても時間切れのまま。UI Automation は provider が切れても HWND から要素を作るため
  (ローカルの live seam で 1026 ms・S_OK・要素ありを観測。成功扱いにすると observe が 2.5 s に
  延びた)。
- すべての UIA 呼び出しの呼び出し元が出力を名指しすることを source 契約で数える
  (ラップ済み 38 == 全 38、渡す出力がその呼び出しの書く変数であること)。
- live seam の C++ に、窓を使わない決定的なケースを足した: 閾値を超えて眠り S_OK と値を返す
  呼び出しは成功で経路が続き、空を返す呼び出し(空の BSTR、null の要素、FALSE)と要素を返した
  遅い最初の接触は時間切れで経路を終える。
- live seam の 1 ケースの上限を、数えた 1 回の最悪値(Connection 500 + Transaction 300)と
  余裕 150 ms の 950 ms にした(host の定数から求め、1 s の Cancel 確認未満を static_assert と
  契約で固定)。PR #822 の CI で連鎖が 844 ms で実際に起きて、旧上限(700 ms)で失敗したため。
- host のコメントと ADR の #820 の段落を更新した。

Refs #823

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sprintreviewer

sprintreviewer Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

🗺️ PR Walkthrough

Note

UI Automation の遅い成功を出力値で判定し、空の値だけを時間切れとして扱うよう変更しました。最初の接触は要素を返しても時間切れを維持し、ライブ seam の上限を 950 ms に更新しています。

Changed files (3)
File Summary
apps/desktop/computer-use-native/computer_use_windows_host.cc 各 UIA 呼び出しが書き込む出力値をタイムアウト判定に渡すよう変更。値の型別に空を判定し、遅くても値がある読み取りは成功、空の遅い読み取りと遅い最初の接触は時間切れにします。
apps/desktop/src/main/computer-use-windows-v1-uia-timeout-live-seam.test.ts 値のある遅い成功、空の遅い成功、遅い FALSE、遅い最初の接触を確認する seam ケースと、全 UIA 呼び出しのラッパーおよび出力対応の契約を追加。上限を 950 ms とし、1 秒未満であることも確認します。
tasks/designs/adr-computer-use-agent-driven-v2.md タイムアウトの規則、CI で観測した Connection と Transaction の連鎖、出力値による判定、950 ms の seam 上限を ADR に反映。

Reviewed by vibe-editor-reviewer — head a21c09b

@sprintreviewer sprintreviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Code review

Tip

LGTM — actionable issues were not found.

確認内容

  • ✅ 変更箇所と関連するコード経路を確認
  • ✅ 独立した差分レビュー(Claude)を確認

レビュー所感

固定 HEAD を確認し、遅い成功の出力判定、分類・操作への伝播、取消し、リソース解放と関連テストを精査しました。静的確認では、この変更が導入する重大な不具合は確認できませんでした。実行による検証は行っていません。

🛡️ blockingな指摘はありません。bot側の安全設定により、merge-relevantなAPPROVEではなくCOMMENTとして投稿します。

Review coverage & tooling
  • Files: 3 reviewed (+257 / -95)
  • Full file bodies included: 0 / 3
  • Reviewer roles: numeric_consistency (deterministic), codex_deep (gpt-6.1-sol), claude_peer (claude-opus-5-5, fixed-diff only, partial)

Reviewed by vibe-editor-reviewer — head a21c09b

@yusei531642
yusei531642 merged commit 4b7b02f into main Oct 17, 2026
39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant