Skip to content

Spike: targeted AX invalidation after AX-free gestures (escape hatch for baseline-distrust cap) #1560

Closed as not planned

Description

@thymikee

Follow-up to #1542 defect 2's approved fix (baseline-comparison distrust in post-gesture stabilization). The v1 fix accepts the result when the bounded distrust cap expires with the signature still matching the pre-gesture baseline — correct for genuine no-op gestures, but it leaves one theoretical hole (a tree that is stale AND partially different reads as settled) and pays a small latency tax on no-op gestures.

Spike question (runner-side, iOS): does a cheap, targeted AX re-resolution hook exist (public or via the private-AX surface the runner already uses for bulk snapshots) that forces the next snapshot query to bypass the cached tree after an AX-free synthesized gesture?

Constraints from history: forced FULL re-resolution on deep RN trees can cost seconds (the #758 sparse-tree/depth-ladder arc and the recurring slow-AX deferrals) — an unconditional post-gesture resync would be a worse agent experience than the bounded cap. The hook is only worth wiring if it is (a) targeted/cheap on complex trees, (b) stable across OS versions. If found, its integration point is the cap-expiry branch of the baseline-distrust logic (replace "accept possibly-stale" with "force one fresh read"), not a new unconditional step.

Deliverable: measurement-backed GO/NO-GO with per-tree-size timings on the test-app + a Bluesky-class deep screen; implement only after sign-off.

Generated by Claude Code

Activity

  1. thymikee commented on Aug 3, 2026

    @thymikee
    MemberAuthor

    Spike verdict: NO-GO

    Investigated via XCUIAutomation.framework disassembly (Xcode 26.2) + live pixel-vs-tree measurement (iPhone 17 Pro / iOS 26.2, test-app + Bluesky Following feed via Metro).

    There is no stale cached tree on the runner's snapshot path to invalidate. element.snapshot() resolves the query (the only cache-eligible step — XCUISnapshotGenerationTracker gates which element handle, not tree data) then performs a live AX fetch of tree contents on every call. The generation cache is invalidated by a CFRunLoopObserver on every main-runloop entry, so its window is far shorter than one stabilization poll.

    Deep screens harden the NO-GO from two directions: on a 147-node Bluesky feed the XCTest tier is already penalized/deferred and the private-ax backend serves instead — which calls the AX server directly and never touches the XCUIAutomation cache, so an invalidation hook would be a no-op precisely where it was proposed. And one forced fresh read there costs ~2.9s warm (23s cold) — worse than the bounded distrust cap it would replace. The private-ax bridge is also simulator-only (#if os(iOS) && targetEnvironment(simulator)), so it could never serve device-side.

    Live staleness controls found no staleness anywhere: working scrolls move pixels and tree together with no lag (test-app and Bluesky); an inert gesture pan left the tree "frozen" at pre-gesture values — and the screenshot confirmed the screen genuinely had not moved. The tree was accurate; the gesture was a no-op.

    Consequence beyond this spike: the checkout-form step-11 failure attributed to "stale-but-fast AX" (defect 2 in #1542/#1559) reproduced with evidence pointing to a genuinely inert scroll, not stale observation — the pixel-vs-tree adjudication has been handed to the in-flight fix workstream before it ships an observation-side fix for what may be a gesture-efficacy defect.

    Invalidation hooks do exist for the record (writable XCUIApplication.generation, XCUIElement.lastSnapshot, or forcing a runloop entry) — they are simply not needed, and were this ever revisited, the integration point remains the cap-expiry branch only.

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions