3535
3636# --- selector constants (one source of truth for .ad fallback, classifiers, waits) ---
3737readonly SEL_LOGIN_FIELD=' id="username" || role="textfield" label="Phone or email" || label="Phone or email"'
38+ # Mirrors the fill selector in sign-in.ad. Waiting on SEL_LOGIN_FIELD only proves the field exists, and the macro fills it requiring editable=true, so the replay could start against a field that had rendered but was not yet interactive.
39+ readonly SEL_LOGIN_FIELD_EDITABLE=' id="username" editable=true || role="textfield" label="Phone or email" editable=true || label="Phone or email" editable=true'
3840readonly SEL_CONTINUE=' role="button" label="Continue" || label="Continue"'
3941readonly SEL_NAME_FIELD=' label="First name" || label="Full name" || role="textfield"'
4042# Web wait-union markers. Apostrophe-free substrings dodge the straight-vs-curly
@@ -75,12 +77,21 @@ take_snap() {
7577
7678snap_has () { printf ' %s' " $SNAP " | grep -qiF -- " $1 " ; }
7779
80+ # Internal drive output lands here, never stdout — callers may parse stdout as a
81+ # machine protocol, and --settle returns a full settled diff.
82+ drive_log () {
83+ local dir=" ${GITHUB_WORKSPACE:-/ tmp} /artifacts"
84+ mkdir -p " $dir " 2> /dev/null || true
85+ printf ' %s/melvin-drive-%s.log' " $dir " " ${SESSION:- unknown} "
86+ }
87+
7888# Native verb per platform: press on android, click on web.
7989press_label () {
8090 local sel=" role=\" button\" label=\" $1 \" || label=\" $1 \" "
8191 local verb=click
8292 [[ " $PLATFORM " = android ]] && verb=press
83- agent-device " $verb " " $sel " --platform " $PLATFORM " --session " $SESSION " 2> /dev/null || true
93+ agent-device " $verb " " $sel " --settle --platform " $PLATFORM " --session " $SESSION " \
94+ >> " $( drive_log) " 2>&1 || true
8495}
8596
8697# Dismiss splash / runtime permission / ANR overlays that block the login hierarchy.
@@ -166,7 +177,7 @@ wait_for_login_field() {
166177 local budget_secs=" ${MELVIN_LOGIN_WAIT_SECS:- 40} "
167178 mkdir -p " ${GITHUB_WORKSPACE:-/ tmp} /artifacts"
168179 if [[ " $PLATFORM " = web ]]; then
169- agent-device wait " $SEL_LOGIN_FIELD || $WAIT_ONBOARDING " $(( budget_secs * 1000 )) \
180+ agent-device wait " $SEL_LOGIN_FIELD_EDITABLE || $WAIT_ONBOARDING " $(( budget_secs * 1000 )) \
170181 --platform " $PLATFORM " --session " $SESSION " > /dev/null 2>&1 || return 1
171182 take_snap
172183 if snap_login_field; then
@@ -218,8 +229,8 @@ clear_onboarding() {
218229 if snap_has ' "First name"' || snap_has ' "Full name"' \
219230 || snap_has " What's your name?" || snap_has $' What\u2019s your name?' ; then
220231 human " sign-in-drive: onboarding — name MelvinBot (${step} )"
221- agent-device fill " $SEL_NAME_FIELD " ' MelvinBot' \
222- --platform " $PLATFORM " --session " $SESSION " 2> /dev/null || true
232+ agent-device fill " $SEL_NAME_FIELD " ' MelvinBot' --settle \
233+ --platform " $PLATFORM " --session " $SESSION " >> " $( drive_log ) " 2>&1 || true
223234 press_label " Continue"
224235 sleep 1
225236 continue
@@ -301,7 +312,14 @@ drive_sign_in() {
301312 fi
302313 human " sign-in-drive: replay ${sign_in_ad} "
303314 # Replay must share AGENT_DEVICE_STATE_DIR with open (caller exports it).
304- if ! agent-device replay " $sign_in_ad " -e " EMAIL=${email} " --platform " $PLATFORM " --session " $SESSION " ; then
315+ # Keep replay's stderr: it names the diverging step, selector, and repair hint.
316+ mkdir -p " ${GITHUB_WORKSPACE:-/ tmp} /artifacts"
317+ local replay_log=" ${GITHUB_WORKSPACE:-/ tmp} /artifacts/melvin-signin-replay-${SESSION} .log"
318+ if ! agent-device replay " $sign_in_ad " -e " EMAIL=${email} " --platform " $PLATFORM " --session " $SESSION " \
319+ >> " $( drive_log) " 2> " $replay_log " ; then
320+ local replay_err
321+ replay_err=" $( tail -n 5 " $replay_log " 2> /dev/null | tr ' \n' ' ' ) "
322+ [[ -n " $replay_err " ]] && human " sign-in-drive: replay reported: ${replay_err} "
305323 # Already past login (onboarding residual / signup REPLACE) — clear, don't re-fill.
306324 take_snap
307325 if snap_onboarding || snap_has ' "Skip"' ; then
@@ -316,12 +334,16 @@ drive_sign_in() {
316334 # already saw the field. Fall back to direct fill+press.
317335 if snap_login_field; then
318336 human " sign-in-drive: replay wait flaked — direct fill for ${email} "
319- if agent-device fill " $SEL_LOGIN_FIELD " " ${email} " \
320- --platform " $PLATFORM " --session " $SESSION " \
321- && agent-device press " $SEL_CONTINUE " \
322- --platform " $PLATFORM " --session " $SESSION " ; then
337+ local fallback_log=" ${GITHUB_WORKSPACE:-/ tmp} /artifacts/melvin-signin-fallback-${SESSION} .log"
338+ if agent-device fill " $SEL_LOGIN_FIELD " " ${email} " --settle \
339+ --platform " $PLATFORM " --session " $SESSION " > " $fallback_log " 2>&1 \
340+ && agent-device press " $SEL_CONTINUE " --settle \
341+ --platform " $PLATFORM " --session " $SESSION " >> " $fallback_log " 2>&1 ; then
323342 true
324343 else
344+ local fallback_err
345+ fallback_err=" $( tail -n 5 " $fallback_log " 2> /dev/null | tr ' \n' ' ' ) "
346+ [[ -n " $fallback_err " ]] && human " sign-in-drive: fallback fill/press reported: ${fallback_err} "
325347 human " sign-in-drive: direct fill failed for ${email} "
326348 return 1
327349 fi
0 commit comments