Repository navigation
Keep Linux controls readable when their positions stall - #31982
Conversation
📝 Walkthrough
Priority: ➖ Normal Merge Risk: 🟡 Moderate · up to
|
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
- Source mode: Auto
- Repository: Unavailable
- Branch: Unavailable
- File: No configuration file from this repository applied
- Commit: Unavailable
- Layers: Repository UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
7d8dbad7-57fa-460c-b5c1-cdda25f97ef0
📒 Files selected for processing: 2
native/computer-use-linux/runtime.pynative/computer-use-linux/runtime_render_test.py
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.
|
Linux inspection could lose an otherwise readable control tree when child position reads stalled until the 30-second bridge deadline. This change collects semantics first and treats descendant positions as bounded optional enrichment. Controls and supported semantic actions remain available with missing frames; requested screenshots and responsive positions remain available. The full review loop is complete on Real Linux QA used Ubuntu 24.04, PyGObject 3.48.2, libatspi 2.52.0 and GTK 3.24.41, the exact CI AppImage and Orca's actual paired RPC route. The main-provider comparison used the supported provider override in the same packaged server; it was not a full main package. Final restart used the unmodified packaged branch provider.
A frameless semantic click through paired RPC changed durable state exactly once (count 1→2) and returned the changed tree in 3.319s. Two GTK windows, name/PID selectors, requested screenshots, password redaction, blocked-app behavior, restoration and state carried through real target/server restarts passed. After restart, stalled inspection retained 68 controls in 3.318s, then healthy recovery took 0.311s. All owned processes exited, the Linux light-job gate is free, real config hashes match, and the remote rig is removed. Limits and separate issues:
For Brennan's review The Flutter main/head captures are byte-identical; both labels below intentionally use the same uploaded image. GTK main/head images show the same retained previous-build text, masked password and successful coordinate count. Initial occluded GTK captures were excluded.
Branch second GTK window: Three review points: native-call timeout restoration, preserved window-identification allowance, and fresh root, semantics, screenshot, then optional child positions. |




Problem
Linux computer inspection can time out after 30 seconds on a Flutter app even though its controls are readable. The provider reads every control's position while collecting its semantic information, so stalled native position reads can consume the whole request. Tracked in STA-11477.
User-facing change
Inspection returns readable controls and supported actions when child positions stall. Unavailable positions become null frames; they do not mark the readable tree truncated. Requested screenshots and responsive positions remain available. The same observation path runs after an action, preserving the fresh result without replaying the input.
Mechanism
Resolve the app/window and read fresh window bounds after any restoration, using the existing native allowance. Standard window roles do not need position reads to establish their identity; other roles retain the existing positive-bounds predicate and timeout. Collect the semantic tree, focus, selection and metadata, then capture the requested screenshot.
Only then start a fresh three-second phase for emitted controls' positions. Each native component/extent read gets at most 800ms, skips when less than 50ms remains, disables startup grace for that call, and restores the 800ms/15s baseline in finally. Associate native nodes with exact record objects through browser compaction. Reuse the selected root rectangle; keep no discovery or restoration rectangle cache.
Intended differences and limits
Review and validation
Two review rounds and a three-seat architecture ruling corrected five initial regressions: semantic work exhausting the position budget, slow nonstandard windows being rejected, benign protected-name labels blocking an app, stale bounds after restoration, and incorrect frames after browser compaction. A fresh full review passed, followed by a narrow check of the final main merge at 4dae758.
All 17 targeted Python tests pass. Independent main/original/final probes verify the five corrections; these use simulated native boundaries and do not prove installed-library timing. The scoped diff is 72 changed production lines and 173 changed test lines; the larger test harness pins the incident and confirmed regressions.
Final-head CI passed, including static analysis/typecheck, all five test shards, relay integration, packaging and native smoke. A dedicated performance/resource scan found no proven introduced issue. Final real Linux QA passed on Ubuntu 24.04 with PyGObject 3.48.2, libatspi 2.52.0 and GTK 3.24.41, using the exact packaged final-head runtime through Orca's paired RPC route.
The inspection change does not fix required root/semantic stalls or coordinate-input timeouts. A three-second descendant-position budget is not a whole-request deadline.
The existing duplicate browser action-index issue is tracked separately in STA-11731. Real GTK set-value fails identically on main and this head because the installed GI Accessible lacks
is_editable_text; this unchanged baseline issue is tracked in STA-2596, assigned to Brennan with fresh native evidence. Neither text nor numeric set-value success is claimed. Per the review lane ruling, set-value acceptance for this PR is main parity; the separate defect remains open.The unchanged internal frame-origin inconsistency when root bounds are unavailable is tracked in STA-11781. Current action consumers reread live positions or safely refuse; the automated thread was resolved after an independent exact-main/head trace.
Visual QA
Main GTK after coordinate input:
Branch GTK after the same input and previous-build state:
Flutter Gallery (main/head byte-identical):