Repository navigation
fix(ios-runner): stop wide sliders from wedging tree snapshots - #3776
Conversation
A wide native slider qualifies for the collapsed tab fallback, which read every live descendant of the app one attribute at a time on the XCTest main thread. The tree-processing slice cannot cancel those reads, so a crowded screen or a sheet with sliders kept the runner busy until it reported wedged. Match candidates inside one XCTest query with a predicate that applies the fallback's own content, type and geometry rules and copies each match's attributes as XCTest evaluates it. Start that query only while the time left in the processing slice covers what the capture's root tree read took; when it cannot start, the tree tier reports a deadline-exhausted, truncated capture so the plan can use the next backend. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The code looks sound at 4c9e5ed, but the PR is missing one live run. The runner unit suite calls recursiveTreeSnapshotAcquisition directly with a hand-picked processingDeadline, so it skips the plan wiring this PR adds: the processingSlice/processingDeadline calculation, runMainThreadWork, and the mapping of the tier outcome in RunnerTests+SnapshotCapturePlan.swift. The Duo run used the production route, but it was built from v0.21.28 plus the patch, not from this head. No run shows a collapsed tab bar, which is the case in the PR title and #277. So nothing yet shows that the daemon snapshot at this head adopts collapsed items, or that it recovers from the not-started branch without RUNNER_BUSY. Please build from this head ( Not blocking, take or leave: (a) querySweepCanStartQuery now also gates the collapsed-tab query through expectedCost, so a neutral name such as xctestQueryCanStart would fit better (RunnerTests+Snapshot.swift); (b) The Swift runner suites are not shown as CI results, and the checks list is empty for this head, so there is no failing job to attribute. I did not build or run the Swift suites, so the claims about in-process predicate evaluation on iOS 27 and the new tests failing on the base rest on your report. Before merge, please post the live iOS daemon snapshot at 4c9e5ed on a collapsed tab, segmented control or slider screen, showing the adopted children and no RUNNER_BUSY. |
The collapsed tab query now shares the check with the query sweep, so the name no longer belongs to the sweep alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The slider sat at y=800, below the iPhone Duo inner display, so a live snapshot there left it out. Above the crowded rows it is on screen on an iPhone and on the inner display, and it still covers no row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ot start A stub slows the plan's root tree read so the processing slice left for the collapsed tab query is shorter than the read. The plan must reject the truncated tree with the budget reason instead of accepting it as healthy. Reverting the tree tier's outcome in the plan fails it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks for the review. Head is now Live run at the head. I built with 5 of 5 {"index":3,"parentIndex":2,"type":"Slider","label":"Volume","rect":{"x":20,"y":20,"width":360,"height":31}}
{"index":4,"parentIndex":3,"type":"Button","label":"Left"}
{"index":5,"parentIndex":3,"type":"StaticText","label":"Left"}
{"index":6,"parentIndex":3,"type":"Button","label":"Right"}
{"index":7,"parentIndex":3,"type":"StaticText","label":"Right"}
Non-blocking points
Also: the crowded-screen test, adapted to main's signatures, fails on |
|
I read the code at 58872fc and found no remaining problems. The findings from the earlier review at 4c9e5ed are fixed. Nothing from that review remains open. No checks are reported for this head, because the fork's CI runs need maintainer approval. There is no failing job to attribute, and the Swift runner suites do not run as PR CI results. There are no conflicts. I did not build or run the Swift runner suites. That the new plan test passes, that it goes red under the .completed mutation, and that the crowded-screen test fails on a0ad15b rests on reading the code and on your report. The new plan test also assumes the first XCUIApplication snapshotWithError call is the tree tier's root read. Its delayed assertion shows the stub fired, but not on which call. The live Duo run at 58872fc is your report (JSON excerpt and log greps), and I did not reproduce it. It covers the wide-slider fixture, not a real React Native collapsed tab bar, and the PR body now says so. Before merge, a maintainer needs to approve the fork CI run, and the PR needs to leave draft. |
|
@gwdp pushed The raw XCTest tree already exposes Left/Right as siblings of Volume. The regular capture was adding copies beneath the slider while keeping the originals. The follow-up excludes Validation at
The exploratory measurements support your performance fix: 513 nodes acquired in 0.14 s, versus 4.56 s for only the first 20 elements using the old exists/type/frame read pattern. That was a bounded sample, not a fresh full I also tried test-app with RN 0.88.0-rc.0 and |
|
This PR is ready at 95238dc. The issue from the earlier review at 58872fc is fixed, and I found no new problems in the code. Not blocking: the new collapsed-tab-bar test checks only the outcome and truncation, so it does not prove the 'First tab' and 'Second tab' items are adopted (the fixture sets isAccessibilityElement=YES, so the candidate query may return nothing). You can take or leave asserting the adopted tab item nodes under the tab bar, if the fixture exposes them. CI is green: 11 checks, none failing. The Swift runner suites do not run as PR CI, so CI does not cover the changed runner route. I did not build or run those suites myself. The live pass on iPhone 17 / iOS 26.2 at 95238dc and the check:affected receipt run-FHHaHO come from your report. There is no daemon-level I know of no conflicts. Before merge, the PR must leave draft, and a maintainer must approve the fork CI run. |
…ment * origin/main: fix(ios-runner): stop wide sliders from wedging tree snapshots (#3776)
…me-no-process-globals * origin/main: fix(ios-runner): stop wide sliders from wedging tree snapshots (#3776)
|
Thanks @thymikee |
…lider fix agent-device folds only inside a session, so on EAS the app now opens before the fold, as it does on a local simulator. Its fold then fails to read the hinge back, so the display is the check instead: agent-device's screenshot must be in the pose's shape and drawn (not one flat colour). The first fold of a fresh session can light a black panel, as it does for Argent; the capture then restarts SpringBoard, reopens the app and folds again, once, and otherwise fails with CONTROLLER_READER_STUCK. agent-device 0.21.28 wedged its iOS runner on @expo/ui sliders on a regular-width display (an opened iPhone Duo or an iPad): every read of euxy's lane editor failed. callstack/agent-device#3776 fixes it; it is not in a stable release yet, so agent-device is pinned to 0.21.29-nightly.20261018.74, which captured the opened Duo 16 of 16 on EAS. doctor reports Argent's single appearance only for an Android EAS session: on an iOS EAS session (simulator:control appearance.set) and on this Mac the host switches it. solidColour moves to shared/png-evidence, for the display check.
…oth controllers (#9) Capture iPhone Duo on EAS Simulator with eas simulator:control, for both controllers - eas-cli 25.2.0: app.approveUrlScheme after install, appearance.set for Argent on iOS EAS sessions, and springboard.restart as the last fold recovery step. The controller's own tools come first; these only fill what neither controller has. - iPhone Duo on EAS: both controllers' folds are verified (Argent by its tree, agent-device by its screenshot) and recovered by restarting SpringBoard and folding again, once; never by stopping the session's tool-server. - agent-device opens the app before folding on EAS, as it does locally. - agent-device pinned to 0.21.29-nightly.20261018.74 for callstack/agent-device#3776, which stops @expo/ui sliders on a regular-width display from wedging its runner. - A session EAS fails to start is replaced, up to five times within 30 minutes, with a growing wait, only when the failure is provably EAS's. - doctor warns about Argent's single appearance only for Android EAS sessions.
Summary
The collapsed-tab fallback from #287 (#277) could read hundreds of live XCTest elements one attribute at a time and wedge the runner on crowded screens.
Candidate attributes are now collected during one XCTest query per capture. Query admission uses the remaining processing slice and the root-read duration; an unstarted query reports
deadlineExhaustedto the capture plan.Ordinary sliders are excluded from recovery: overlapping sibling buttons must not become duplicated slider children. Recovery remains available for childless tab bars and segmented controls. The fixtures cover slider sibling preservation and tab-bar query deadlines. Seven files changed; no test-app dependency added.
Validation
Head
95238dc3f6; maintainer reproduction and results:pnpm check:affected --run --head 95238dc3f65a81599ddcd8108269869ae7858d28passed,exactCommit: true, receiptrun-FHHaHO.The earlier crowded-screen regression failed on base
a0ad15bc7(author-reported 398.2 s). A maintainer reproduction at58872fc7fmeasured 0.14 s for 513 nodes; the slider sibling assertions failed before eligibility was narrowed and passed afterward.CI-owned native/replay checks were skipped locally. #277's exact React Native case remains unreproduced. Query admission estimates cost; it cannot cancel an admitted XCTest query.
Authorship and LLM use
Original implementation primarily LLM-generated by Claude Code, directed and reviewed by Gabe. Codex-assisted maintainer follow-up narrows slider eligibility and updates tests.
Rollback
Revert the PR.