Summary
Sibling to #1269 / #1272. The #1269 fix (demote a non-unique id from identity) resolves the Android
list-get false-divergence class. It does not address list-presses, which are a distinct
identity gap with the same root spirit (non-selective identity → unstable positional disambiguation) but
no id to demote.
The gap
On Android, a list row's clickable node is a label-less container (role="linearlayout") — the visible
label lives on a child TextView. So a recorded press annotates to a target with no selective
identity at all: role only, no id, label-less ancestry. Measured (wave-3 E1, stripped-id fixture,
step-5 press "Connected devices"):
identity-mismatch, matchCount: 12, recorded={role:linearlayout} observed={role:linearlayout}, mismatches:[]
The 12 same-role containers are disambiguated purely by recorded position; on replay the position drifts
and it binds the wrong row — exactly the #1269 mechanism, but id-demotion is inapplicable because there is
no id.
Why #1272 doesn't cover it
#1272 demotes a non-unique id, falling back to the (selective) label. A press-container has neither a
unique id nor its own label — the label is one level down. So there is nothing for that fix to fall back to.
Fix direction (needs a design call)
Derive the press target's identity from its labeled descendant (or resolve the press to the labeled
node and record identity from there), so a list-row press carries a selective label identity instead of
a bare container role. This is an ADR-0012 identity-construction decision, distinct from #1269's
id-demotion — hence its own issue.
Evidence
Summary
Sibling to #1269 / #1272. The #1269 fix (demote a non-unique
idfrom identity) resolves the Androidlist-get false-divergence class. It does not address list-presses, which are a distinct
identity gap with the same root spirit (non-selective identity → unstable positional disambiguation) but
no id to demote.
The gap
On Android, a list row's clickable node is a label-less container (
role="linearlayout") — the visiblelabel lives on a child
TextView. So a recorded press annotates to a target with no selectiveidentity at all: role only, no id, label-less ancestry. Measured (wave-3 E1, stripped-id fixture,
step-5 press "Connected devices"):
The 12 same-role containers are disambiguated purely by recorded position; on replay the position drifts
and it binds the wrong row — exactly the #1269 mechanism, but id-demotion is inapplicable because there is
no id.
Why #1272 doesn't cover it
#1272 demotes a non-unique
id, falling back to the (selective)label. A press-container has neither aunique id nor its own label — the label is one level down. So there is nothing for that fix to fall back to.
Fix direction (needs a design call)
Derive the press target's identity from its labeled descendant (or resolve the press to the labeled
node and record identity from there), so a list-row press carries a selective
labelidentity instead ofa bare container
role. This is an ADR-0012 identity-construction decision, distinct from #1269'sid-demotion — hence its own issue.
Evidence
~/.agent-device-bench/wave3/E1/), the step-5 presstargetBindingabove. Get class fixed + measured in fix: demote non-unique ids from writer identity/selector chain (#1269) #1272; press class is what remains for Android list flows.