fix(ios): give simulator AX bridge captures a tree-bound keyboard fact

Merged
KD
1h ago
+953-4

Summary

Follow-up to #4207. On the default Simulator route (simulator-ax-bridge), a drag that only dismisses the keyboard still waited for the 3.5 s distrust cap and returned a stale-accepted read: bridge captures published no keyboard fact.

The bridge reads the app root like the runner, so the keyboard window is in its tree, and it marks every cut truncated. A bridge capture now publishes a tree-bound fact (observeCompleteTreeKeyboard):

  • a docked keyboard: the docked-tree band (derived);
  • a complete tree with no keyboard window, Keyboard/Key node, or keyboard role: absent;
  • a truncated tree, or a keyboard window without keys (placeholder, assistant bar only): unmeasurable.

Taps do not change. 9 files. I can add an ADR 0004 amendment if wanted.

Validation

  • pnpm check:affected --base upstream/main --run at 05c8da976: passed.
  • Live, base 7d42395ff vs head 4d0176d5f (same code as 05c8da976), iPhone 17 Pro simulator, iOS 26.4, 60 runs, all exit 0:
    • Default route, keyboard dismiss ×15: stale-accept 3701 ms → trust 770 ms (median read), 13 → 3 captures.
    • Default route, no-keyboard control ×10: no-effect on both builds, no false trust.
    • Runner route ×5: unchanged (860 / 877 ms).
  • Not covered live: truncated and window-without-keys branches (unit tests only), physical devices, iPad, other keyboards and runtimes.

AI assistance and human review

AI was used to prepare these changes. Human-reviewed by @kdy1.

  • Harness: T3 Code (Claude Code)
  • Model: claude-opus-5-5

🤖 Generated with Claude Code


Autofix with [code]smith
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.