Skip to content

wait still refuses an unverified-hittability wrapper chain (native runner path) #2498

Description

@prateekranka

wait still refuses an unverified-hittability wrapper chain

PR #2482 (merged as c94e66e) collapses an unverified-hittability wrapper chain for the action-target resolution only: press/click/fill/longpress, the is target verification, and the post-action settle observation. Issue #2480 was closed by that merge, but its second half is not fixed, so I am opening this to keep it tracked rather than lost.

Symptom (0.21.0 and current main)

A SwiftUI toolbar item that carries an accessibility identifier yields two nodes: the wrapper Other and the Button under it, with no hittability evidence and rects ~0.7-1 pt apart.

$ agent-device press 'id="scoring_home_button"' --settle
Error (AMBIGUOUS_MATCH): Selector matched 2 distinct actionable elements: id="scoring_home_button"
Candidates: @e3 [other] "Home"  @e4 [button] "Home"        <- fixed by #2482

$ agent-device wait 'id="scoring_home_button"' 3000
Error (AMBIGUOUS_MATCH): selector matched multiple elements
Diagnostics Log: .../runner.log                            <- still fails

Observed screen state in both cases: scoring_home_button -> Other [20,63,36,36] + Button [21,63,35,36].

Why it is a separate path

wait does not run the action-target resolution. src/daemon/wait-runtime.ts builds its own selector runtime:

src/daemon/wait-runtime.ts:46   await bindWaitOperations(params, parsed, session, device)
src/daemon/wait-runtime.ts:156  const runtime = createSelectorRuntimeForDevice({ ... })

classifyActionableTouchCandidates is reached only from src/commands/interaction/runtime/selector-action-resolution.ts (called by resolution.ts), which wait never imports. On iOS the refusal surfaces from the native runner, which does not use the shared structural-equivalence rules:

  • apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+CommandExecution.swift:1683
  • apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/RunnerTests+Interaction.swift:238

Options

  1. Delegate: have the runner hand its multi-match decision to the shared equivalence rules, so the selector layer and the runner cannot drift.
  2. Mirror: re-implement the wrapper-chain rule inside the runner.

Option 1 is preferable: the two layers disagree today, and mirroring guarantees a future divergence.

Verification

A device lane is required: an iOS simulator run of press + wait against one toolbar control, with the same screen state recorded on both sides. I can prepare the patch and run that lane if you pick a shape.

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions