Skip to content

test(thread): read fresh accessibility bounds in the newer-pagination emulator test - #3613

Merged
stamp-build[bot] merged 1 commit into
mainfrom
agent/lagoon/fix-newer-pagination-flake
Oct 23, 2026
Merged

stamp-build[bot] merged 1 commit into
mainfrom
agent/lagoon/fix-newer-pagination-flake

Conversation

@stamp-build

@stamp-build stamp-build Bot commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Lagoon from raft opened this pull request through Stamp
View in Stamp →


The emulator test thread-newer-auto-pagination failed at random in the "Android first-character baseline (emulator)" job with Timed out waiting for stable retained message AUTO-MSG-0008. This happened three times today: runs 39939224593 and 39951797674, plus one earlier run. A rerun always passed. This PR fixes the test harness. The product code is not changed.

Root cause

The test reads message positions through UiAutomation, which answers from its accessibility cache. Compose clears that cache only through throttled content-change events. Right after the first toward-newer swipe, cached rows can still report where they were before the swipe. On a local emulator, a fresh read put AUTO-MSG-0011..0013 at y=341/554/946, while the cache still had them at y=1629/2021/2413, overlapping the rows that had scrolled in.

The test picks its "retained anchor" from those reads. In local runs of the unchanged test, the anchor it picked jumped between AUTO-MSG-0008, 0009, 0010 and 0014 for the same scroll. It picked 0008 once locally, the same row as in the CI failures. 0008 is the focused row that the swipe had already scrolled away. The test then compared stale bounds with stale bounds. It passed while the cache stayed stale, and timed out when the page append refreshed the cache and 0008 was no longer in the window. The product kept its anchor: the restore logs show the newer-page settlement restoring the pointer-settled anchor every time.

This is not a scroll/settle race and not a timing wait that depends on emulator speed. It also does not come from #3578 or #3555. The fixture's realtime catch-up is a no-op, and the failure is in the harness's reads. The CI history I could pull (test.yml runs from 10-22 18:00 through today) shows this test passing in all but two of the roughly 27 full runs that included it. #3192 already reported it as flaky on 10-20, before either PR.

Fix

  • Message markers are collected in one walk of the window. The walk calls AccessibilityNodeInfo.refresh() on every node and drops nodes that no longer exist, so bounds are never served from the stale cache.
  • The retained anchor is the topmost marker that sits fully inside the list viewport. A clipped marker has its top pinned to the viewport edge, which hides displacement.
  • The Retry and Back-to-bottom nodes are refreshed before their bounds are used.
  • The two stable-anchor waits report the latest sample, the visible markers and the accessibility tree when they time out.

The waits stay bounded monotonic polls. No timeout was raised and no retry was added. There is no deterministic hook here because the property under test is the on-screen position, and only the accessibility tree reports it to the test process.

Verification

Local runs, on an API 35 emulator limited to 2 host cores with one busy loop on those cores:

Full CI (test.yml, scope=full) on head 2aaccf0 has been dispatched three times: on this branch and on two extra refs with the same commit, because the workflow cancels earlier runs on the same ref. Results will follow in a comment.

No changeset, because this change only touches a test.

🤖 Generated with Claude Code

… emulator test

RaftThreadNewerAutoPaginationConnectedTest read message markers through
UiAutomation's accessibility cache. Compose only invalidates that cache through
throttled content-change events, so right after the first toward-newer swipe
cached rows can still report their pre-swipe bounds: a local run read
AUTO-MSG-0011..0013 at their old positions (y=1629/2021/2413) while a fresh
read had them at y=341/554/946. The test then picked a stale row as the
"retained" anchor. On CI that was AUTO-MSG-0008, the focused row that the
swipe had already scrolled away. Once the append refreshed the cache, the row
was gone for good, and the test timed out with "Timed out waiting for stable
retained message AUTO-MSG-0008". The product kept its anchor; the harness was
measuring the old frame.

- Markers are collected in one walk of the window that calls
  AccessibilityNodeInfo.refresh() on every node and drops nodes that no
  longer exist.
- The retained anchor is the topmost marker fully inside the list viewport.
  A clipped marker has its top pinned to the viewport edge, which hides
  displacement.
- The Retry and Back-to-bottom nodes are refreshed before their bounds are
  used.
- The stable-anchor waits report the latest sample, the visible markers and
  the accessibility tree when they time out.

Signed-off-by: Lagoon <raft+lagoon@agents.stamp.build>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@stamp-build

stamp-build Bot commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Verification results for head 2aaccf0, rebased onto main with #3605 and #3602.

CI, full test.yml: thread-newer-auto-pagination passed in every run where the emulator suite ran.

  • 6 of 6 passed with this change. Runs 39968433652, 39968741589 and 39968750143 were on the pre-rebase commit a9f2915. Runs 39982731725, 39982737911 and 39990199373 are on 2aaccf0. In run 39990199373 the anchor was AUTO-MSG-0011 at its live position, fully inside the list (top 456).
  • Run 39982721749 is not counted. Its emulator jobs failed before the emulator booted ("Error on ZipFile unknown archive" while preparing the system image), so the suite never started. Stamp would not rerun it because a newer run existed on the branch, so I dispatched 39990199373 instead.
  • Before this change: of the roughly 27 full runs since 10-22 18:00 that ran the test, 2 failed with the AUTO-MSG-0008 timeout (39939224593 and 39951797674). feat(cmp): big switch — whole app UI from Kuikly to Compose Multiplatform #3192 also reported it flaky (2/3) on 10-20.

Local, API 35 emulator on 2 pinned cores:

  • Unchanged test: 15 of 15 passed, but the anchor it read jumped between rows 8, 9, 10 and 14 for the same swipe. Those reads came from the stale accessibility cache.
  • This change: 15 of 15 passed on the old base and 10 of 10 on the rebased head. The anchor was always a fully visible row (10, 11 or 12) at its live position.

Lagoon commented through Stamp · server raft · head when posted 2aaccf0
View in Stamp →

@stamp-build
stamp-build Bot merged commit 40045d8 into main Oct 23, 2026
45 of 48 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.

0 participants