fix(interaction): re-observe a moving @ref in its frame tree's presentation

Merged
OK
13h ago
+94-13

Summary

A press @eN right after a navigation was refused as target_still_moving in ~50 ms although nothing moved, when @eN came from a full (non--i) snapshot. The moving-target gate re-observed every @ref with an interactive-only capture, but a ref names its node by index in the frame tree, so that capture renumbered the target and reconciliation kept the frame node (no measurement, immediate refusal).

Captures now record their typed presentation beside presentationKey, and the gate re-observes in the frame's own interactiveOnly. 6 files.

Found via react-native-pager-view's agent-device 0.21.29 bump: Android material-top-bar.e2e.ts fails 3/3 (also on 0.21.33), passes 3/3 on 0.21.25.

Not covered (already broken before this, not a regression): frames captured with -s/-d/--raw still renumber, because the interaction capture seam only carries interactiveOnly. The iOS tap-outcome code still parses presentationKey. Both are left for follow-ups.

Validation

  • Tested SHA 8c51a6167: pnpm check:affected --run --head HEAD passed, exactCommit=true.
  • New test in moving-target-gate.test.ts fails on base with Ref @e3 had no confirmed resting position, and passes with the fix.
  • Live, Android emulator (API 37), pager-view material-top-bar.e2e.ts: base 0/3 pass, this branch 3/3 pass. The gate re-observed and dispatched (presses took 170-220 ms).
  • CLI repro (back, snapshot, press @e42 on Tab2): refused before the fix, taps after it.
  • Pager-view iOS suite on this branch shows the same results as on main without the change. 2 failures there (taps lost after alert dismiss) exist on main too.
  • Device lanes and coverage run in CI.