fix: record step durations, and pin the foreground app before matching text

Two defects found by running spotify_play against the real phone.

- Step durations were always zero in the run log: executeStep returned a copy,
  so the deferred assignment never reached the caller (FR-10). It now returns a
  named value, with a regression test.
- The phone was sitting on the Android Settings app, and wait "Search" was
  satisfied by Settings' own "Search Settings" entry, so the recipe tapped the
  Settings search bar. New "foreground" step waits until the recipe's app really
  is in front; spotify_play uses it right after launch.

docs/phase-3-spotify-recipe.md now logs all six live attempts and states
plainly that the end-to-end playback run has not completed: the phone is
showing a Settings "Verify that it's you" biometric prompt, which needs Sam and
is left untouched.
This commit is contained in:
2026-10-16 13:29:07 +11:00
parent 2604fea483
commit 767844cacc
5 changed files with 124 additions and 22 deletions

View File

@@ -29,6 +29,7 @@
// Steps are "- " lines, run in order:
//
// - launch start the recipe's app
// - foreground 30s wait until the recipe's app is in front
// - wait "Search" 30s wait for an element whose text matches
// - wait_gone "Recents" 30s wait until no element matches the text
// - tap "Search" tap the element whose text matches (FR-4)
@@ -105,17 +106,18 @@ var verbs = map[string]struct {
durArg bool // the single argument is a duration
allowExact bool
}{
"launch": {0, 1, false, false},
"wait": {1, 2, false, true},
"wait_gone": {1, 2, false, true},
"tap": {1, 2, false, true},
"tap_if": {1, 1, false, true},
"tap_row": {1, 2, false, true},
"type": {1, 1, false, false},
"key": {1, 1, false, false},
"back": {0, 0, false, false},
"home": {0, 0, false, false},
"sleep": {1, 1, true, false},
"launch": {0, 1, false, false},
"foreground": {0, 1, false, false},
"wait": {1, 2, false, true},
"wait_gone": {1, 2, false, true},
"tap": {1, 2, false, true},
"tap_if": {1, 1, false, true},
"tap_row": {1, 2, false, true},
"type": {1, 1, false, false},
"key": {1, 1, false, false},
"back": {0, 0, false, false},
"home": {0, 0, false, false},
"sleep": {1, 1, true, false},
}
// keyNames are the key event names a recipe may use.